Приватные и публичные слоты в QT
В доке сказано только следующее:
Слоты - это обычные функции-члены, они следуют обычным правилам C ++ при непосредственном вызове.
Однако как слоты они могут быть вызваны любым компонентом, независимо от его уровня доступа, через соединение "сигнал-слот".
Это означает, что сигнал, отправляемый экземпляром некоторого класса, может выполнить вызов приватного слота в экземпляре другого класса.
Иными словами из другого класса вы не можете вызывать приватный слот как функцию, но если вы отправляете сигнал методом
emit
, подключённый к этому приватному слоту, вы можете вызывать его.
Возьмём примерно тот же самый код, что в этой заметке,
создадим виджет как здесь,
разместим на форме однострочное текстовое поле QLineEdit
и флажок-переключатель QCheckBox
,
а также добавим в проект пустой класс MyObject
, унаследованный от Object
. Будем "танцевать" в разработке от объекта, который ещё упростим.
Файл object.h
#ifndef OBJECT_H #define OBJECT_H #include <QObject> #include <QtWidgets> class MyObject : public QObject { Q_OBJECT //Класс д.б. наследником QObject, чтобы использовать сигналы и слоты public: explicit MyObject(QObject * parent = 0); signals: void send_to_gui(bool value); //Сигнал, отправляемый объектом в GUI private slots: void get_from_gui(bool value); //Слот для приёма сигналов от GUI void gets_from_gui(QString value); //Ещё один слот для приёма информации о том, что изменилось текстового поля //При этом объект не знает о виджете, //он просто предоставляет слот для получения внешней информации private: bool state; //Собственно данные класса }; #endif // OBJECT_H
Файл object.cpp
#include "object.h" MyObject::MyObject(QObject *parent) : QObject (parent) { } void MyObject::get_from_gui(bool value) { //Слот 1 state = value; //У объекта есть состояние, он его как-то поменял emit send_to_gui(state); //и послал сигнал в GUI } void MyObject::gets_from_gui(QString value) { //Слот 2 QMessageBox msgBox; msgBox.setText(value); msgBox.exec(); }
Файл widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "object.h" namespace Ui {class Widget;} class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); signals: void send_to_object(bool value); //Сигнал для отправки из GUI в объект private slots: void get_from_object(bool value); void on_checkBox_clicked(); private: Ui::Widget *ui; MyObject Object; //Экземпляр объекта }; #endif // WIDGET_H
Файл widget.cpp
Тут будет самое интересное. Если мы соединим сигналы со слотами в конструкторе виджета "классческим" кодом, пришедшим ещё из QT4, то всё работает как надо.
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //Виджет может использовать интефейс сигналов-слотов других виджетов, //не вникая в детали их реализации, очередность обработки сигналов и т.п. connect(&Object,SIGNAL(send_to_gui(bool)),this,SLOT(get_from_object(bool))); //Это сигнал от объекта в виджет connect(this,SIGNAL(send_to_object(bool)),&Object,SLOT(get_from_gui(bool))); //Это сигнал от виджета в слот объекта connect(ui->lineEdit,SIGNAL(textChanged(QString)),&Object,SLOT(gets_from_gui(QString))); //Это сигнал от дочернего виджета lineEdit в слот объекта } Widget::~Widget(){ delete ui; } void Widget::get_from_object(bool value) { //Слот 1 виджета ui->lineEdit->setText(value?"true":"false"); } void Widget::on_checkBox_clicked() { //Слот 2 виджета emit send_to_object(ui->checkBox->isChecked()); }
Теперь изменения в текстовом поле также обрабатываются слотом. Причём, это сработает при любом изменении текста в поле, в том числе, вызванном активностью слота get_from_object
, который записал туда текст.
Но если мы изменим соединения на "стиль QT5" на основе указателей (показано только изменённое тело конструктора виджета)
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); connect (&Object,&MyObject::send_to_gui,this,&Widget::get_from_object); connect (this,&Widget::send_to_object,&Object,&MyObject::get_from_gui); connect(ui->lineEdit,&QLineEdit::textChanged,&Object,&MyObject::gets_from_gui); }
то возникнет ошибка вида "'get_from_gui' is a private member of 'MyObject'" и описания слотов в object.h
придётся сделать публичными:
public slots: void get_from_gui(bool value); void gets_from_gui(QString value);
Думается, всё понятно из общих соображений - QT отказывается получать явно адрес функции-слота, объявленной приватной.
Скачать этот проект QT 5.X в архиве .zip, папка уже создана внутри архива (3 Кб)
15.03.2020, 13:16 [2426 просмотров]