Qt / C++ - accès à MainWindow UI d'une classe différente

je suis un débutant de C++ et Qt, donc peut-être que c'est trivial. Je pense que ça devrait être simple, mais je cherche une réponse depuis quelques heures et je n'arrive pas à trouver la solution. Je suis en train de faire un jeu de société simple où l'interface utilisateur de MainWindow (réalisée en QtDesigner) contient une toile pour le jeu de société (un QGraphicsView). Maintenant, le principal.le rpc est très simple:

MainWindow Game;

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);

 Game.show();

return a.exec();
}

depuis que j'ai besoin d'accéder et d'éditer les Widgets MainWindow à partir d'un autre totalement sans rapport j'ai pensé que le plus simple serait de faire de MainWindow une variable globale. Il semble que cette approche était très erronée. En essayant d'exécuter le projet dans QtDesigner je reçois une erreur de bibliothèque visuelle C++ runtime de Microsoft: l'application a demandé runtime pour le terminer d'une manière inhabituelle.

alors quelle est la bonne façon de faire ce dont j'ai besoin?

a part le MainWindow j'ai un dialogue pour un nouveau jeu (QDialog, généré par QtDesigner) qui est affiché après avoir cliqué sur un élément de menu dans MainWindow. Lorsque l'utilisateur entre tous les paramètres du jeu et clique sur OK dans la boîte de dialogue, J'instancie une classe personnalisée Non-Qt appelée GameState. Cette classe est destinée à faire fonctionner le jeu lui-même, à dessiner la carte, à inviter l'utilisateur, etc. Cependant, comme cette classe est créée dans le QDialog, elle ne connaît pas l'existence d'un MainWindow et donc je ne peux rien faire avec le MainWindow de cette classe. Comment puis-je modifier le MainWindow d'une autre classe, alors?

aussi, jsut comment fonctionne la fonction setEnabled ()? Il ne semble jamais à faire quoi que ce soit. Tout widget que j'ai défini comme désactivé dans le QtDesigner et ensuite essayer d'activer à travers cette fonction reste toujours désactivé dans l'interface graphique...

15
demandé sur user742925 2011-05-07 14:41:04

6 réponses

tout d'Abord c'est une mauvaise idée de créer MainGame avant de créer votre QApplication objet. Si vous voulez avoir votre MainGame objet disponible dans le monde entier comme cela, il doit être un pointeur:

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;
}

cette approche n'est cependant pas la plus élégante. Il y a deux choix bien meilleurs.

  1. QApplication l'objet stocke en fait toutes les fenêtres de haut niveau comme votre MainGame ce qui signifie que vous pouvez toujours acquérir par QApplication::topLevelWidgets() qui est une fonction statique et retourne une liste avec tous les widgets de haut niveau. Puisque vous n'avez qu'un, le premier est votre MainGame. L'inconvénient est que vous devrez le lancer, mais en utilisant Qts qobject_cast<MainGame*>(...) est assez sûr. Vous aurez à vérifier le résultat cependant pour s'assurer qu'il n'est pas un pointeur NULL.

  2. utilisez le motif singelton. Vous devez stocker le pointeur de jeu global dans le fichier source (cpp) de la classe de jeu elle-même (sous-classe QMainWindow) et votre classe de jeu devrait implémenter un public statique méthode qui renvoie ce pointeur global. Donc si une autre classe a besoin de Game un pointeur, il appelle tout simplement:

    MyGame *theGame = MyGame::getInstance();
    

    par exemple.

Concernant votre setEnabled() problème. Veuillez afficher le code correspondant. Si c'est trop hésitez pas à m'envoyer l' *.fichier ui et le morceau de code par courrier.

cordialement

D

10
répondu Dariusz Scharsig 2011-05-08 14:45:48

la façon la plus facile de faire ceci est d'abord de configurer un signal dans le fichier d'en-tête de votre autre classe pour dire effectuer une fonction pour manipuler un objet dans la classe principale comme ceci

signals:
    void disableLoadButtton();

puis créer une fente sous les fentes privées dans le fichier d'en-tête de la fenêtre principale comme ceci

private slots:
     void disableLoadButtton();

puis créer la fonction comme une fonction de membres dans la fenêtre principale pour manipuler l'objet

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

puis Ajouter la ligne suivante dans un autre membre de la fonction la fenêtre principale qui dit configure la page. Mon autre classe s'appelle searchWidget

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

alors tout ce que vous avez à faire pour désactiver le loadButton (qui est un objet dans MainWindow) est d'ajouter la ligne suivante dans n'importe quelle fonction members de mon autre classe searchWidget

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

ceci manipulera alors le loadButton de l'objet dans le mainwindow à partir d'une fonction de membre de l'autre classe searchWidget.

6
répondu Tom 2014-11-20 23:42:37

Si votre application n'a qu'une seule fenêtre, vous pouvez simplement utiliser:

MainWindow * win = (MainWindow *) qApp::activeWindow();
5
répondu Alex Reche Martinez 2011-05-07 14:11:19

si vous devez accéder à votre MainWindow à partir d'une autre fenêtre, vous le faites probablement mal. L'utilisation d'une autre classe pour transmettre des informations avec des signaux/fentes est probablement une bien meilleure approche

4
répondu Ignacius 2011-05-07 18:55:16

je suis en train de faire de cette façon:

QMainWindow* getMainWindow()
{
    foreach (QWidget *w, qApp->topLevelWidgets())
        if (QMainWindow* mainWin = qobject_cast<QMainWindow*>(w))
            return mainWin;
    return nullptr;
}
3
répondu Flot2011 2017-09-27 19:55:33

j'utilise cette approche dans Qtractor projet:

main.c

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.rpc

#include <QString>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "c.h"

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 <QMainWindow>
#include <QString>
#include <QPushButton>

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