QT / C ++ – Accesso all’interfaccia utente di MainWindow da una class diversa

Sono un principiante sia per C ++ che per Qt, quindi forse questo è banale. Sembra certamente che dovrebbe essere semplice, ma ho cercato una risposta per qualche ora e non sono riuscito a trovare la soluzione. Sto facendo un semplice gioco da tavolo in cui l’interfaccia utente di MainWindow (realizzata in QtDesigner) contiene una canvas per il tabellone (una QGraphicsView). Ora, main.cpp è il più semplice ansible:

MainWindow Game; int main(int argc, char *argv[]) { QApplication a(argc, argv); Game.show(); return a.exec(); } 

Dal momento che ho bisogno di accedere e modificare i widget MainWindow da un’altra class totalmente indipendente, ho pensato che il modo più semplice sarebbe semplicemente rendere MainWindow una variabile globale. Sembra che questo approccio fosse molto sbagliato, però. Nel tentativo di eseguire il progetto in QtDesigner ottengo un errore di libreria di runtime Microsoft Visual C ++: l’applicazione ha richiesto al runtime di terminarlo in un modo insolito.

Allora, qual è il modo corretto di fare ciò di cui ho bisogno?

A parte il MainWindow ho una finestra di dialogo per un nuovo gioco (QDialog, generato da QtDesigner) che viene visualizzato dopo aver fatto clic su una voce di menu in MainWindow. Quando l’utente inserisce tutti i parametri per il gioco e fa clic su OK nella finestra di dialogo, istanzio una class non-Qt personalizzata chiamata GameState. Questa class è pensata per far funzionare il gioco stesso, disegnare il tabellone, richiedere all’utente, ecc. Tuttavia, poiché questa class è creata nel QDialog, non sa dell’esistenza di una finestra principale e quindi non posso fare nulla con la finestra principale. da questa class Come posso modificare MainWindow da una class non correlata, quindi?

Inoltre, jsut come funziona la funzione setEnabled ()? Non sembra mai fare nulla. Qualsiasi widget che ho impostato come disabilitato in QtDesigner e poi cerco di abilitare attraverso questa funzione rimane comunque disabilitato nella GUI …

Innanzitutto è una ctriggers idea creare MainGame prima di creare l’object QApplication . Se vuoi che il tuo object MainGame globalmente disponibile come questo dovrebbe essere un puntatore:

 MainWindow *Game; int main (int argc, char **argv) { QApplication a (argc, argv); Game = new MainWindow(); Game->show(); int result = a.exec(); delete Game; Game = NULL; return result; } 

Questo approccio non è tuttavia il più elegante. Ci sono due scelte molto migliori.

  1. L’object QApplication memorizza in realtà tutte le windows di primo livello come il tuo MainGame che significa che puoi sempre acquisirlo tramite QApplication::topLevelWidgets() che è una funzione statica e restituisce un elenco con tutti i widget di primo livello. Dal momento che ne hai solo uno, il primo è il tuo MainGame . L’inconveniente è che dovrai lanciarlo, ma l’uso di Qts qobject_cast(...) è abbastanza sicuro. Dovrai controllare il risultato per assicurarti che non sia un puntatore NULL.

  2. Usa il modello di design di Singelton. Dovresti memorizzare il puntatore del gioco globale nel file sorgente (cpp) della class Game stessa (sottoclass QMainWindow ) e la tua class Game dovrebbe implementare un metodo pubblico statico che restituisca questo puntatore globale. Quindi se qualsiasi altra class ha bisogno del puntatore del Game , chiama semplicemente:

     MyGame *theGame = MyGame::getInstance(); 

    per esempio.

Per quanto riguarda il problema setEnabled() . Si prega di inviare il codice pertinente. Se è troppo sentitevi liberi di inviarmi il file * .ui e il pezzo di codice via mail.

I migliori saluti
D

Se la tua applicazione ha una sola finestra puoi semplicemente usare:

 MainWindow * win = (MainWindow *) qApp::activeWindow(); 

Il modo più semplice per farlo è impostare prima un segnale nel file di intestazione dell’altra class per dire eseguire una funzione per manipolare un object nella class principale come questo

 signals: void disableLoadButtton(); 

Quindi creare uno slot sotto le windows private nel file di intestazione della finestra principale come questo

 private slots: void disableLoadButtton(); 

Quindi creare la funzione come funzione dei membri nella finestra principale per manipolare l’object

 void MainWindow::disableLoadButton() { ui->loadButton->setenabled(false); } 

Quindi aggiungi la seguente riga in un’altra funzione membro della finestra principale che dice imposta la pagina. La mia altra class è chiamata searchWidget

 void MainWindow::setUpPage() { connect(searchWidget, SIGNAL(disableLoadButton()), this, SLOT(disableLoadButton())); } 

Quindi tutto ciò che devi fare per disabilitare il loadButton (che è un object in MainWindow) è aggiungere la seguente riga in qualsiasi funzione membro della mia altra searchmap di class

 void searchWidget::performSomething() { emit disableLoadButton(); } 

Questo manipolerà quindi l’object loadButton nella finestra principale all’interno di una funzione membro dell’altra searchmap della class.

Se devi accedere alla tua MainWindow da un’altra finestra, probabilmente stai sbagliando. Usare un’altra class per passare informazioni con segnali / slot è probabilmente un approccio molto migliore

Lo sto facendo in questo modo:

 QMainWindow* getMainWindow() { foreach (QWidget *w, qApp->topLevelWidgets()) if (QMainWindow* mainWin = qobject_cast(w)) return mainWin; return nullptr; } 

Io uso questo approccio trovato nel progetto Qtractor :

main.c

 #include "mainwindow.h" #include  int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 

mainwindow.cpp

 #include  #include "mainwindow.h" #include "ui_mainwindow.h" #include "ch" MainWindow * MainWindow::pMainWindow = nullptr; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); pMainWindow = this; setCentralWidget(&m_pb); connect(&m_pb, SIGNAL(clicked()), this, SLOT(on_pb_clicked())); } MainWindow::~MainWindow() {delete ui;} // kind of singleton reference. MainWindow *MainWindow::getMainWinPtr() { return pMainWindow; } void MainWindow::pbSetText() { m_pb.setText(QString{"Call from c."}); } void MainWindow::on_pb_clicked() { c C; // call of MainWindow from class c ctor } 

mainwindow.h

 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include  #include  #include  namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); static MainWindow * getMainWinPtr(); void pbSetText(); public slots: void on_pb_clicked(); private: static MainWindow * pMainWindow; Ui::MainWindow *ui; QPushButton m_pb{QString{"Press me."}, this}; }; #endif // MAINWINDOW_H 

c.cpp

 #include "ch" #include "mainwindow.h" c::c() { MainWindow * mw = MainWindow::getMainWinPtr(); mw->pbSetText(); } 

ch

 #ifndef C_H #define C_H class c { public: explicit c(); }; #endif // C_H