QPushButton не выполняет подключенную функцию при клике - PullRequest
1 голос
/ 12 марта 2020

У меня есть класс с именем UserInterface. В этом классе есть разные функции. build_start_screen() добавляет все виджеты (метки, кнопки, ...) для начального начального экрана. build_option_a_screen() удаляет все с начального экрана и добавляет все виджеты, необходимые для экрана, когда пользователи нажимают кнопку для опции А и так далее. Ради этого вопроса класс урезан.

Теперь я объявил кнопку в build_start_screen() и подключил ее к простому MessageBox.exec(), поэтому он должен всплывать при нажатии. Однако при нажатии кнопки ничего не происходит.

Что я делаю не так? Имеет ли это какое-то отношение к времени жизни переменных, истекающих после завершения функции?

#include <QApplication>
#include <QPushButton>
#include <QAbstractButton>
#include <QLabel>
#include <QFont>
#include <QVBoxLayout>
#include <QMessageBox>

//Class handling all the UI in this Application
class UserInterface {
    public:
        //Build the initial UI the user sees
        void build_start_screen(QWidget& window) {
            //Make new QVBoxLayout for this startscreen UI
            this->layout = new QVBoxLayout(&window);

            //Test messagebox
            QMessageBox msgBox;
            msgBox.setText("Button test.");

            //Button to go to Option A-screen
            QPushButton* showMsgBox = new QPushButton("Show pop-up");
            QAbstractButton::connect(showMsgBox, SIGNAL (clicked()), &window, SLOT (msgBox.exec()));

            //Add labels and button to QVBoxLayout
            layout->addWidget(showMsgBox);
        }

    private:
        //Properties
        QVBoxLayout* layout;
};

int main(int argc, char **argv) {
    QApplication app (argc, argv);

    //Initialize Window
    QWidget Window;
    Window.resize(400, 250);     

    //Create new UserInterface object
    //This will allow us to create different user-interfaces
    //depending on the function we call
    UserInterface* ui = new UserInterface();
    ui->build_start_screen(Window);
    Window.show();

    return app.exec();
}

А что если я хотел бы сделать то же самое, но вместо вызова messageBox я бы хотел вызвать другой функция?

#include <QApplication>
#include <QPushButton>
#include <QAbstractButton>
#include <QLabel>
#include <QFont>
#include <QVBoxLayout>
#include <QMessageBox>

//Class handling all the UI in this Application
class UserInterface {
    public:
        //Build the initial UI the user sees
        void build_start_screen(QWidget& window) {
            //Make new QVBoxLayout for this startscreen UI
            this->layout = new QVBoxLayout(&window);

            //Test messagebox
            QMessageBox msgBox;
            msgBox.setText("Button test.");

            //Button to go to Option A-screen
            QPushButton* showMsgBox = new QPushButton("Show pop-up");
            QAbstractButton::connect(showMsgBox, SIGNAL (clicked()), &window, SLOT (build_option_a_screen()));

            //Add labels and button to QVBoxLayout
            layout->addWidget(showMsgBox);
        }

        void build_option_a_screen(QWidget& window) {
            //Do stuff here with window
            //e.g
            window.resize(500, 500);
        }

    private:
        //Properties
        QVBoxLayout* layout;
};

int main(int argc, char **argv) {
    QApplication app (argc, argv);

    //Initialize Window
    QWidget Window;
    Window.resize(400, 250);     

    //Create new UserInterface object
    //This will allow us to create different user-interfaces
    //depending on the function we call
    UserInterface* ui = new UserInterface();
    ui->build_start_screen(Window);
    Window.show();

    return app.exec();
}

1 Ответ

2 голосов
/ 12 марта 2020

В вашем коде 2 проблемы:

  • В окне "объект" нет слота "msgBox.exe c ()", на что указывает ошибка:

    QObject::connect: No such slot QWidget::msgBox.exec() in ../main.cpp:23
    
  • Исправляя вышесказанное, решение будет следующим:

    QObject::connect(showMsgBox, &QPushButton::clicked, &msgBox, &QMessageBox::exec);
    

    , но теперь проблема в том, что msgBox является локальной переменной, которая будет уничтожена и не может быть

Таким образом, решение состоит в том, чтобы сделать msgBox членом класса или указателем (в случае указателя вы должны управлять динамической памятью c, чтобы избежать утечек памяти) :

//Class handling all the UI in this Application
class UserInterface {
    public:
        //Build the initial UI the user sees
        void build_start_screen(QWidget& window) {
            //Make new QVBoxLayout for this startscreen UI
            this->layout = new QVBoxLayout(&window);
            msgBox.setText("Button test.");
            //Button to go to Option A-screen
            QPushButton* showMsgBox = new QPushButton("Show pop-up");
            QObject::connect(showMsgBox, &QPushButton::clicked, &msgBox, &QMessageBox::exec);

            //Add labels and button to QVBoxLayout
            layout->addWidget(showMsgBox);
        }

    private:
        //Properties
        QVBoxLayout* layout;
        QMessageBox msgBox;
};

Plus:

Рекомендуется не использовать старый синтаксис подключения, поскольку он имеет ограничения и скрывает проблемы.

Это Рекомендуется не использовать старый синтаксис подключения, поскольку он имеет ограничения и скрывает проблемы.

Если вы хотите подключиться к какому-либо методу, который не является QObject (например, X, как вы хотите OP) тогда решение состоит в том, чтобы использовать лямбда-метод:

//Class handling all the UI in this Application
class UserInterface {
public:
    //Build the initial UI the user sees
    void build_start_screen(QWidget& window) {
        //Make new QVBoxLayout for this startscreen UI
        this->layout = new QVBoxLayout(&window);
        //Button to go to Option A-screen
        QPushButton* showMsgBox = new QPushButton("Show pop-up");
        QObject::connect(showMsgBox, &QPushButton::clicked, [this, &window](){
            build_option_a_screen(window);
        });
        //Add labels and button to QVBoxLayout
        layout->addWidget(showMsgBox);
    }
    void build_option_a_screen(QWidget& window) {
        //Do stuff here with window
        //e.g
        window.resize(500, 500);
    }
private:
    //Properties
    QVBoxLayout* layout;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...