2013-08-26 205 views
0

我有一个主窗口类,其中包含一个QSplitter小部件(以及其他小部件)。此拆分器的内容由另一个类中的小部件填充。Qt连接信号插槽

这里面其他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())); 

我不能从其他类调用测试功能,除非我叫它from main_win_test_function()

我知道我错过了connect语句中的'receiver widget',虽然它没有在主窗口类中工作,编译时也没有出现任何错误。

我是否需要在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

现在你明白为什么张贴代码*非常重要*。第二次看到它时,这个错误显而易见。 –

回答

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_ptrnull,或者如果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 *

希望有所帮助。

+0

感谢您对此的快速回应。我尝试了你对代码的建议,虽然我不确定我是否正确实现了它,但我不能将这些添加到'other_class' cpp文件,因为它不能用递归指针正确构建并将其添加到main_window类似乎不工作,虽然我可能没有正确地做。 – user2718679

+0

要解决该问题,请勿在其他地方包含其他课程。 – phyatt

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" 
+0

感谢您的快速响应。我也尝试过这一点,它也没有工作,是否有可能是因为我有一个'Qwidget',在主类中有一个'Qsplitter',它有一个'oc_point.QWidget'而'test'又添加了'test_btn'的'layout','test_btn'的父节点没有test_function()槽? (这可能会让人感到困惑,所以让我知道是否对我来说更容易添加我的实际代码) – user2718679

+1

您**绝对,肯定需要显示您的代码**。制作一个自包含的单个文件示例。没有'.h'文件,没有那样的。只有一个'main.cpp'文件和一个'.pro'文件。在末尾添加'#include“main.moc”',这样就不需要单独的头文件。重新运行地震,重建,然后在确认它可以正常工作并演示问题后在此处发帖。否则,这是浪费每个人的时间。 –

+0

如何将'other_widget'添加到'splitter1'而不破坏对象?我是否必须返回对象或小部件ID或其他东西,还是有没有'oc_point'这样做的更好方法,因为显然试图使用'other_class.other_widget'将它添加给我'预期的主表达式'之前'。 “错误“ – user2718679