首先,我对有重大问题的问题表示歉意,但事实并非如此。我正在阅读《 qt开发基础》,在阅读第四章时,作者将通过显示以下示例来介绍MDI窗口的基础知识:
MdiWindow::MdiWindow( QWidget *parent ) : QMainWindow( parent ) {
setWindowTitle( tr( "MDI" ) );
QWorkspace* workspace = new QWorkspace;
setCentralWidget( workspace );
connect( workspace, SIGNAL(windowActivated(QWidget *)), this, SLOT(enableActions()));
QSignalMapper* mapper = new QSignalMapper( this );
//my problem is in this line
connect( mapper, SIGNAL(mapped(QWidget*)), workspace, SLOT(setActiveWindow(QWidget*)) );
createActions();
createMenus();
createToolbars();
statusBar()->showMessage( tr("Done") );
enableActions();
}
他的这种解释完全使我难以理解(是我还是其他人对它的理解有问题?):
我的问题:在上面的示例中,我仍然不知道什么是信号映射器类,如何使用以及它的功能是什么?谁能用简单的术语解释上面的段落?如果您能通过简单的例子来教我有关Mapper类的基础知识,那将是很棒的事情吗?可能是外行的说法?
P.S :一个困惑是当我们有MDI窗口时,是否更改菜单(尽管已禁用/启用了操作),例如,对于一个特定文档,我们具有菜单“File / close”,对于其他文档,我们具有“File / remaper”?
最佳答案
QSignalMapper
用于重新发射带有可选参数的信号。换句话说(来自documentation):
如下设置了一个很好的示例(也可以从文档中查看):
因此,假设您将许多按钮封装在一个类中,比如ButtonWidget
,并带有一个自定义信号void clicked(const QString &text)
。这是定义:
class ButtonWidget : public QWidget {
Q_OBJECT
public:
ButtonWidget(QStringList texts, QWidget *parent = 0);
signals:
void clicked(const QString &text);
private:
QSignalMapper *signalMapper;
};
然后可以如下定义构造函数:
ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
: QWidget(parent)
{
signalMapper = new QSignalMapper(this);
QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}
connect(signalMapper, SIGNAL(mapped(const QString &)),
this, SIGNAL(clicked(const QString &)));
setLayout(gridLayout);
}
那么这里发生了什么?我们构造一个网格布局和
QPushButton
类型的按钮。其中每个的clicked()
信号都连接到信号映射器。使用
QSignalMapper
的作用之一是可以将参数传递给重新发射的信号。在我们的示例中,每个按钮应发出不同的文本(由于信号的定义),因此我们使用setMapping()
方法进行设置。现在剩下要做的就是将信号映射器映射到我们类(class)的信号上:
connect(signalMapper, SIGNAL(mapped(const QString &)),
this, SIGNAL(clicked(const QString &)));
假设我们有一个称为
TestClass
的测试类,则可以这样使用ButtonWidget
:TestClass::TestClass() {
widget = new ButtonWidget(QStringList() << "Foo" << "Bar");
connect(widget, SIGNAL(clicked(const QString &)),
this, SLOT(onButtonClicked(const QString &)));
}
void TestClass::onButtonClicked(const QString &btnText) {
if (btnText == "Foo") {
// Do stuff.
}
else {
// Or something else.
}
}
通过这种方式使用信号映射器,您不必声明和管理所有按钮及其单击的信号,只需声明一个信号即可。
ButtonWidget
。唯一的缺点是信号映射器非常适合 bundle 多个信号,甚至在重新发出信号时都可以设置参数。我希望这给了
QSignalMapper
用法的一些直觉。您的示例代码
说明(您的“para”)指出,所有 Action 均分别映射到特定的
QWidget*
。触发 Action 时,其各自的QWidget*
将传递到QWorkspace::setActiveWindow(QWidget*)
的插槽workspace
,从而激活小部件。还要注意,从 Action 到小部件的映射必须发生在代码中的某处。我假设它是用
createActions()
或enableActions()
完成的。关于c++ - MDI窗口和QSignalMapper基础,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12652356/