代码之家  ›  专栏  ›  技术社区  ›  philm

qt库qObject::Connect:无法连接(空)::finished()到mainwindow::updategui()错误

  •  0
  • philm  · 技术社区  · 6 年前

    我目前正在学习Qt库,因为这似乎是一个流行的C++ GUI库。以前,我使用wxwidgets,在某些方面,我很喜欢。但我发现qt在功能上给了我更多的选择,并且在某些方面与wxwidgets类似。

    无论如何,我得到了一个奇怪的错误(这是本文的标题),代码无法连接到我的插槽。起初,我以为我是在说我的位置不对。然后,发现其中一个qpushbutton对象正在干扰信号。

    我有一个连续的动画对象,我在其中取两个按钮,让它们淡出,然后调整窗口的大小。但是,出现此错误时,所有动画都不起作用。直到我注释掉qpushbutton对象。奇怪的是这个对象还没有被分配空间!对象是一个指针,我没有用new声明它,我得到了这个错误。

    代码很简单,我将在这里发布.h和.cpp文件。我还将标记错误发生的位置以及给我问题的对象的位置:

    这是.h文件

    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
        QSequentialAnimationGroup *p_group;
    
    //    QParallelAnimationGroup *p_parallelGroup;
    
        QPushButton *p_button; 
    
        QPushButton *p_anotherButton;
    
        QPushButton *p_backButton; // This is the object that when commented out, removes the error
    
        QPushButton *p_nextButton;
    
        QPushButton *p_finishButton;
    
        QPropertyAnimation *p_sizeAnimation;
    
        QPropertyAnimation *p_fadeOut;
    
        QGraphicsOpacityEffect *p_opacityEffect;
    
     //   QPushButton *p_backButton;
    
        systemState p_GUIState;
    
    
    
        void changeGUIState(systemState nextState);
    
     private slots:
        void handleButton();
    
        void hideOpenButton();
    
        void hideNewButton();
    
        void hideBackButton();
    
        void hideFinishButton();
    
        void updateGUI();
    };
    

    下面是.cpp文件中的代码:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        QHBoxLayout *startingLayout = new QHBoxLayout();
        this->centralWidget()->setLayout(startingLayout);
    
        this->statusBar()->setSizeGripEnabled(false);
    
        this->statusBar()->setWindowTitle("Simulator");
    
        p_button = new QPushButton("New", this);
        p_anotherButton = new QPushButton("Open", this);
    
    
        this->centralWidget()->layout()->addWidget(p_button);
        this->centralWidget()->layout()->addWidget(p_anotherButton);
    
        this->setWindowTitle("Omni-FEM");
    //    this->centralWidget()->layout()->children().at(1)
        this->setFixedSize(this->minimumSize());
    //    p_anotherButton->setVisible(false);
    //    this->setFixedSize(this->cenOpentralWidget()->size());
    
        connect(p_anotherButton, SIGNAL (released()), this, SLOT (handleButton()));
    }
    
    
    void MainWindow::changeGUIState(systemState nextState)
    {
        switch(nextState)
        {
            case systemState::PHYSICS_CHOOSING:
            {
                switch(p_GUIState)
                {
                    case systemState::ON_START_UP_STATE:
                    {
                        this->setMaximumSize(QSize(1000, 1000));
    
                        if(p_group)
                            delete p_group;
    
                        p_group = new QSequentialAnimationGroup;
    
                        p_sizeAnimation = new QPropertyAnimation(this, "size");
                        p_sizeAnimation->setDuration(500);
                        p_sizeAnimation->setStartValue(this->size());
                        p_sizeAnimation->setEndValue(QSize(600, 600));
    
                        p_opacityEffect = new QGraphicsOpacityEffect(this);
                        QGraphicsOpacityEffect *test = new QGraphicsOpacityEffect(this);
    
                        p_button->setGraphicsEffect(test);
                        p_anotherButton->setGraphicsEffect(p_opacityEffect);
    
                        QPropertyAnimation *fadeTest = new QPropertyAnimation(test, "opacity");
    
                        p_fadeOut = new QPropertyAnimation(p_opacityEffect, "opacity");
                        p_fadeOut->setDuration(1000);
                        p_fadeOut->setStartValue(1);
                        p_fadeOut->setEndValue(0);
                        p_fadeOut->setEasingCurve(QEasingCurve::OutBack);
    
                        fadeTest = new QPropertyAnimation(test, "opacity");
                        fadeTest->setDuration(1000);
                        fadeTest->setStartValue(1);
                        fadeTest->setEndValue(0);
                        fadeTest->setEasingCurve(QEasingCurve::OutBack);
    
                        p_fadeOut->start();
                        fadeTest->start();
                 //       p_group->addAnimation(p_fadeOut);
                 //       p_group->addAnimation(fadeTest);
                        p_group->addAnimation(p_sizeAnimation);
    
                        connect(p_fadeOut, SIGNAL (finished()), this, SLOT (hideOpenButton()));
                        connect(fadeTest, SIGNAL (finished()), this, SLOT (hideNewButton()));
    
                        p_group->start();
    
                    }
                        break;
                    default:
                        break;
                }
            }
            break;
        default:
            break;
        }
    
        p_GUIState = nextState;
        connect(p_group, SIGNAL (finished()), this, SLOT (updateGUI())); // The Debugger throws the error on this line
    }
    
    
    
    // ----- Section is for Interrupts ------
    void MainWindow::handleButton()
    {
        changeGUIState(systemState::PHYSICS_CHOOSING);
    }
    
    void MainWindow::hideNewButton()
    {
        p_button->setHidden(true);
    }
    
    void MainWindow::hideOpenButton()
    {
        p_anotherButton->setHidden(true);
    }
    
    void MainWindow::hideBackButton()
    {
    }
    
    void MainWindow::hideFinishButton()
    {
    }
    
    void MainWindow::updateGUI()
    {
        switch(p_GUIState)
        {
        case systemState::PHYSICS_CHOOSING:
            if(!p_finishButton)
            {
                p_finishButton = new QPushButton("Finish", this);
                this->centralWidget()->layout()->addWidget(p_finishButton);
            }
            break;
        default:
            break;
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    以下是枚举定义文件:

    //! The system state enum that describes the state that the UI is in
    /*!
        This is used to keep track of what state that the UI is in. This will
        effect how frames are drawn and what variables are initilized or accessed.
        Some variables are accessed only when the user is drawing on the canvas,
        for example.
    */
    enum class systemState
    {
        ON_START_UP_STATE,/*!< The default value for the enum. This is the state that the program is in when the user first opens the progam in order to load any default settings */
        INITIAL_START_UP,/*!< This is the state that the program is in when the user can choose either new or open. The startup screen */
        PHYSICS_CHOOSING,/*!< This is the state that the program is in when the user can choose the simulation they would like to run */
        MODEL_DEFINING,/*!< This is the state that the program is in when the user is drawing their geometry on the canvas */
        SIMULATING,/*!< This is the state that the program is in when the user is simulating their simulation */
        VIEWING_RESULTS/*!< This is the state that the program is in when the user is viewing the results of the simulation */
    };
    

    再次,我得到了错误:

    QObject::Connect:无法连接(空)::已完成()到 主窗口::updateGUI())

    当我拥有 QPushButton *p_button; 在中发表了评论。注释掉后,错误就消失了。我已经尝试将qpushbutton放在代码的不同位置,但仍然收到相同的错误。

    我对这个错误感到很困惑,因为我没有遇到类似的错误!如有任何帮助,我们将不胜感激。

    顺便说一句:我在写这篇文章的时候使用的是最新发布的qt版本。另外,对于两个按钮淡入淡出的动画,我希望将它们放在qparallellanimationgroup中,但同样的情况发生在qparallellanimationgroup作为qpushbutton时!因此,对原因进行了评论。所以,如果你能为这两个问题提出一个解决方案的话,就得加倍!我认为他们的问题是一样的。

    1 回复  |  直到 6 年前
        1
  •  1
  •   A.Fagrell    6 年前

    出现此错误的原因是连接完成后p_group变量为空。也许 changeGUIState(systemState) 使用调用 nextState != systemState::PHYSICS_CHOOSING 或者那个 p_GUIState != systemState::ON_START_UP_STATE . 调试程序以找出答案!

    另外,我建议使用新的信号和插槽语法,例如:

    connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue);
    

    而不是

    connect(sender, SIGNAL(valueChanged(QString, QString)), receiver, SLOT( updateValue(QString)));
    

    为什么?最好的理由是:

    编译时检查是否存在信号和插槽、类型或是否缺少q_对象。

    https://wiki.qt.io/New_Signal_Slot_Syntax 更多信息。