我有一个QPushButton,并且插槽连接到它的“按下”信号:
connect( &m_oBtnSnapshot, SIGNAL( pressed() ), this,
SLOT( SnapshotClicked() ) );
Slot的实现方式如下:
void
GUI::SnapshotClicked()
{
m_oBtnSnapshot.blockSignals( true );
m_oBtnSnapshot.setDisabled( true );
m_oBtnBenchmark.repaint();
m_oBtnBenchmark.update();
emit( DoSnapshotWork() );
m_oBtnSnapshot.setDisabled( false );
m_oBtnSnapshot.blockSignals( false );
}
所以你可以看到,我点击它时禁用了按钮,并在完成所有操作后重新启用它。 假设DoSnapshotWork()函数需要5秒......虽然这5秒按钮被禁用,但如果我点击它,之后将调用SnapshotClicked()Slot。为什么禁用按钮不会阻止我点击它?
我已经尝试断开进入插槽的信号并在之后重新连接,但没有任何帮助。
答案 0 :(得分:1)
因为鼠标按下事件已放在事件循环上,并等到SnapshotClicked()
方法完成后,再次启用该按钮。
一个简单的解决方案是在QCoreApplication::processEvents()
之后立即调用emit
,这将导致在按钮仍处于禁用状态时处理新闻事件。或者您可以让DoSnapshotWork()
方法在完成时发出信号,然后启用该按钮并取消阻止信号。
此外,
m_oBtnBenchmark.repaint();
m_oBtnBenchmark.update();
repaint()
强制重绘窗口小部件,而update()
通过事件循环调用repaint()
- 不要同时调用它们。
答案 1 :(得分:1)
GUI::SnapshotClicked()
是GUI线程的一部分,这意味着,在运行时,您的GUI无法访问。我假设,信号DoSnapshotWork()
与一个插槽连接,在Qt::QueuedConnection
(或Qt::AutoConnection
)的另一个线程中运行。在这种情况下,发出此信号是异步的,这意味着GUI::SnapshotClicked()
在您的插槽完成之前很久就完成了。我想你应该这样做:
gui.h
public slots:
void onReleaseButton();
gui.cpp
void
GUI::SnapshotClicked()
{
m_oBtnSnapshot.setDisabled( true );
m_oBtnBenchmark.repaint();
m_oBtnBenchmark.update();
emit( DoSnapshotWork() );
}
void
GUI::onReleaseButton()
{
m_oBtnSnapshot.setDisabled( false );
}
其他地方:
connect(shapshotWorker, SIGNAL(releaseButton()), gui, SLOT(onReleaseButton()));
...
DoSnapshotWork()
{
...
emit releaseButton();
}
P.S:你需要一个很好的理由来使用QPushButton :: pressed()信号。在大多数情况下,您更喜欢QPushButton :: clicked()。