2013-08-26 201 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