4

假设我们有以下用户界面:

+--------------------------+
|W1       +--------------+ |
|         |W2            | |
|         | +----------+ | |
|         | |W3        | | |
|         | +----------+ | |
|         |              | |
|         +--------------+ |
+--------------------------+

W3 对 W1 中发出的某个信号(或低于该级别,即 qApp)感兴趣。

想法是独立开发W3。但是必须有人进行信号/插槽连接。

如果我们希望 W3 不知道任何其他小部件,并且我们也不希望 W1 知道 W3,那么将 W1 中发出的信号连接到 W3 中的插槽的良好做法/推荐方法是什么?

解决方案 1:将 W1 中的信号与 W2 中的信号连接(信号到信号技术),因此将 W2 中的信号连接到 W3 中的插槽。

解决方案 2:生成一个 qApp 信号并将其连接到 W2 和 W3 中的插槽。

解决方案 3:生成一个 qApp 信号并让 W3 本身使用自己的插槽连接到它。

谢谢

4

3 回答 3

4

通常,封闭的小部件将小部件封装在其中并提供更高级别的接口。例如,如果 W3 包含几个需要根据某些状态启用/禁用的小部件,W3 将管理该状态,为其提供 API 并相应地启用/禁用小部件。所以通常不需要直接从W1到W3。

如果小部件彼此不了解(例如 b/c W1 是一个可以嵌入任何东西的通用容器小部件),那么组装 UI 的人,知道所有涉及的小部件,应该进行连接。

我不知道您所说的“qApp 信号”是什么意思,但这听起来太像中心对象连接到所有东西,这当然也不是好的设计。

也许您有一个特定的例子?

于 2010-08-03T20:46:35.963 回答
2

我们在这里使用的方法是“外壳”进行连接。

shell 是一个对象,它知道所涉及的所有小部件。在这种情况下,W1、W2 和 W3。通常它是组装用户界面的代码。

如果 shell 不知道 W3(例如,因为 W3 是一个实现细节),那么 W3 的“所有者”应该建立连接等等。

于 2010-08-03T18:50:53.150 回答
0

您可以将名称设置为小部件,然后在任何地方发现它们:

for(auto w_ptr: qApp->allWidgets())
    if(w_ptr->objectName() == "QObject anywhere")
        connect(...)

或在父小部件中:

if(QPushButton* o = findChild<QPushButton*>("QPushButton with name"))
    connect(...)

主文件

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QWidget wdgt;
    wdgt.setWindowTitle("wdgt");
    wdgt.setObjectName("wdgt");
    wdgt.show();

    Widget w;
    w.show();

    return a.exec();
}

小部件.cpp

#include <qlayout>
#include <qpushButton>
#include <qdebug>
#include <qapplication>

#include "widget.h"
#include "connect_by_name.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle("Widget");

    m_label->setFrameShape(QFrame::Box);

    QHBoxLayout * hl{new QHBoxLayout{}};

    hl->addWidget(m_label);
    hl->addWidget(new connect_by_name{});
    setLayout(hl);

    connect_to_unique_pb();
}

void Widget
::connect_to_unique_pb() {
    if(QPushButton * pb_ptr
            = findChild<QPushButton*>("unique_pb"))
    {
        connect(pb_ptr,  &QPushButton::pressed,
                m_label, &QLabel::clear);
        connect(pb_ptr,  &QPushButton::released,
                this,    &Widget::pb_relased);
    }
    else
    {
        qDebug() << "The push button not found.";
    }
}

void Widget
::pb_relased() {
    m_label->setText("button not pressed");
}

小部件.h

#ifndef WIDGET_H
#define WIDGET_H

#include <qwidget>
#include <QLabel>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);

public slots:
    void pb_relased();

private:
    void connect_to_unique_pb();

private:
    QLabel * m_label{new QLabel{"button not pressed"}};
};

#endif // WIDGET_H

connect_by_name.cpp

#include <qapplication>
#include <qdebug>
#include <qwidget>

#include "connect_by_name.h"
#include "widget.h"

connect_by_name
::connect_by_name(QWidget *parent) :
    QWidget(parent)
{
    m_pb->setObjectName("unique_pb");
    m_hl->addWidget(m_pb);
    connect_to_unique_widget();
}

void connect_by_name
::connect_to_unique_widget() {
    for(auto w_ptr: qApp->allWidgets())
        if(w_ptr->objectName() == "wdgt") {
            connect(m_pb,  &QPushButton::pressed,
                    w_ptr, &QWidget::hide);
            connect(m_pb,  &QPushButton::released,
                    w_ptr, &QWidget::show);
            break;
        }
}

connect_by_name.h

#ifndef CONNECT_BY_NAME_H
#define CONNECT_BY_NAME_H

#include <QWidget>
#include <QPushButton>
#include <QLayout>

class connect_by_name : public QWidget
{
    Q_OBJECT

public:
    explicit connect_by_name(QWidget *parent = nullptr);

private:
    void connect_to_unique_widget();

private:
    QHBoxLayout * m_hl {new QHBoxLayout{this}};
    QPushButton * m_pb {new QPushButton{"unique button"}};
};

#endif // CONNECT_BY_NAME_H

连接.pro

QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET   = connect
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
        main.cpp \
        widget.cpp \
        connect_by_name.cpp

HEADERS += \
        widget.h \
        connect_by_name.h
于 2019-02-07T15:48:06.137 回答