Сигналы и слоты в QT на С++

Пытаюсь разобраться с системой сигналов и слотов. Нишиша не получается... По задумке Кнопка созданная в классе Button, должна посылать сигнал в слот confirm_window_open в классе Window... Все работает только в том случае если confirm_window_open сделать static... Везде во всех примерах все вроде так же...

#ifndef TEST_H
#define TEST_H
#endif // TEST_H
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QGridLayout>
#include <QFont>
#include <iostream>

class Window :public QObject{
    Q_OBJECT
public:
    QWidget window;
    QGridLayout* grid = new QGridLayout;
    Window(int W, int H, QString title){
        window.setMinimumSize(W, H);
        window.setWindowTitle(title);
        window.setLayout(grid);
    }
public slots:
    void confirm_window_open(){
       std::cout << "DONE!" << std::endl;
   }
};

class Button :public QObject{
    Q_OBJECT
public:
    QFont font;
    Button(QString text, QWidget &window, QGridLayout &grid, int row, int column){
        QPushButton* button = new QPushButton(&window);
        (*button).setText(text);
        (*button).setMinimumHeight(50);
        (*button).setStyleSheet("padding-left: 10px; padding-right: 10px;");
        font.setFamily("Arial");
        font.setPixelSize(15);
        (*button).setFont(font);
        grid.addWidget(button, row, column);
        connect(button, &QPushButton::clicked, window, &Window::confirm_window_open);
    }
};

class Main_window :public Window{
    Q_OBJECT
public:
    Main_window() :Window(2000, 800, "Дневник"){
        Button button1("Создать дневник", window *grid, 2, 13);
    }
};

Ответы (1 шт):

Автор решения: maestro

Вот ваш код с минимальными изменениями, приведённый в работоспособное состояние. Весь код можно скопировать в файл main.cpp, скомпилировать и запустить.

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QGridLayout>
#include <QFont>
#include <iostream>

class Window :public QObject{
    Q_OBJECT
public:
    QWidget window;
    QGridLayout* grid = new QGridLayout;
    Window(int W, int H, QString title){
        window.setMinimumSize(W, H);
        window.setWindowTitle(title);
        window.setLayout(grid);
    }
public slots:
    void confirm_window_open(){
       std::cout << "DONE!" << std::endl;
   }
};

class Button : public QObject{
    Q_OBJECT
public:
    QFont font;
    // Здесь вы передаёте вторым параметром ссылку на объект типа QWidget 
    // и пытаетесь подключится к его слоту confirm_window_open. 
    // Но у типа QWidget нет такого слота! Он есть у типа Window.
    // Скорее всего, вы имели в виду именно его. 
    // Поэтому поменяем тип второго параметра.
    Button(QString text, Window &window, QGridLayout &grid, int row, int column){
        QPushButton* button = new QPushButton(&window.window);
        (*button).setText(text);
        (*button).setMinimumHeight(50);
        (*button).setStyleSheet("padding-left: 10px; padding-right: 10px;");
        font.setFamily("Arial");
        font.setPixelSize(15);
        (*button).setFont(font);
        grid.addWidget(button, row, column);
        // Параметр window имеет тип ссылки, а функция connect 
        // ожидает тип указателя. Поэтому преобразуем ссылку в указатель.
        connect(button, &QPushButton::clicked, &window, &Window::confirm_window_open);
    }
};

class Main_window :public Window{
    Q_OBJECT
    Button button1;
public:
    Main_window() :
        Window(2000, 800, "Дневник"),
        // Здесь вы передавали вторым параметром объект window,
        // который имеет тип QWidget и не имеет слота
        // confirm_window_open. Так как мы поменяли сигнатуру 
        // конструктора Button, изменим вызов здесь:
        // передадим вторым параметром текущий объект, у которого
        // есть слот confim_window_open.
        // Кроме того, у вас кнопка была локальным объектом 
        // этого конструктора, и поэтому она была бы уничтожена
        // сразу после завершения её выполнения.
        // Поэтому перенесём её в класс.
        button1("Создать дневник", *this, *grid, 2, 13)
    {
    }
};

// Ну и сводим всё воедино.
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Main_window main_window;
    main_window.window.show();
    return app.exec();
}

#include "main.moc"
→ Ссылка