了解信号、槽顺序和父部件
Understanding signals, slot order, and parent widgets
所以我遇到的情况是我无法按照我希望的顺序触发几个插槽。
基本设置是我有一个带有状态栏的主窗口,需要根据来自子小部件 (SearchWidget) 的信号进行更新。当单击子小部件上的 "Go" 按钮时,我希望它更新状态栏以显示 "Searching..." 然后执行实际的数据库搜索。但是,我只能在搜索完成并显示在 tablewidget 中后触发 updateStatusBar 插槽。我已经尝试将连接重新安排为适当的顺序,我已经尝试了一个单独的函数,该函数发出状态栏信号,然后发出搜索信号,但似乎没有任何效果。搜索总是先执行,状态栏直到完成后才会改变。
我是新手,但我猜这个问题可能与主窗口和小部件之间的父子关系有关?也许同一个小部件中的插槽以某种方式排列优先级?请参阅下面的基本代码。
主窗口class:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
initMembers();
initUI();
connect(searchWidget, SIGNAL(searchingStatus(QString)), this, SLOT(updateStatusBar(QString)));
}
void MainWindow::initMembers()
{
tabWidget = new QTabWidget(this);
searchWidget = new SearchWidget(this);
saleWidget = new SaleWidget(this);
statusBar = new QStatusBar();
setCentralWidget(tabWidget);
setStatusBar(statusBar);
}
void MainWindow::initUI()
{
tabWidget->addTab(searchWidget, "Search");
tabWidget->addTab(saleWidget, "Sale Data");
}
void MainWindow::updateStatusBar(QString status)
{
statusBar->showMessage(status);
}
SearchWidget class:
SearchWidget::SearchWidget(QWidget *parent) : QWidget(parent)
{
connect(goButton, SIGNAL(clicked), this, SLOT(buildQuery()));
}
void SearchWidget::buildQuery()
{
emit searchingStatus("Searching...");
//builds sql query
}
任何有启发性的信息将不胜感激!
我怀疑这不是顺序问题,而是 SQL 查询阻塞了主 GUI 事件循环这一事实:尝试在 emit searchStatus(...)
之后插入对 QApplication::processEvents()
的调用称呼。如果我是正确的,您应该会在数据库搜索完成之前看到状态栏更新。
但是,由于您仍在阻止事件循环,因此在执行数据库调用时您的 GUI 仍会冻结,这不是很好。您可以通过 运行 不同线程上的查询来消除此问题(最简单的方法之一是通过 http://doc.qt.io/qt-5/qtconcurrent.html#run),但请注意您必须担心并发问题(例如,现在您可以单击 go连续多次按钮...)。
所以我遇到的情况是我无法按照我希望的顺序触发几个插槽。
基本设置是我有一个带有状态栏的主窗口,需要根据来自子小部件 (SearchWidget) 的信号进行更新。当单击子小部件上的 "Go" 按钮时,我希望它更新状态栏以显示 "Searching..." 然后执行实际的数据库搜索。但是,我只能在搜索完成并显示在 tablewidget 中后触发 updateStatusBar 插槽。我已经尝试将连接重新安排为适当的顺序,我已经尝试了一个单独的函数,该函数发出状态栏信号,然后发出搜索信号,但似乎没有任何效果。搜索总是先执行,状态栏直到完成后才会改变。
我是新手,但我猜这个问题可能与主窗口和小部件之间的父子关系有关?也许同一个小部件中的插槽以某种方式排列优先级?请参阅下面的基本代码。
主窗口class:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
initMembers();
initUI();
connect(searchWidget, SIGNAL(searchingStatus(QString)), this, SLOT(updateStatusBar(QString)));
}
void MainWindow::initMembers()
{
tabWidget = new QTabWidget(this);
searchWidget = new SearchWidget(this);
saleWidget = new SaleWidget(this);
statusBar = new QStatusBar();
setCentralWidget(tabWidget);
setStatusBar(statusBar);
}
void MainWindow::initUI()
{
tabWidget->addTab(searchWidget, "Search");
tabWidget->addTab(saleWidget, "Sale Data");
}
void MainWindow::updateStatusBar(QString status)
{
statusBar->showMessage(status);
}
SearchWidget class:
SearchWidget::SearchWidget(QWidget *parent) : QWidget(parent)
{
connect(goButton, SIGNAL(clicked), this, SLOT(buildQuery()));
}
void SearchWidget::buildQuery()
{
emit searchingStatus("Searching...");
//builds sql query
}
任何有启发性的信息将不胜感激!
我怀疑这不是顺序问题,而是 SQL 查询阻塞了主 GUI 事件循环这一事实:尝试在 emit searchStatus(...)
之后插入对 QApplication::processEvents()
的调用称呼。如果我是正确的,您应该会在数据库搜索完成之前看到状态栏更新。
但是,由于您仍在阻止事件循环,因此在执行数据库调用时您的 GUI 仍会冻结,这不是很好。您可以通过 运行 不同线程上的查询来消除此问题(最简单的方法之一是通过 http://doc.qt.io/qt-5/qtconcurrent.html#run),但请注意您必须担心并发问题(例如,现在您可以单击 go连续多次按钮...)。