首先,我为一个看上去很大的问题道歉,但事实并非如此。我正在阅读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();
}他的这段解释使我完全无法理解(是我还是其他人也有问题理解它?)
接下来,创建并连接一个名为QSignalMapper的信号映射对象。信号映射器用于将信号源与另一个信号的参数绑定。在本例中,对应于窗口菜单中每个窗口的菜单项的操作被绑定到实际的文档窗口。这些动作反过来又与映射器相关联。当该动作发出触发信号时,发送动作已与相应的文档窗口的QWidget*相关联。此指针用作由信号映射对象发出的映射(QWidget*)信号中的参数。
我的问题:在上面的示例中,我仍然不知道什么是信号映射类,它是如何使用的,它的功能是什么?有谁能用简单的术语来解释上面的段落吗?另外,如果你能用简单的例子来教我地图类的基础知识,那就太棒了?可能在外行人的任期内?
P.S:当我们有MDI窗口时,是否会对菜单进行更改(尽管操作已被禁用/启用),例如假设对于一个特定的文档,我们有“File/”菜单,而对于其他文档,我们是否有“File/remaper”?
发布于 2012-09-29 15:54:39
QSignalMapper用于重新发射带有可选参数的信号.换句话说,(来自文档):
该类收集一组无参数信号,并使用与发送信号的对象对应的整数、字符串或小部件参数重新发射它们。
一个很好的示例(也来自于文档--看看它)设置如下:
假设我们希望创建一个包含一组按钮的自定义小部件(如工具调色板)。一种方法是将每个按钮的clicked()信号连接到它自己的自定义插槽;但在本例中,我们希望将所有按钮连接到单个插槽,并通过单击的按钮参数化该插槽。
因此,假设您有许多按钮封装在一个类中,比如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()方法设置它。
现在剩下的就是将信号映射器映射到我们类的信号:
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.
}
}通过这种方式使用信号映射器,您不必声明和管理所有按钮及其单击的信号,只需一个信号pr。ButtonWidget。
但是,信号映射器很适合捆绑多个信号,甚至可以在它重新发射时设置参数。我希望这给了一些关于QSignalMapper的使用的直觉。
示例代码
解释(您的“段落”)指出,所有的操作都分别映射到特定的QWidget*。当触发一个动作时,它各自的QWidget*将被传递给插槽QWorkspace::setActiveWindow(QWidget*) of workspace,后者反过来激活小部件。
还请注意,从操作到小部件的映射必须发生在代码中的某个地方。我猜想它是在createActions()或enableActions()中完成的。
发布于 2012-09-29 16:00:00
QSignalMapper允许您在需要时将一些信息添加到信号中。这个对象内部有一个类似于QMap<QObject*,QVariant>的映射。然后将一个对象连接到它,当调用插槽时,它会用相关的值重新发出信号。
工作流程:
mySignalMapper:
[ obj1 -> 42 ]
[ obj2 -> "obiwan" ]
[ obj3 -> myWidget ]
connect(obj1,mySignal,mySignalMapper,SLOT(map())); // idem for obj2 and obj3
(obj2 emits "mySignal")
-> (mySignalMapper::map slot is called)
-> (sender() == obj2, associated data = "obiwan")
-> (mySignalMapper emits mapped("obiwan"))我本来打算增加一个更详细的例子,但是Morten Kristensen比我快;)
https://stackoverflow.com/questions/12652356
复制相似问题