Qt将信号连接到插槽
Posted
技术标签:
【中文标题】Qt将信号连接到插槽【英文标题】:Qt connect signal to slot 【发布时间】:2013-08-26 16:47:47 【问题描述】:我有一个包含 QSplitter 小部件(以及其他小部件)的主窗口类。此拆分器的内容由另一个类中的小部件填充。
在另一个 Widgwt 中,我有一个布局,其中添加了一个名为 test_btn 的 QPushButton 我还在 public slots:
下的头文件中定义了一个名为 test_function 的函数,它在 cpp 文件中有相应的代码:
cout << "Test!" << endl;
我尝试使用以下代码调用此函数:
connect(test_btn, SIGNAL(clicked()), SLOT(test_function()));
小部件和按钮在应用程序中按预期显示,但是当我单击它时没有任何反应。
如果我将相同的 connect
代码添加到主窗口,它可以工作(用于从主窗口调用测试函数),即
connect(cc_point.test_btn, SIGNAL(clicked()), SLOT(main_win_test_function()));
我不能从其他类调用测试函数,除非我从main_win_test_function()
调用它
我知道我缺少连接语句中的“接收器小部件”,尽管它在主窗口类中没有它也可以工作,并且在编译时我没有收到任何错误。
我是否需要在other_class
中定义父级或其他内容?
main_window.cpp:
main_window::main_window()
add_splitter();
QGridLayout *window_layout = new QGridLayout;
window_layout->setSpacing(0);
window_layout->setContentsMargins(0, 0, 0, 0);
window_layout->addWidget(splitter1, 0, 0);
set_layout(window_layout);
void main_window::add_splitter()
other_class oc_point;
splitter1 = new QSplitter(Qt::Horizontal);
splitter1->addWidget(oc_point.oc_widget);
other_class.cpp:
other_class:other_class()
oc_widget = new QWidget;
QGridLayout *other_layout = new QGridLayout(oc_widget);
test_btn = new QPushButton;
test_btn->setText("Test Button");
connect(test_btn, SIGNAL(clicked()), test_btn->parent(), SLOT(test_function());
other_layout->addWidget(test_btn);
void other_class::test_function()
cout << "Test output" << endl;
main.cpp:
int main(int argc, char *argv[])
QApplication app(argc, argv);
main_window window;
window.resize(1100, 700);
window.setWindowTitle("Qt Test");
window.setWindowIcon(QIcon (":/images/icon_1.png"));
window.setMinimumHeight(500);
window.show();
return app.exec();
正如我上面提到的,就创建窗口和显示小部件而言,这一切都很好,但是当我单击按钮时不会调用 test_function。如果我还需要包含我的头文件,请告诉我。
【问题讨论】:
现在您明白为什么发布代码非常重要了。当我看到它的那一刻,这个错误就很明显了。 【参考方案1】:在main_window::add_splitter()
中,oc_point
在函数返回后立即被销毁。问题不在于连接,问题在于您的对象在您对它做任何有用的事情之前就消失了。
下面是一个独立的示例,在 Qt 4 和 5 中都演示了这个问题。一旦单击“删除其他”,测试按钮就不起作用。
//main.cpp
#include <QApplication>
#include <QGridLayout>
#include <QSplitter>
#include <QPushButton>
#include <QMessageBox>
class Other : public QObject
Q_OBJECT
QWidget *m_widget;
Q_SLOT void testFunction()
QMessageBox::information(NULL, "Test", "Slot works.");
public:
QWidget *widget() const return m_widget;
Other(QObject *parent = 0) : m_widget(new QWidget), QObject(parent)
QGridLayout *l = new QGridLayout(m_widget);
QPushButton *btn = new QPushButton("Test Button");
l->addWidget(btn);
connect(btn, SIGNAL(clicked()), this, SLOT(testFunction()));
~Other() if (!m_widget->parent()) delete m_widget;
;
class Main : public QWidget
public:
Main(QWidget *parent = 0, Qt::WindowFlags f = 0) : QWidget(parent, f)
QGridLayout *l = new QGridLayout(this);
QPushButton *btn = new QPushButton("Delete Other");
Other *o = new Other(this);
QSplitter *spl = new QSplitter;
spl->addWidget(o->widget());
l->addWidget(spl);
l->addWidget(btn);
connect(btn, SIGNAL(clicked()), o, SLOT(deleteLater()));
;
int main(int argc, char *argv[])
QApplication a(argc, argv);
Main w;
w.show();
return a.exec();
#include "main.moc"
【讨论】:
感谢您的快速回复。我也试过这个,它也没有工作,有没有可能是因为我在主类中有一个Qwidget
和一个layout
,它有一个Qsplitter
,然后有一个'oc_point.QWidget`这又有一个layout
和test_btn
添加test_btn
的父级没有test_function() 插槽? (这可能会让人感到困惑,所以让我知道添加我的实际代码是否更容易)
您绝对,肯定需要展示您的代码。制作一个独立的单文件示例。没有.h
文件,没有类似的。只有一个main.cpp
文件和一个.pro
文件。在末尾添加#include "main.moc"
,这样就不需要单独的头文件了。一旦您确认它可以工作并演示了问题,请重新运行 quake、rebuild 并在此处发布。否则就是浪费大家的时间。
如何在不破坏对象的情况下将other_widget
添加到splitter1
?我是否必须返回对象或小部件 ID 或其他内容,或者是否有更好的方法可以在没有 oc_point
的情况下执行此操作,因为显然尝试使用 other_class.other_widget
添加它会给我“预期的主表达式之前”。错误'
所有的QWidgets都是QObjects。只需在堆上而不是在堆栈上创建新对象,并使其为必要时存在的东西所拥有。就这样。您提供的代码中的问题是 oc_point
在堆栈上,而不是在堆上。就是这样。【参考方案2】:
在您的对象初始化之后,您应该将它们相互连接起来。明确命名谁的槽是谁的,谁的信号是谁的,会有很大帮助。
有时我会做一个辅助函数void Widget::connectTo__Class__(Class * class_ptr);
然后在该函数调用中,我将连接跨越类/父/继承边界的插槽。
这是一个示例实现:
void Widget::connectTo__Class__(Class * class_ptr)
QObject::connect(this, SIGNAL(myWidgetSignal()),
class_ptr, SLOT(myClassSlot()));
QObject::connect(class_ptr, SIGNAL(myClassSignal()),
this, SLOT(myWidgetSlot()));
还请记住,当您做错事情时,运行时会抱怨,例如class_ptr
是否为null
,或者myClassSignal
不存在。当您在调试模式下运行应用程序时,您可以在应用程序输出中看到这些错误。
有时间试试QDebug
。
http://qt-project.org/doc/qt-4.8/debug.html
编辑: 要修复任何头类递归定义问题,请执行以下操作:
在您的类之一的头文件中仅对该类进行原型化,不要包含它:
在 widget.h 中:
// #include "myclass.cpp" // Should be commented out!
class MyClass; // This prototype avoids the recursion
// ...
class Widget
// ...
public:
void connectToMyClass(Class * class_ptr);
// ...
然后在 cpp 文件中,执行包含。
#include "myclass.h"
void Widget::connectToMyClass(Class * class_ptr)
// ...
解决此问题的另一种方法是使用QObject *
而不是Class *
。
希望对您有所帮助。
【讨论】:
感谢您对此的快速回复。我尝试了您对代码的建议,虽然我不确定我是否正确实现它,但我无法将这些添加到other_class
cpp 文件中,因为它无法使用递归指针正确构建并将其添加到main_window 类似乎也不起作用,尽管我可能做得不对。
要解决这个问题,不要在两个地方都包含其他类。以上是关于Qt将信号连接到插槽的主要内容,如果未能解决你的问题,请参考以下文章