0

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

在这个其他 Widgwt 中,我有一个布局,其中添加了一个名为 test_btn 的 QPushButton 我还在名为 test_function 的头文件中定义了一个函数,该函数在public slots: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

主窗口.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);
}

其他类.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;
}

主.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。让我知道是否还需要包含我的头文件。

4

2 回答 2

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"
于 2013-08-26T17:22:30.983 回答
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_ptris null,或者 ifmyClassSignal不存在。当您在调试模式下运行应用程序时,您可以在应用程序输出中看到这些错误。

QDebug尝试一下。

http://qt-project.org/doc/qt-4.8/debug.html

编辑:要修复任何头类递归定义问题,请执行以下操作:

在您的类之一的头文件中,仅对该类进行原型化,不要包含它:

在小部件.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 *.

希望有帮助。

于 2013-08-26T17:08:08.683 回答