- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 Qt 4.8 中使用 QSignalMapper。现在我正在发出如下网络请求:
// start the request
QNetworkRequest request(url);
QNetworkReply* reply = networkManager->get(request);
// connect signals using QSignalMapper
QSignalMapper* signalMapper = new QSignalMapper(reply);
connect(signalMapper, SIGNAL(mapped(QObject*)),this, SLOT(onFeedRetrieved(QObject*)), Qt::UniqueConnection);
connect(reply,SIGNAL(finished()),signalMapper, SLOT(map())); // connect to the signal mapper
signalMapper->setMapping(reply, dataModel); // set the mapping (the mapping should be automatically removed when reply is destroyed)
我为我发出的每个请求都这样做,我每次都将 QSignalMapper 连接到我的插槽。是否有更优雅的解决方案可以做同样的事情,也许使用一个 QSignalMapper?
最佳答案
一种简单的方法是将 dataModel
设置为回复的属性。
按值而不是指针保留网络管理器和其他对象 - 指针是一种额外的间接寻址,在大多数情况下完全没有必要。
下面是一个在 Qt 4 和 5 中都有效的完整 C++11 示例。
// https://github.com/KubaO/stackoverflown/tree/master/questions/netreply-property-38775573
#include <QtNetwork>
#include <QStringListModel> // needed for Qt 4
using DataModel = QStringListModel;
const char kDataModel[] = "dataModel";
class Worker : public QObject {
Q_OBJECT
QNetworkAccessManager m_manager;
Q_SLOT void onFeedRetrieved(QNetworkReply* reply) {
auto dataModelObject = qvariant_cast<QObject*>(reply->property(kDataModel));
auto dataModel = qobject_cast<DataModel*>(dataModelObject);
qDebug() << dataModel;
emit got(reply);
}
public:
Worker(QObject * parent = nullptr) : QObject{parent} {
connect(&m_manager, SIGNAL(finished(QNetworkReply*)),
SLOT(onFeedRetrieved(QNetworkReply*)));
}
void newRequest(const QUrl & url, DataModel * dataModel) {
QNetworkRequest request{url};
auto reply = m_manager.get(request);
reply->setProperty(kDataModel, QVariant::fromValue((QObject*)dataModel));
}
Q_SIGNAL void got(QNetworkReply*);
};
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
DataModel model;
Worker worker;
worker.newRequest(
QUrl{"http://stackoverflow.com/questions/38775573/best-way-to-use-qsignalmapper"},
&model);
QObject::connect(&worker, SIGNAL(got(QNetworkReply*)), &app, SLOT(quit()));
return app.exec();
}
#include "main.moc"
如果 dataModel
实例和回复之间存在 1:1 映射,您只能使用 QSignalMapper
。如果一个数据模型用于多个回复,它将不起作用。
如果你真的很关心分配计数,那么使用属性系统会有更多的开销:设置对象的第一个属性至少执行两次分配 - 一个内部类,以及 QMap 的数据段
。这就是 2N 分配。相比之下,将映射添加到 QSignalMapper
会执行摊销的 log(N) 分配。否则,QSignalMapper
是无用的。
在 Qt 5 中使用它完全是一种反模式,因为您可以连接到 std::bind
或 lambda。无论如何,如果 QSignalMapper
映射到 QVariant
会好得多。
向对象添加第一个连接也会分配一个(不同的)内部类。为避免这种潜在成本,您应该避免向您经常创建的对象添加连接。最好将 一次 连接到 QNetworkManager::finished(QNetworkReply*)
信号,而不是连接到每个 QNetworkReply::finished()
。 las,一旦您使用排队连接,这种节省就消失了:目前,它们为传递给插槽的每个参数花费了额外的分配。这只是当前实现的一个缺点,而不是架构限制;它可以在随后的次要 Qt 版本中删除(如果我或其他人得到它)。
#include <QtNetwork>
#include <QStringListModel> // needed for Qt 4
using DataModel = QStringListModel;
class Worker : public QObject {
Q_OBJECT
QNetworkAccessManager m_manager;
QSignalMapper m_mapper;
// QObject::connect is not clever enough to know that QNetworkReply* is-a QObject*
Q_SLOT void map(QNetworkReply* reply) { m_mapper.map(reply); }
Q_SLOT void onFeedRetrieved(QObject * dataModelObject) {
auto dataModel = qobject_cast<DataModel*>(dataModelObject);
auto reply = qobject_cast<QNetworkReply*>(m_mapper.mapping(dataModelObject));
qDebug() << dataModel << reply;
emit got(reply);
}
public:
Worker(QObject * parent = nullptr) : QObject{parent} {
connect(&m_manager, SIGNAL(finished(QNetworkReply*)), SLOT(map(QNetworkReply*)));
connect(&m_mapper, SIGNAL(mapped(QObject*)), SLOT(onFeedRetrieved(QObject*)));
}
void newRequest(const QUrl & url, DataModel * dataModel) {
QNetworkRequest request{url};
auto reply = m_manager.get(request);
// Ensure a unique mapping
Q_ASSERT(m_mapper.mapping(dataModel) == nullptr);
m_mapper.setMapping(reply, dataModel);
}
Q_SIGNAL void got(QNetworkReply*);
};
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
DataModel model;
Worker worker;
QObject::connect(&worker, SIGNAL(got(QNetworkReply*)), &app, SLOT(quit()));
worker.newRequest(
QUrl{"http://stackoverflow.com/questions/38775573/best-way-to-use-qsignalmapper"},
&model);
return app.exec();
}
#include "main.moc"
关于c++ - 使用 QSignalMapper 的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38775573/
我知道 QSignalMapper 在这种情况下工作得很好: QSignalMapper *signalMapper = new QSignalMapper(this); connect(signal
是否可以使用 QSignalMapper 重新发出具有多个参数的信号?我找到了一种解决方法,但我很想知道它是否可能。 示例:采取 void QLineEdit::textEdited ( const
我尝试制作一个简单的示例来帮助理解 QSignalMapping 的概念如何在 PySide 中工作。我想通过循环迭代来动态创建一系列按钮,当用户按下其中一个按钮时,我可以激活一个方法,为按下的按钮返
如何使用 QSignalMapper 映射多个复选框?我将使用的来自复选框的信号是 stateChanged(int flag)。在此过程中,我想保留此 int 标志,它最终将与其他映射变量一起发送到
在我在这里发帖之后:Associate signal and slot to a qcheckbox create dynamically我需要关联: • 当我点击一个 qCheckBox 到我的函数
我遇到了一个问题,我需要保留映射源信号的参数。到目前为止,我只找到了没有任何参数的映射信号的示例。 例如,clicked() 信号: signalMapper = new QSignalMapper(
我在 Qt 4.8 中使用 QSignalMapper。现在我正在发出如下网络请求: // start the request QNetworkRequest request(url); QNetwo
我有一个自定义结构,它的实例与 QAction 实例相关联。我希望在执行操作时使用我的结构的相应实例执行槽。 我设法使用 QSignalMapper 通过对 QObject 进行子类化以封装我的结构实
我正在制作一个能够对我的电路板进行编程的应用程序。我想通过文件对话框选择文件,并通过上传按钮上传带有所选文件的板。我有两个类:MyFileDialog 和 CommandProcess。我将上传按钮单
我正在尝试将 QSignalMapper 与我的按钮一起使用,但我似乎无法让它工作以触发我的插槽。 这是我的 SignalMapper 代码: 在我的标题中: ... private: QSi
我正在使用 C++ Qt 框架制作一个应用程序。我现在遇到的问题类似于提交表格。我需要向系统添加一个客户端。因此,当您单击“添加客户端”按钮时,它需要将来自 QLineEdit 的文本和来自 QDat
我有一个QSignalMapper,在某些时候我需要断开这个QSignalMapper到一个插槽,之后,我再次重新连接。执行此操作的正确方法是什么? 或者有什么方法可以检查 QSignalMapper
我在一个表中有一堆 QComboBoxes。为了知道触发了哪个信号,我重新映射信号以对表格单元格位置进行编码(如 Selecting QComboBox in QTableWidget 中所述) (为
我正在尝试使用 QSignalMapper 在单击时将信号发送器 (QPushButton) 发送到插槽。但它不起作用,我真的不知道为什么。 如果您知道执行此操作的不同方法,很高兴通知我,但我真的很想
我有一个带有所有标准按钮和非标准按钮的 QDialogButtonBox(添加 QPushbutton 以创建非标准按钮)。 我可以为非标准按钮单独实现 SignalMapper。但在这种情况下,
我想创建一个动态菜单,它枚举 QMainWindow 中的所有 QDockWidget 并允许显示/隐藏 QDockWidgets,因此到目前为止我得到了这个代码: class PluginActio
我有一个 QTreeWidget,其中它的每个项目在一列中都有一个 QComboBox。我已将它连接到带有 QSignalMapper 的插槽,并且在触发时成功检索了组合框中的项目和索引。我是这样做的
首先,我很抱歉这个看起来很夸张的问题,但事实并非如此。我正在阅读 Foundation of qt development 一书,在阅读第四章时,作者通过展示这个例子讲述了 MDI 窗口的基础知识:
您好,我尝试将带有参数的插槽绑定(bind)到 QAction 触发的信号我有这段代码,上下文菜单效果很好。但是 OpenPublishWin 从未触发过。 void MyApp::ShowConte
编辑:下面的代码已更新为工作解决方案。 为了向 QT 介绍自己,我尝试用 64 个 QPushButtons 设计一个棋盘。我知道这可能不是最好的方法,但我相信从基础开始是一个很好的学习方法。无论如何
我是一名优秀的程序员,十分优秀!