深圳市网站建设_网站建设公司_后端工程师_seo优化
2026/1/9 19:47:11 网站建设 项目流程

1.概要

模式对话框,会截断主线程的执行。所以应该快速的退出,不能时间过长。且这段时间,给主线程发的信号都不会响应。

实验1:

现在想做这样的一个实验,打开一个弹出,弹窗结束后,会返回主线程执行一个处理。这个处理是否会受到打开的弹出模式影响,比如show()和模式对话框是否有差别。

结论:没有差别

实验2:

当打开弹窗的时候,如果这个弹窗的父亲窗体不是当前的主画面,会有什么影响,会不会显示在屏幕的最前面、

结论:无论是否把当前画面作为弹窗的父对象,弹窗都会显示在窗口的最前面。但如果不是将当前的主窗体设置为父对象,那么第二次触发显示的时候,不会是窗体的最前面。

如果要在最前面显示,需要设置raise();

2.内容

1.工程结构

1.结构

2.工程文件

cmake_minimum_required(VERSION 3.5) project(untitled3 VERSION 0.1 LANGUAGES CXX) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) set(PROJECT_SOURCES main.cpp mainwindow.cpp mainwindow.h mainwindow.ui ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(untitled3 MANUAL_FINALIZATION ${PROJECT_SOURCES} dialog.h dialog.cpp dialog.ui ) # Define target properties for Android with Qt 6 as: # set_property(TARGET untitled3 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR # ${CMAKE_CURRENT_SOURCE_DIR}/android) # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation else() if(ANDROID) add_library(untitled3 SHARED ${PROJECT_SOURCES} ) # Define properties for Android with Qt 5 after find_package() calls as: # set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android") else() add_executable(untitled3 ${PROJECT_SOURCES} ) endif() endif() target_link_libraries(untitled3 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. # If you are developing for iOS or macOS you should consider setting an # explicit, fixed bundle identifier manually though. if(${QT_VERSION} VERSION_LESS 6.1.0) set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.untitled3) endif() set_target_properties(untitled3 PROPERTIES ${BUNDLE_ID_OPTION} MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE WIN32_EXECUTABLE TRUE ) include(GNUInstallDirs) install(TARGETS untitled3 BUNDLE DESTINATION . LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(untitled3) endif()

2.代码

1.主函数

#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }

2.主窗体

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include "dialog.h" #include <QProgressBar> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: void show_QProgressBar(); private slots: //打开弹窗 void on_pushButton_clicked(); //弹窗关闭返回的值 void slo_fis_ret(int); //打开进度条窗体-槽 void slo_test(); //打开进度条 void on_pushButton_2_clicked(); private: Ui::MainWindow *ui; //弹窗 Dialog* dialog; //进度条控件 QProgressBar* qb; signals: //打开进度条信号 void sig_test(); }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "./ui_mainwindow.h" #include <QProgressBar> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); dialog = new Dialog(this); connect(dialog,&Dialog::finished,this,&MainWindow::slo_test); //如果不讲父窗体设为父对象,进度条第一次显示会在窗口最前面,但是第二次显示就不在最前面了。 qb = new QProgressBar(); //qb = new QProgressBar(this); } MainWindow::~MainWindow() { delete ui; } //打开弹窗 void MainWindow::on_pushButton_clicked() { //两种无差别,不会对返回后的逻辑有影响。但exec执行期间,主线程会被停止。 //dialog->show(); dialog->exec(); } //弹窗关闭返回的值 void MainWindow::slo_fis_ret(int ret){ emit sig_test(); } //打开进度条窗体-槽 void MainWindow::slo_test(){ show_QProgressBar(); } //进度条窗体显示 void MainWindow::show_QProgressBar(){ qb->show(); qb->raise(); } //打开进度条 void MainWindow::on_pushButton_2_clicked() { show_QProgressBar(); }
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="pushButton"> <property name="geometry"> <rect> <x>100</x> <y>100</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>打开弹出</string> </property> </widget> <widget class="QLineEdit" name="lineEdit"> <property name="geometry"> <rect> <x>330</x> <y>100</y> <width>113</width> <height>21</height> </rect> </property> </widget> <widget class="QPushButton" name="pushButton_2"> <property name="geometry"> <rect> <x>100</x> <y>150</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>打开进度条</string> </property> </widget> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>21</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>

3.弹窗

#ifndef DIALOG_H #define DIALOG_H #include <QDialog> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = nullptr); ~Dialog(); private slots: void on_buttonBox_accepted(); void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::Dialog *ui; }; #endif // DIALOG_H
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) , ui(new Ui::Dialog) { ui->setupUi(this); } Dialog::~Dialog() { delete ui; } void Dialog::on_buttonBox_accepted() { } //确定 void Dialog::on_pushButton_clicked() { accept(); } //取消 void Dialog::on_pushButton_2_clicked() { reject(); }

<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Dialog</class> <widget class="QDialog" name="Dialog"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>257</width> <height>121</height> </rect> </property> <property name="windowTitle"> <string>Dialog</string> </property> <widget class="QPushButton" name="pushButton"> <property name="geometry"> <rect> <x>30</x> <y>70</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>确定</string> </property> </widget> <widget class="QPushButton" name="pushButton_2"> <property name="geometry"> <rect> <x>150</x> <y>70</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>取消</string> </property> </widget> </widget> <resources/> <connections/> </ui>

3.运行结果

1.主页

2.打开弹窗

3.弹窗进度条

3.关联链接

4.关联知识

1.QDialog

QDialog是 Qt 框架中用于创建对话框窗口的类,继承自QWidget。它通常用于实现模态(modal)或非模态(modeless)的用户交互窗口,比如登录窗口、设置窗口、消息提示等。


基本用法

1. 包含头文件

#include <QDialog>

2. 创建一个简单的自定义对话框类

// MyDialog.h #ifndef MYDIALOG_H #define MYDIALOG_H #include <QDialog> #include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> class MyDialog : public QDialog { Q_OBJECT public: explicit MyDialog(QWidget *parent = nullptr); private slots: void onOkClicked(); private: QLineEdit *lineEdit; QPushButton *okButton; }; #endif // MYDIALOG_H
// MyDialog.cpp #include "MyDialog.h" #include <QMessageBox> MyDialog::MyDialog(QWidget *parent) : QDialog(parent) { lineEdit = new QLineEdit(this); okButton = new QPushButton("OK", this); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(lineEdit); layout->addWidget(okButton); setLayout(layout); connect(okButton, &QPushButton::clicked, this, &MyDialog::onOkClicked); } void MyDialog::onOkClicked() { QString text = lineEdit->text(); if (text.isEmpty()) { QMessageBox::warning(this, "警告", "输入不能为空!"); } else { accept(); // 关闭对话框并返回 QDialog::Accepted } }

3. 在主窗口中使用对话框

// mainwindow.cpp 中调用 MyDialog dialog(this); if (dialog.exec() == QDialog::Accepted) { // 用户点击了 OK }
  • exec():以模态方式显示对话框(阻塞当前窗口)。
  • show():以非模态方式显示(不阻塞)。

注意:非模态对话框一般需要动态分配(new),并设置setAttribute(Qt::WA_DeleteOnClose),否则可能造成内存泄漏或提前析构。


常用方法

方法说明
exec()显示模态对话框,返回AcceptedRejected
show()显示非模态对话框
accept()接受对话框,关闭并返回Accepted
reject()拒绝对话框,关闭并返回Rejected
done(int r)通用关闭函数,可指定返回值
setModal(true/false)设置是否为模态

示例:非模态对话框

MyDialog *dialog = new MyDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动 delete dialog->show(); // 非模态

内置标准对话框(推荐优先使用)

Qt 提供了许多现成的对话框:

  • QMessageBox:消息提示
  • QFileDialog:文件选择
  • QInputDialog:简单输入
  • QColorDialog:颜色选择
  • QFontDialog:字体选择

例如:

QString text = QInputDialog::getText(this, "输入", "请输入姓名:");

2.如何在QDialog中实现文件选择功能

QDialog中实现文件选择功能,最常用的方式是使用 Qt 提供的标准对话框类QFileDialog。你可以将文件选择逻辑集成到自定义的QDialog中,例如让用户点击一个按钮后弹出文件选择对话框,并将选中的文件路径显示在界面上(如QLineEditQLabel)。

下面是一个完整的示例,展示如何在自定义QDialog中实现文件选择功能:


✅ 示例:在 QDialog 中添加“选择文件”按钮

1. 头文件FileSelectDialog.h
#ifndef FILESELECTDIALOG_H #define FILESELECTDIALOG_H #include <QDialog> #include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> #include <QFileDialog> class FileSelectDialog : public QDialog { Q_OBJECT public: explicit FileSelectDialog(QWidget *parent = nullptr); // 可选:提供获取所选文件路径的接口 QString selectedFile() const; private slots: void onBrowseButtonClicked(); private: QLineEdit *filePathEdit; QPushButton *browseButton; QPushButton *okButton; }; #endif // FILESELECTDIALOG_H

2. 源文件FileSelectDialog.cpp
#include "FileSelectDialog.h" #include <QMessageBox> FileSelectDialog::FileSelectDialog(QWidget *parent) : QDialog(parent) { setWindowTitle("选择文件"); filePathEdit = new QLineEdit(this); filePathEdit->setReadOnly(true); // 只读,防止手动输入错误路径 browseButton = new QPushButton("浏览...", this); okButton = new QPushButton("确定", this); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(new QLabel("请选择一个文件:")); layout->addWidget(filePathEdit); layout->addWidget(browseButton); layout->addWidget(okButton); setLayout(layout); // 连接信号槽 connect(browseButton, &QPushButton::clicked, this, &FileSelectDialog::onBrowseButtonClicked); connect(okButton, &QPushButton::clicked, this, &QDialog::accept); } void FileSelectDialog::onBrowseButtonClicked() { // 弹出文件选择对话框 QString fileName = QFileDialog::getOpenFileName( this, "选择文件", // 对话框标题 QDir::homePath(), // 初始目录(可选) "所有文件 (*.*);;文本文件 (*.txt);;图像文件 (*.png *.jpg)" // 文件过滤器 ); if (!fileName.isEmpty()) { filePathEdit->setText(fileName); } } QString FileSelectDialog::selectedFile() const { return filePathEdit->text(); }

3. 在主窗口中使用该对话框(例如在MainWindow中)
// mainwindow.cpp FileSelectDialog dialog(this); if (dialog.exec() == QDialog::Accepted) { QString file = dialog.selectedFile(); if (!file.isEmpty()) { qDebug() << "用户选择了文件:" << file; // 在这里处理文件,比如加载、解析等 } }

🔧 补充说明

  • QFileDialog::getOpenFileName():用于选择单个已存在的文件
  • 如果要选择多个文件,使用QFileDialog::getOpenFileNames()
  • 如果要保存文件(指定新文件名),使用QFileDialog::getSaveFileName()
  • 如果要选择目录,使用QFileDialog::getExistingDirectory()

例如,选择多个文件:

QStringList files = QFileDialog::getOpenFileNames( this, "选择多个文件", QDir::homePath(), "图像文件 (*.png *.jpg)" );

💡 小技巧

  • 可以将filePathEdit的内容绑定到类成员变量,避免重复调用text()
  • 若希望对话框非模态(不阻塞主窗口),改用show()并注意内存管理(建议配合setAttribute(Qt::WA_DeleteOnClose))。

如果你有更具体的需求,比如:

  • 限制只能选择特定类型文件(如.csv
  • 自动预览文件内容
  • 在对话框中嵌入QTreeView实现自定义文件浏览器

3.QProgressBar

QProgressBar是 Qt 框架中用于显示任务进度的控件,常用于文件传输、数据加载、安装过程等需要可视化进度的场景。


📌 基本用法(C++)

1.头文件

#include <QProgressBar>

2.常用属性与方法

方法说明
void setMinimum(int minimum)设置最小值(默认为 0)
void setMaximum(int maximum)设置最大值(默认为 100)
void setRange(int minimum, int maximum)同时设置最小和最大值
void setValue(int value)设置当前进度值
int value() const获取当前值
void setOrientation(Qt::Orientation)设置方向(水平/垂直,默认水平)
void setTextVisible(bool visible)是否显示百分比文本(默认 true)
QString format() const/setFormat(const QString &)自定义进度文本格式

💡 当minimum == maximum时,进度条进入“繁忙”模式(无限循环动画),适用于未知总进度的情况。


3.简单示例:水平进度条

#include <QApplication> #include <QProgressBar> #include <QTimer> #include <QWidget> #include <QVBoxLayout> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; QProgressBar *progressBar = new QProgressBar(&window); progressBar->setRange(0, 100); // 可省略,默认就是 0~100 progressBar->setValue(0); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(progressBar); window.setLayout(layout); window.resize(300, 80); window.show(); // 模拟进度增加 QTimer *timer = new QTimer(&window); int value = 0; QObject::connect(timer, &QTimer::timeout, [&]() { value += 5; progressBar->setValue(value); if (value >= 100) { timer->stop(); } }); timer->start(200); // 每 200ms 更新一次 return app.exec(); }

4.“繁忙”模式(不确定进度)

progressBar->setRange(0, 0); // 或 setMinimum(0); setMaximum(0); // 此时进度条会显示循环动画,表示任务正在进行但无法确定完成时间

5.自定义文本格式

progressBar->setFormat("已完成 %p% (%v/%m)"); // %p = 百分比,%v = 当前值,%m = 最大值 // 默认格式通常是 "%p%"

6.垂直进度条

progressBar->setOrientation(Qt::Vertical);

⚠️ 注意事项

  • 线程安全:不要在非 GUI 线程中直接调用setValue()。若需从工作线程更新进度,请使用信号槽机制(跨线程连接)。

    示例:

    // 工作线程 emit progressUpdated(int value); connect(workerThread, &Worker::progressUpdated, progressBar, &QProgressBar::setValue);
  • 性能:频繁更新(如每毫秒)可能导致界面卡顿,建议合理控制更新频率(如每 50~100ms)。


🧩 常见应用场景

  • 文件复制/下载进度
  • 数据库导入/导出
  • 安装向导步骤
  • 后台计算任务反馈

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询