【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
? ? ? ? 软件编写的场景中,有一种情况很常见,但是不好处理,那就是子窗口在进行业务处理的时候需要通知父窗口来更新进度条。这里面势必会涉及到阻塞的问题,一般处理起来比较麻烦。但是如果用qt来实现的话,其实就很简单。利用它自身的emit和signals机制就可以完美解决这个问题。下面,我们就来看下qt是如何处理这个问题的。
? ? ? ? 老规矩,首先还是创建一个qt基础工程。
? ? ? ? 头文件中目前需要有两个窗口。一个是主窗口,一个是子窗口。在主窗口上面还有两个控件,一个是按钮,一个是进度条。按下按钮就会弹出子窗口。此外主窗口还有两个slots函数,一个是按钮的回调,一个是进度条的回调。到时候进度条的回调函数会和子窗口的signals做一个绑定。
? ? ? ? 子窗口中只有一个按钮,此外它也只有一个slots函数。不过相比较主窗口,它会多一个signals,到时候这个signals回和主窗口的进度条回调函数做一个connect结合。
#pragma once
#include <QtWidgets/QMainWindow>
#include <QProgressBar>
#include <QPushButton>
#include <QDialog>
#include <QVBoxLayout>
#include "ui_QtWidgetsApplication.h"
// about main window
class SubWindow;
class QtWidgetsApplication : public QMainWindow
{
Q_OBJECT
public:
QtWidgetsApplication(QWidget *parent = nullptr);
~QtWidgetsApplication();
private:
Ui::QtWidgetsApplicationClass ui;
public slots:
void openSubWindow();
void updateProgressBar(int value);
private:
QProgressBar *progressBar;
QPushButton *openSubWindowButton;
};
// about sub window
class SubWindow : public QDialog
{
Q_OBJECT
public:
SubWindow(QWidget *parent = nullptr);
signals:
void updateProgressBar(int value);
private slots:
void updateProgressBarSlot();
private:
QPushButton *updateButton;
};
? ? ? ? 头文件设计好了,自然就要开始源文件的设计了。这次源文件除了常规的控件布局和按钮回调,有三个地方值得一说。第一,主窗口的按钮回调中,会临时生成一个SubWindow,同时把这个SubWindow显示出来;第二,SubWindow生成的时候,会把它的signals和主窗口的进度条更新做一个connect;第三,子窗口中按钮回调的时候,会通过emit signals的方法,促请主窗口更新进度条。
#include <Windows.h>
#include <QThread>
#include <QTimer>
#include "QtWidgetsApplication.h"
// about main window
QtWidgetsApplication::QtWidgetsApplication(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
progressBar = new QProgressBar(this);
progressBar->setMaximum(100);
openSubWindowButton = new QPushButton("OpenSubWindow", this);
connect(openSubWindowButton, &QPushButton::clicked, this, &QtWidgetsApplication::openSubWindow);
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
layout->addWidget(progressBar);
layout->addWidget(openSubWindowButton);
setCentralWidget(centralWidget);
}
void QtWidgetsApplication::openSubWindow()
{
SubWindow *subWindow = new SubWindow(this);
connect(subWindow, &SubWindow::updateProgressBar, this, &QtWidgetsApplication::updateProgressBar);
subWindow->show();
}
void QtWidgetsApplication::updateProgressBar(int value)
{
progressBar->setValue(value);
}
QtWidgetsApplication::~QtWidgetsApplication()
{}
// about sub window
SubWindow::SubWindow(QWidget *parent)
: QDialog(parent)
{
updateButton = new QPushButton("Update Progress", this);
connect(updateButton, &QPushButton::clicked, this, &SubWindow::updateProgressBarSlot);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(updateButton);
}
void SubWindow::updateProgressBarSlot()
{
for (int value = 0; value <= 100; value += 10)
{
Sleep(100);
emit updateProgressBar(value);
}
}
? ? ? ? 代码编写完了,测试相对比较简单。首先看看编译有没有问题,窗口能不能正常显示。如果可以正常显示,那么主窗口有没有问题,按钮被按下去的时候,子窗口有没有弹出。子窗口的按钮被按下去的时候,主窗口的进度条会不会更新。这一切都没问题的话,就代表基本达到了我们自己的设计要求了。