当前位置: 首页 > news >正文

QT(5)

六、多窗口编程详解(Qt框架)


​1. QMessageBox消息对话框(模态交互核心)​

QMessageBox是Qt中用于​​模态交互​​的基础对话框,继承自QDialog,主要用于向用户传递信息或获取简单反馈(如确认、警告等)。其核心特点是​​阻塞式交互​​——用户必须响应对话框(点击按钮)后,程序才会继续执行后续代码。

​1.1 核心特性与常用接口​

QMessageBox通过​​静态成员函数​​直接调用,无需手动创建对象,函数返回值为用户点击的按钮类型(QMessageBox::StandardButton)。常用接口包括:

  •  

    critical():显示严重错误信息(红色标题);

  •  

    information():显示提示信息(蓝色标题);

  •  

    question():显示询问信息(问号图标);

  •  

    warning():显示警告信息(黄色标题)。

​1.2 代码示例:消息对话框的使用​
// dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QMessageBox>
#include <QButtonGroup>namespace Ui {
class Dialog;
}class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private:Ui::Dialog *ui;QButtonGroup *btnGroup;  // 按钮组管理多个按钮private slots:void onButtonClicked(int id);  // 按钮点击槽函数
};#endif // DIALOG_H
// dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);// 初始化按钮组并关联按钮btnGroup = new QButtonGroup(this);btnGroup->addButton(ui->btnQuestion, 1);  // 按钮ID=1btnGroup->addButton(ui->btnInfo, 2);       // 按钮ID=2btnGroup->addButton(ui->btnWarning, 3);    // 按钮ID=3btnGroup->addButton(ui->btnCritical, 4);   // 按钮ID=4// 连接按钮组点击信号到槽函数connect(btnGroup, &QButtonGroup::buttonClicked, this, &Dialog::onButtonClicked);
}Dialog::~Dialog() {delete btnGroup;delete ui;
}void Dialog::onButtonClicked(int id) {switch (id) {case 1: {  // 询问对话框QMessageBox::StandardButton reply = QMessageBox::question(this, "确认", "是否关闭窗口?",QMessageBox::Yes | QMessageBox::No);if (reply == QMessageBox::Yes) close();break;}case 2: {  // 信息对话框QMessageBox::information(this, "提示", "数据加载完成!");break;}case 3: {  // 警告对话框QMessageBox::warning(this, "警告", "输入内容格式错误!");break;}case 4: {  // 错误对话框QMessageBox::critical(this, "错误", "程序异常:缺少必要文件 ***.dll");break;}}
}

​2. QWidget类(窗口基类)​

QWidget是Qt中​​所有窗口和组件的基类​​,既是窗口容器(如主窗口),也是基础组件(如按钮、文本框)的父类。作为窗口时,它具备窗口的基本特性(标题、边框、状态等)。

​2.1 窗口特性控制​

通过成员函数可灵活控制窗口行为:

  •  

    setWindowTitle(const QString&):设置窗口标题;

  •  

    setWindowFlags(Qt::WindowFlags):设置窗口标志(如无边框、置顶);

  •  

    setWindowState(Qt::WindowState):设置窗口状态(最大化、最小化、全屏)。

​2.2 代码示例:自定义窗口属性​
// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>namespace Ui {
class Widget;
}class Widget : public QWidget {Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};#endif // WIDGET_H
// widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 设置窗口标题setWindowTitle("自定义窗口");// 设置窗口标志:无边框 + 置顶setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);// 设置窗口状态:最大化setWindowState(Qt::WindowMaximized);
}Widget::~Widget() {delete ui;
}

​3. parent参数(内存管理与窗口关系)​

在Qt中,parent参数是​​对象树机制​​的核心,用于管理内存生命周期和窗口层级关系:

​3.1 核心作用​
  •  

    ​内存管理​​:若对象A的parent设为对象B,则对象B销毁时,对象A会被自动销毁(无需手动delete);

  •  

    ​窗口层级​​:parentnullptr时,对象是独立窗口;否则是父窗口的子窗口(内嵌显示)。

​3.2 代码示例:parent参数的两种场景​
// 场景1:独立窗口(无parent)
Widget *w = new Widget();  // 主窗口,需手动delete
w->show();// 场景2:子窗口(parent指向主窗口)
Dialog *dlg = new Dialog(w);  // dlg是w的子窗口,w销毁时dlg自动销毁
dlg->show();

​4. QStackedWidget(堆栈窗口)​

QStackedWidget是​​层叠窗口容器​​,用于管理多个子窗口(页面),同一时间仅显示一个页面,常与QListWidget联动实现“选项卡”效果。

​4.1 核心特性​
  •  

    通过addWidget()添加子窗口;

  •  

    通过setCurrentIndex(int)切换显示的页面;

  •  

    与QListWidget联动时,通过currentRowChanged(int)信号触发页面切换。

​4.2 代码示例:堆栈窗口与列表联动​
// dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QStackedWidget>
#include <QListWidget>namespace Ui {
class Dialog;
}class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private:Ui::Dialog *ui;
};#endif // DIALOG_H
// dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);// 初始化堆栈窗口和列表QStringList pages = {"页面1", "页面2", "页面3"};ui->listWidget->addItems(pages);// 添加子窗口到堆栈(假设ui->stackedWidget已设计3个页面)for (int i = 0; i < 3; ++i) {QWidget *page = new QWidget();ui->stackedWidget->addWidget(page);}// 列表选择变化时切换页面connect(ui->listWidget, &QListWidget::currentRowChanged,ui->stackedWidget, &QStackedWidget::setCurrentIndex);
}Dialog::~Dialog() {delete ui;
}

​5. QMainWindow(主窗口类)​

QMainWindow是Qt中​​最适合做主窗口的类​​,内置菜单栏(QMenuBar)、工具栏(QToolBar)、状态栏(QStatusBar)等标准组件,适合开发复杂桌面应用。

​5.1 核心组件​
  •  

    ​菜单栏(QMenuBar)​​:通过addMenu()添加一级菜单,addAction()添加菜单项;

  •  

    ​工具栏(QToolBar)​​:通过addWidget()addAction()添加按钮(通常关联菜单项的QAction);

  •  

    ​状态栏(QStatusBar)​​:通过showMessage()显示临时信息,addWidget()添加固定组件。

​5.2 代码示例:主窗口基础结构​
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onNewTriggered();    // 新建文件槽函数void onOpenCppTriggered();// 打开C++文件槽函数private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);// 构建菜单栏QMenu *fileMenu = ui->menuBar->addMenu("文件");QAction *newAction = fileMenu->addAction("新建");QAction *openCppAction = fileMenu->addAction("打开C++文件");// 构建工具栏(关联菜单项的QAction)ui->toolBar->addAction(newAction);ui->toolBar->addAction(openCppAction);// 连接信号槽connect(newAction, &QAction::triggered, this, &MainWindow::onNewTriggered);connect(openCppAction, &QAction::triggered, this, &MainWindow::onOpenCppTriggered);
}MainWindow::~MainWindow() {delete ui;
}void MainWindow::onNewTriggered() {ui->textEdit->append("新建文件");ui->statusBar->showMessage("新建文件成功", 2000);  // 显示2秒
}void MainWindow::onOpenCppTriggered() {ui->textEdit->append("打开hello.cpp");ui->statusBar->showMessage("已打开hello.cpp");
}

​6. 自定义窗口类​

通过继承QWidget或QDialog,可创建自定义窗口类,封装特定功能(如绘图、数据展示)。

​6.1 创建步骤​
  1.  

    在Qt Creator中右键项目 → “添加新文件” → 选择“Qt设计师界面类”;

  2.  

    设计界面(.ui文件)并生成对应的头文件(.h)和源文件(.cpp);

  3.  

    在自定义类中实现业务逻辑(如事件处理、数据交互)。

​6.2 代码示例:自定义绘图窗口​
// mydialog.h
#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>
#include <QPainter>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog {Q_OBJECTpublic:explicit MyDialog(QWidget *parent = nullptr);~MyDialog();protected:void paintEvent(QPaintEvent *event) override;  // 覆盖绘制事件
};#endif // MYDIALOG_H
// mydialog.cpp
#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MyDialog) {ui->setupUi(this);
}MyDialog::~MyDialog() {delete ui;
}void MyDialog::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);  // 抗锯齿// 绘制背景painter.fillRect(rect(), Qt::lightGray);// 绘制圆形painter.setBrush(Qt::blue);painter.drawEllipse(50, 50, 200, 200);  // (x,y)为左上角,宽高200
}

​7. 对象传值(跨窗口通信)​

Qt中跨窗口传值需通过​​信号槽机制​​或​​成员变量共享​​实现,核心是建立窗口间的关联。

​7.1 父→子传值(成员变量共享)​

父窗口创建子窗口时,通过成员变量保存子窗口指针,直接调用子窗口的公有方法传值。

​7.2 子→父传值(信号槽机制)​

子窗口定义带参数的信号,父窗口连接该信号到自己的槽函数,实现子窗口数据传递到父窗口。

​7.3 代码示例:双向传值​
// dialog.h(父窗口)
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private slots:void onOpenChildClicked();       // 打开子窗口按钮点击void onChildValueChanged(int);   // 子窗口值变化槽函数private:Ui::Dialog *ui;MyDialog *childDlg;  // 子窗口指针
};#endif // DIALOG_H
// dialog.cpp(父窗口)
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);childDlg = nullptr;
}void Dialog::onOpenChildClicked() {if (!childDlg) {childDlg = new MyDialog(this);  // 父窗口为当前窗口connect(childDlg, &MyDialog::valueChanged, this, &Dialog::onChildValueChanged);}childDlg->show();
}void Dialog::onChildValueChanged(int value) {ui->progressBar->setValue(value);  // 父窗口进度条同步更新
}
// mydialog.h(子窗口)
#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>
#include <QSlider>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog {Q_OBJECTpublic:explicit MyDialog(QWidget *parent = nullptr);~MyDialog();signals:void valueChanged(int);  // 值变化信号private slots:void onSliderMoved(int);  // 滑块移动槽函数private:Ui::MyDialog *ui;
};#endif // MYDIALOG_H
// mydialog.cpp(子窗口)
#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MyDialog) {ui->setupUi(this);connect(ui->slider, &QSlider::valueChanged, this, &MyDialog::onSliderMoved);
}void MyDialog::onSliderMoved(int value) {emit valueChanged(value);  // 发射信号传递值
}MyDialog::~MyDialog() {delete ui;
}

​8. 事件机制(底层交互)​

Qt的事件机制是窗口响应用户操作(如点击、键盘输入)的核心,通过​​事件循环​​传递事件,开发者可通过覆盖基类事件函数实现自定义行为。

​8.1 常见事件类型​
  •  

    ​鼠标事件​​:mousePressEvent()(按下)、mouseReleaseEvent()(释放)、mouseMoveEvent()(移动);

  •  

    ​键盘事件​​:keyPressEvent()(按键按下)、keyReleaseEvent()(按键释放);

  •  

    ​绘制事件​​:paintEvent()(窗口重绘);

  •  

    ​焦点事件​​:focusInEvent()(获得焦点)、focusOutEvent()(失去焦点);

  •  

    ​关闭事件​​:closeEvent()(窗口关闭前触发)。

​8.2 代码示例:键盘控制进度条​
// dialog.h
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QKeyEvent>namespace Ui {
class Dialog;
}class Dialog : public QDialog {Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();protected:void keyPressEvent(QKeyEvent *event) override;  // 覆盖键盘按下事件
};#endif // DIALOG_H
// dialog.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) {ui->setupUi(this);
}void Dialog::keyPressEvent(QKeyEvent *event) {switch (event->key()) {case Qt::Key_Up:    // 上箭头:进度条+10ui->progressBar->setValue(ui->progressBar->value() + 10);break;case Qt::Key_Down:  // 下箭头:进度条-10ui->progressBar->setValue(ui->progressBar->value() - 10);break;case Qt::Key_Space: // 空格:重置进度条ui->progressBar->setValue(0);break;}QDialog::keyPressEvent(event);  // 传递事件给父类处理
}Dialog::~Dialog() {delete ui;
}

http://www.dtcms.com/a/395951.html

相关文章:

  • 仓颉语言宏(Cangjie Macros)全面解析:从基础到实战
  • linux RAID存储技术
  • 【每日一问】交流电和直流电有什么区别?
  • Postman使用指南
  • 软件架构面试题及答案
  • 【STM32】基于串口的bootloader
  • 【STM32】中断
  • how many penguins in ur linux你有几只企鹅呢?
  • windows1122h2怎么升级24h2
  • ansible-playbook的使用
  • Zabbix7 监控USG6300E 并发IPv4会话数
  • Qt中使用多线程的范式
  • c语言10:指针加减指针的那些事儿
  • 数据库成为突破口:勒索软件攻击始于暴露的Oracle服务器
  • PT100铂电阻高精度原理图设计,已量产(温度传感器)
  • 推荐 6 个本周 yyds 的 GitHub 项目。
  • 内存释放机制以及栈和堆(c++)
  • PCL基础:点云体积计算,若需更精确的体积估算,可采用 Alpha Shape 或 Marching Cubes 等方法重建表面后再进行积分计算。
  • OSPF实验-20250922
  • Python控制流概述
  • 【LLM学习】【Ollama】四、MCP
  • 5G RedCap模组:轻量化5G技术的商业化实现
  • 深入探索卷积神经网络:从基础到高级架构(二)
  • 什么是DeepSeek-V3.1-Terminus版本?
  • 【C语言代码】堵车问题
  • A Survey of Zero-Shot Learning: Settings, Methods, and Applications
  • Windows连接Linux做开发的安装和配置
  • 【C++】lambda表达式类型相关问题
  • HTML应用指南:利用GET请求获取全国大疆限飞区域shp图层信息
  • Nginx进阶(二)