小项目实验:模式对话框对线程的影响

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)。


🧩 常见应用场景

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1135919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于python的艺术作品展示平台 艺术家在线交流系统 关注z50di044

目录基于Python的艺术作品展示平台与艺术家在线交流系统关于博主开发技术路线相关技术介绍核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;基于Python的艺术作品展示平台与艺术家在线交流系统 Python作为一种功能强大…

一文说清OTG如何实现移动设备数据扩展

用一根线&#xff0c;让手机变电脑&#xff1a;深度拆解OTG如何实现移动设备“外设自由” 你有没有过这样的经历&#xff1f; 急需把一份PPT拷进会议室的投影仪U盘&#xff0c;却发现只有手机里存着文件&#xff1b;孩子想在平板上连个键盘打字练作文&#xff0c;可设备只有一…

微服务架构中,网关层和服务层的限流策略如何协同工作

在微服务架构中&#xff0c;网关层与服务层的限流并非相互替代&#xff0c;而是分工明确的协同关系。它们共同构成了一道纵深防御体系&#xff0c;确保系统稳定。 &#x1f3af; 角色分工&#xff1a;各司其职层级核心职责实现方案网关层全局入口防护&#xff1a;作为系统的唯一…

opencv 常用接口

1.opencv 常用接口OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个广泛使用的开源计算机视觉和机器学习软件库&#xff0c;支持多种编程语言&#xff08;如 C、Python、Java 等&#xff09;&#xff0c;其中 Python 接口最为常用。以下是 OpenCV 中一…

USB转串口驱动中的D+与D-上拉电阻设计核心要点

USB转串口设计中D上拉电阻的“生死线”&#xff1a;一枚1.5kΩ电阻为何决定产品成败&#xff1f;你有没有遇到过这样的场景&#xff1a;一个USB转串口模块&#xff0c;在自家电脑上插拔顺畅、通信稳定&#xff0c;可一拿到客户现场&#xff0c;就频频掉线、无法识别&#xff1f…

Redis+Lua实现分布式限流时,确保高可用性和性能优化

要确保基于 RedisLua 的分布式限流器的高可用与高性能&#xff0c;可以从 Redis 架构、Lua 脚本、降级策略、性能优化 和 运维监控 五个核心方面入手。&#x1f6e1;️ 高可用&#xff1a;保障 Redis 稳定运行Redis 部署架构 主从 哨兵&#xff1a;实现故障自动切换&#xff0…

图解说明UVC协议中视频数据包的分段与重组过程

深入UVC协议&#xff1a;视频数据是如何在USB上“分块传输、无缝拼接”的&#xff1f;你有没有想过&#xff0c;一个小小的USB摄像头是怎么把1080p甚至4K的高清画面实时传到电脑上的&#xff1f;毕竟一帧YUY2格式的1080p图像就接近4MB&#xff0c;而USB一次最多只能传1024字节—…

一文说清Multisim在Win10和Win11的安装流程

Multisim安装全攻略&#xff1a;Win10/Win11避坑指南&#xff0c;一次搞定不翻车你是不是也遇到过这样的情况&#xff1f;下载好Multisim安装包&#xff0c;满怀期待地点开setup.exe——结果弹出“Windows已保护你的电脑”警告&#xff1b;好不容易绕过去&#xff0c;安装到一半…

一文说清Multisim14.0在模拟信号处理中的应用

用Multisim14.0打通模拟信号处理的“任督二脉”你有没有过这样的经历&#xff1f;花了一周时间画好电路&#xff0c;焊好PCB&#xff0c;通电一试——没输出。换芯片、改电阻、调电源……折腾三天&#xff0c;最后发现是运放接反了反馈网络。在模拟电路的世界里&#xff0c;这种…

巴菲特的企业价值链优化

巴菲特的企业价值链优化关键词&#xff1a;巴菲特、企业价值链、优化策略、价值创造、投资理念摘要&#xff1a;本文深入探讨了巴菲特的企业价值链优化理念。通过剖析巴菲特的投资哲学和对企业运营的独特见解&#xff0c;阐述了企业价值链的核心概念及其重要性。详细介绍了巴菲…

基于OpenMV的作物病害识别系统:实战案例详解

用一块指甲盖大小的相机&#xff0c;让农田自己“看病”&#xff1f;——OpenMV作物病害识别实战手记 去年夏天在云南一个草莓种植基地&#xff0c;我亲眼见过一位老农蹲在一排排藤蔓间&#xff0c;顶着烈日翻看叶片&#xff0c;一待就是半天。他告诉我&#xff1a;“要是能早点…

Redis集群部署方案对比:主从哨兵 vs Cluster,各自的适用场景和配置要点

在 Redis 的部署方案中&#xff0c;主从哨兵和 Cluster 是两种主流选择。 &#x1f3db;️ 主从 哨兵模式 (Master-Slave Sentinel) 此方案是在主从复制基础上&#xff0c;增加了哨兵进程以实现自动故障转移&#xff0c;是官方推荐的高可用方案之一。 核心架构 主从复制&…

hbuilderx制作网页结合Bootstrap响应式开发全面讲解

用 HBuilderX 搭配 Bootstrap 做响应式网页&#xff1a;从零开始的实战指南 你有没有遇到过这样的情况&#xff1f;辛辛苦苦写好的网页&#xff0c;在自己电脑上看得很完美&#xff0c;结果一拿到手机上就“炸了”——文字小得看不见、图片溢出屏幕、导航栏挤成一团……这其实…

opensbi中plic中断控制逻辑使能

你提供的这两个函数是 PLIC 控制器中中断使能位&#xff08;IE, Interrupt Enable&#xff09; 的核心读写接口&#xff0c;负责精准定位并操作指定上下文、指定中断块的 PLIC 使能寄存器&#xff0c;我会从功能、地址计算逻辑、参数含义、使用场景四个维度拆解&#xff0c;帮你…

计算机行业的本质

1.概述计算机行业的本质&#xff0c;有两种最重要的本质,一个if else while&#xff1b;一个是结构关系&#xff0c;像是数据库的关系表。任何程序的运转无法是 if else while 控制具体的运算行为&#xff0c;这行为可以是数学运算&#xff0c;可以是io的写入&#xff0c;可以是…

救命神器!8款AI论文软件测评:研究生毕业论文痛点全解

救命神器&#xff01;8款AI论文软件测评&#xff1a;研究生毕业论文痛点全解 2026年AI论文工具测评&#xff1a;为何要关注这些“救命神器” 在研究生阶段&#xff0c;撰写毕业论文不仅是学术能力的体现&#xff0c;更是时间与精力的巨大挑战。从选题构思到文献检索&#xff0c…

PyQt上位机界面构建:超详细版布局管理讲解

PyQt上位机界面构建&#xff1a;从零掌握专业级布局管理在工业自动化、嵌入式调试和数据采集系统中&#xff0c;上位机软件是连接操作人员与底层设备的“神经中枢”。它不仅要稳定可靠地完成通信控制任务&#xff0c;更要提供清晰直观的操作体验。一个结构混乱、缩放错乱的界面…

Packet Tracer中RIP路由更新过程动态追踪指南

用Packet Tracer“看懂”RIP&#xff1a;从路由更新到网络收敛的全过程追踪你有没有过这样的经历&#xff1f;在学习动态路由协议时&#xff0c;老师讲得头头是道——“路由器会周期性广播自己的路由表”、“跳数加一后转发”、“最终实现全网收敛”……但这些过程到底长什么样…

MySQL/MongoDB

MySQL 和 MongoDB 是两种非常流行的数据库系统&#xff0c;但它们在设计理念、数据模型、使用场景等方面有显著差异。以下是它们的主要对比&#xff1a; 1. 类型 MySQL&#xff1a;关系型数据库&#xff08;RDBMS&#xff09;&#xff0c;基于 SQL&#xff08;结构化查询语言&…

提供基于comsol中相场方法模拟多孔介质两相驱替(水气、油水等等)的算例(也可以定做水平集驱...

提供基于comsol中相场方法模拟多孔介质两相驱替&#xff08;水气、油水等等&#xff09;的算例&#xff08;也可以定做水平集驱替的算例&#xff09;&#xff0c;可在此基础上学会利用comsol软件进行两相流驱替的模拟&#xff0c;拓展研究&#xff0c;具体参考算例附后。 附赠基…