我有一个主窗口类,其中包含一个QSplitter小部件(以及其他小部件)。此拆分器的内容由另一个类中的小部件填充。
在其他Widgwt内部我有一个带有QPushButton的布局,名为test_btn,我还在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()
我知道我错过了&#39;接收器小部件&#39;来自connect语句,虽然它在主窗口类中没有它,但在编译时我没有遇到任何错误。
我是否需要在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不会被调用。如果我还需要包含我的头文件,请告诉我。
答案 0 :(得分: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"
答案 1 :(得分:0)
初始化对象后,应将它们相互连接。明确命名哪个插槽的信号是哪个,哪个信号是谁的,这将有很大帮助。
有时候我会做一个辅助函数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。
#include "myclass.h"
void Widget::connectToMyClass(Class * class_ptr)
{
// ...
}
解决此问题的另一种方法是使用QObject *
代替Class *
。
希望有所帮助。