延迟发射信号
emit signal with delay
我想要实现的目标是发出一个信号,但在它实际发出之前延迟一段时间。
我的想法是这样的:
emitLater(QObject *obj, QEvent *event, int msDelay)
{
QTimer...
connect(timout to obj and event...
start timer with msDelay...
//maybe I might need a public timer of some sort but the idea is clear
}
所以这种方法因 QEvent
参数而失败,因为信号无法转换为 QEvents
。
我试过用 std::bind 调用几个变体,但我无法让它工作:
//the call
std::function<void(void)> signal = std::bind(&CustomPushButton_Header::clicked, &uiWindow->btnHeader_left); //just a random button to connect a valid signal
emitLater(signal, 2000);
//the function
emitLater(std::function<void(void)>, int msDelay)
{
qDebug() << "hi";
}
我希望有一个适用于所有对象和所有信号的解决方案...也许只适用于调用函数的部分。我认为延迟会很容易。
或者您有不同的甚至更简单的方法。那就太好了。
我查看的一些来源:
你可以为此使用一个计时器,在上面的例子中,你对按钮中的点击槽做出反应,定义了一个 QTimer,连接超时时调用的内容(在本例中是 lambda)和然后你开始计时:)
void MyWindow::on_pushButton_5_clicked()
{
QTimer* t= new QTimer(this);
connect(t, &QTimer::timeout, [this](){ui->label_3->setText("done!");});
t->start(5000); //after 5 seconds
}
有一个函数QTimer::singleShot()
可以在一定时间后触发signal/slot。我是这样实现的:
void MyWindow::emitLater(const QObject *obj, const char *signalOrSlot, int msDelay)
{
//use QTimer::singleShot() to trigger the signal/slot after a certain amount of time
QTimer::singleShot(msDelay, obj, signalOrSlot);
}
并像这样使用它:
void MyWindow::on_pushButton_5_clicked()
{
//trigger the "doing fancy stuff" function after 5 seconds (= 5000 ms)
emitLater(this, SLOT(setText()), 5000);
}
void MyWindow::setText()
{
//do some fancy stuff
ui->label_3->setText("Hello World!");
}
另一种方法是在 中使用 lambda 表达式作为 QTimer::timout()
信号的调用函数:
void MyWindow::on_pushButton_5_clicked()
{
//initialize timer
QTimer* t= new QTimer(this);
t->setSingleShot(true);
//do some fancy stuff after timeout
connect(t, &QTimer::timeout, [this]()
{
ui->label_3->setText("Hello World!");
});
//start the timer with delay of 5 seconds (= 5000 ms)
t->start(5000);
}
这是我在 Python
中使用 PySide2
实现的。
首先我创建了一个 class:
class DelayedSignal:
def __init__(self, timeout, func):
self.timeout = timeout
self.func = func
self.timer = QTimer()
self.timer.setSingleShot(True)
self.timer.setInterval(1000 * timeout)
self.timer.timeout.connect(func)
@Slot()
def __call__(self):
self.timer.stop()
self.timer.start()
下面是代码的其余部分,因此所有这些都是一个最小的工作示例:
from PySide2.QtCore import QTimer, Slot
from PySide2.QtWidgets import QPushButton, QWidget, QHBoxLayout
class AppWindow(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("PRESS", self)
self.setLayout(QHBoxLayout())
self.layout().addWidget(self.btn)
self.delayed_signal = DelayedSignal(timeout=2, func=self.target)
self.btn.clicked.connect(self.delayed_signal)
@Slot()
def target(self):
print("END")
if __name__ == '__main__':
import sys
from PySide2.QtWidgets import QApplication
app = QApplication(sys.argv)
window = AppWindow()
window.show()
sys.exit(app.exec_())
我想要实现的目标是发出一个信号,但在它实际发出之前延迟一段时间。
我的想法是这样的:
emitLater(QObject *obj, QEvent *event, int msDelay)
{
QTimer...
connect(timout to obj and event...
start timer with msDelay...
//maybe I might need a public timer of some sort but the idea is clear
}
所以这种方法因 QEvent
参数而失败,因为信号无法转换为 QEvents
。
我试过用 std::bind 调用几个变体,但我无法让它工作:
//the call
std::function<void(void)> signal = std::bind(&CustomPushButton_Header::clicked, &uiWindow->btnHeader_left); //just a random button to connect a valid signal
emitLater(signal, 2000);
//the function
emitLater(std::function<void(void)>, int msDelay)
{
qDebug() << "hi";
}
我希望有一个适用于所有对象和所有信号的解决方案...也许只适用于调用函数的部分。我认为延迟会很容易。
或者您有不同的甚至更简单的方法。那就太好了。
我查看的一些来源:
你可以为此使用一个计时器,在上面的例子中,你对按钮中的点击槽做出反应,定义了一个 QTimer,连接超时时调用的内容(在本例中是 lambda)和然后你开始计时:)
void MyWindow::on_pushButton_5_clicked()
{
QTimer* t= new QTimer(this);
connect(t, &QTimer::timeout, [this](){ui->label_3->setText("done!");});
t->start(5000); //after 5 seconds
}
有一个函数QTimer::singleShot()
可以在一定时间后触发signal/slot。我是这样实现的:
void MyWindow::emitLater(const QObject *obj, const char *signalOrSlot, int msDelay)
{
//use QTimer::singleShot() to trigger the signal/slot after a certain amount of time
QTimer::singleShot(msDelay, obj, signalOrSlot);
}
并像这样使用它:
void MyWindow::on_pushButton_5_clicked()
{
//trigger the "doing fancy stuff" function after 5 seconds (= 5000 ms)
emitLater(this, SLOT(setText()), 5000);
}
void MyWindow::setText()
{
//do some fancy stuff
ui->label_3->setText("Hello World!");
}
另一种方法是在 QTimer::timout()
信号的调用函数:
void MyWindow::on_pushButton_5_clicked()
{
//initialize timer
QTimer* t= new QTimer(this);
t->setSingleShot(true);
//do some fancy stuff after timeout
connect(t, &QTimer::timeout, [this]()
{
ui->label_3->setText("Hello World!");
});
//start the timer with delay of 5 seconds (= 5000 ms)
t->start(5000);
}
这是我在 Python
中使用 PySide2
实现的。
首先我创建了一个 class:
class DelayedSignal:
def __init__(self, timeout, func):
self.timeout = timeout
self.func = func
self.timer = QTimer()
self.timer.setSingleShot(True)
self.timer.setInterval(1000 * timeout)
self.timer.timeout.connect(func)
@Slot()
def __call__(self):
self.timer.stop()
self.timer.start()
下面是代码的其余部分,因此所有这些都是一个最小的工作示例:
from PySide2.QtCore import QTimer, Slot
from PySide2.QtWidgets import QPushButton, QWidget, QHBoxLayout
class AppWindow(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("PRESS", self)
self.setLayout(QHBoxLayout())
self.layout().addWidget(self.btn)
self.delayed_signal = DelayedSignal(timeout=2, func=self.target)
self.btn.clicked.connect(self.delayed_signal)
@Slot()
def target(self):
print("END")
if __name__ == '__main__':
import sys
from PySide2.QtWidgets import QApplication
app = QApplication(sys.argv)
window = AppWindow()
window.show()
sys.exit(app.exec_())