延迟处理您的信号
的一种可能解决方案是使用Qt::QueuedConnection将其连接到插槽。
connect(ui->zoomSlider, SIGNAL(valueChanged(int)), ui->map, SLOT(SetZoom(int)), Qt::QueuedConnection);
使用Qt::QueuedConnection
发出的valueChanged
信号事件不会在生成时被处理,就像使用directly
连接的信号一样。事件将被添加到事件循环队列中。这就是Qt::QueuedConnection
在Qt内部的实现方式。
专门为Nejat设计
测试这种方法,可以使用以下代码:
MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void signalReceived();
void signalReceivedQueued();
void buttonPressed();
signals:
void directConnectedSignal();
void queuedConnectedSignal();
private:
Ui::MainWindow *ui;
};
#endif
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(this, SIGNAL(directConnectedSignal()), SLOT(signalReceived()), Qt::DirectConnection);
connect(this, SIGNAL(queuedConnectedSignal()), SLOT(signalReceivedQueued()), Qt::QueuedConnection);
connect(ui->pushButton, SIGNAL(pressed()), SLOT(buttonPressed()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::signalReceived()
{
qDebug() << "signalReceived";
}
void MainWindow::signalReceivedQueued()
{
qDebug() << "signalReceivedQueued";
}
void MainWindow::buttonPressed()
{
emit queuedConnectedSignal();
emit directConnectedSignal();
}
如果您运行上面的代码片段,当按下按钮时,您将获得以下输出:
signalReceived
signalReceivedQueued
排队信号首先发出,但最后接收。这可以在您的情况下用于优先处理发出的信号。
然而,大多数情况下使用排队连接都无法帮助您,因为用户会过于频繁地发出滑块事件,UI 无论如何都会冻结。所以,我建议以下操作:
- 确定 UI 冻结的原因,哪部分代码导致了它。
- 尝试通过异步调用、将逻辑移动到单独的线程中或使用
QtConcurrent
来避免冻结。
- 如果您真的无法控制网页中地图缩放的方式,请尝试忽略 QSlider 生成的所有事件,并仅在
500
毫秒间隔内对最后一个事件做出反应。
Qt::QueuedConnection
参数调用connect函数。虽然我不是100%确定,但如果这样做会将新事件放入循环并继续线程执行,那么你的问题就会得到解决。 - Max GoQt::QueuedConnection
是无用的。 - Nejat