QT库QObject :: connect:无法连接(null):: finished()到MainWindow :: updateGUI()错误

时间:2018-05-22 13:41:44

标签: c++ qt user-interface

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

无论如何,我收到一个奇怪的错误(这是这篇文章的标题),代码无法连接到我的插槽。起初,我以为我宣布我的插槽错了。然后,事实证明其中一个QPushButton对象正在干扰信号。

我有一个Sequential Animation对象,我拿两个按钮,让它们淡出然后调整窗口大小。但是,由于此错误,所有动画都无法正常工作。直到我注释掉我的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:无法连接(null):: finished()   主窗口:: updateGUI()

虽然我已经注释了QPushButton *p_button;。当注释掉时,错误消失了。我已经尝试将QPushButton放在代码中的不同位置,但我仍然收到相同的错误。

我对此错误感到非常难过,因为我没有碰到类似的东西!任何帮助将不胜感激。

BTW:在撰写本文时,我正在使用最新发布的QT版本。另外,对于两个按钮渐变的动画,我想把它们放在QParallelAnimationGroup中,但是QParallelAnimationGroup作为我的QPushButton发生同样的事情!因此,原因是被注释掉了。如果你可以建议修复这两个问题,那么双点!我认为他们的问题是一样的。

1 个答案:

答案 0 :(得分:1)

您收到此错误的原因是因为连接完成后p_group变量为null。可能会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_OBJECT是否缺失。

有关详细信息,请参阅https://wiki.qt.io/New_Signal_Slot_Syntax