Qt::WA_QuitOnClose用法

本文详细探讨了Qt框架中关于窗口关闭导致应用程序退出的行为。默认情况下,当最后一个具有Qt::WA_QuitOnClose属性的窗口关闭时,应用会退出。通过设置QtWidgetsApplication1的Qt::WA_QuitOnClose为false,可以改变这一行为,使得关闭特定窗口时不退出程序。实验展示了不同设置下关闭窗口的顺序如何影响程序退出的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Qt官方助手对该标志的解释如下:

Makes Qt quit the application when the last widget with the attribute set has accepted closeEvent(). This behavior can be modified with the QApplication::quitOnLastWindowClosed property. By default this attribute is set for all widgets of type Qt::Window.

大意是:

  当最后一个设置了本属性的窗体部件关闭时(即接受了closeEvent()事件)退出应用程序。这个属性可以被QApplication::quitOnLastWindowClosed函数修改。对所有类型为Qt::Window.的窗体,这个属性默认被设置为true。

如下:

#include "QtWidgetsApplication1.h"
#include "QtTestWidget.h"
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    setWindowTitle("WidgetsApplication1");
   // setAttribute(Qt::WA_QuitOnClose, false);

    m_pTestWidget = new QtTestWidget();
    m_pTestWidget->show();
}

QtWidgetsApplication1::~QtWidgetsApplication1()
{
    
}



其中 m_pTestWidget是QtWidgetsApplication1的成员变量,类型为:QtTestWidget。QtTestWidget.cpp如下:

#include "QtTestWidget.h"

QtTestWidget::QtTestWidget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	setWindowTitle("TestWidget"); 

   // setAttribute(Qt::WA_QuitOnClose, false);
}

QtTestWidget::~QtTestWidget()
{
}

 

弹出标题为:WidgetsApplication1、TestWidget两个窗体。按Qt助手的解释:这两个窗体的Qt::WA_QuitOnClose默认都为true,所以先关闭其中任何一个窗体,程序不会退出,只有当最后一个窗体关闭时,应用程序才退出。

  当将QtWidgetsApplication1.cpp构造函数中的setAttribute(Qt::WA_QuitOnClose, false);注释去掉,则:

a):关闭WidgetsApplication1窗体,程序不退出关闭TestWidget窗体,程序才退出。因为此时WidgetsApplication1窗体的Qt::WA_QuitOnClose为false,即剔除了该属性;TestWidget窗体的Qt::WA_QuitOnClose依然为true,即TestWidget窗体是包含Qt::WA_QuitOnClose属性的最后一个窗体,当最后一个包含Qt::WA_QuitOnClose属性的窗体退出时,程序退出。

b):先关闭TestWidget窗体,程序退出。道理同a)条目所述。

  当将QtWidgetsApplication1.cpp、QtTestWidget.cpp构造函数中的setAttribute(Qt::WA_QuitOnClose, false);注释都去掉,无论先关闭哪个窗体或两个窗体都关闭,应用程序都不会退出

#ifndef MEASUREWIDGET_H #define MEASUREWIDGET_H #include <QWidget> namespace Ui { class MeasureWidget; } class MeasureWidget : public QWidget { Q_OBJECT public: explicit MeasureWidget(QWidget *parent = nullptr); ~MeasureWidget(); protected: void closeEvent(QCloseEvent *e); void changeEvent(QEvent *event); signals: void sig_close(); void sig_set(QString unit, QString pixel); private slots: void slot_btn_set_clicked(); public slots: void slot_pos_update(int pos1_x, int pos1_y, int pos2_x, int pos2_y); private: Ui::MeasureWidget *ui; double pixel = 1.0; double len_h = 0.0; double len_v = 0.0; double len_c = 0.0; }; #endif // MEASUREWIDGET_H #include “measurewidget.h” #include “ui_measurewidget.h” MeasureWidget::MeasureWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MeasureWidget) { ui->setupUi(this); this->setAttribute(Qt::WA_QuitOnClose, false); this->setWindowFlag(Qt::Window); ui->com_unit->insertItems(0, QStringList()<< "m"); ui->com_unit->setCurrentIndex(0); connect(ui->btn_set, &QPushButton::clicked, this, &MeasureWidget::slot_btn_set_clicked); } MeasureWidget::~MeasureWidget() { } void MeasureWidget::closeEvent(QCloseEvent *e) { emit sig_close(); QWidget::closeEvent(e); } void MeasureWidget::changeEvent(QEvent *event) { if(event->type() == QEvent::LanguageChange){ this->ui->retranslateUi(this); } QWidget::changeEvent(event); } void MeasureWidget::slot_btn_set_clicked() { if(!ui->ledit_pixel->text().isEmpty()){ pixel = ui->ledit_pixel->text().toDouble(); if(pixel > 0){ ui->lab_len_horizontal->setText(QString::asprintf("%.2f", len_h * pixel)); ui->lab_len_vertical->setText(QString::asprintf("%.2f", len_v * pixel)); ui->lab_len_cartesian->setText(QString::asprintf("%.2f", len_c * pixel)); emit sig_set(ui->com_unit->currentText(), ui->ledit_pixel->text()); } } } void MeasureWidget::slot_pos_update(int pos1_x, int pos1_y, int pos2_x, int pos2_y) { len_h = abs(pos1_x - pos2_x)+1; len_v = abs(pos1_y - pos2_y)+1; len_c = sqrt(pow(len_h,2) + pow(len_v,2)); ui->lab_pos_start->setText(QString("(%1,%2)").arg(pos1_x).arg(pos1_y)); ui->lab_pos_end->setText(QString("(%1,%2)").arg(pos2_x).arg(pos2_y)); ui->lab_len_horizontal->setText(QString::asprintf("%.2f", len_h * pixel)); ui->lab_len_vertical->setText(QString::asprintf("%.2f", len_v * pixel)); ui->lab_len_cartesian->setText(QString::asprintf("%.2f", len_c * pixel)); } 解析并添加注释
最新发布
03-18
<think>好的,用户让我解析并添加注释到他们的Qt代码。首先,我需要仔细看看他们提供的头文件和实现文件的内容。用户之前的问题是关于QRect::width()是否返回像素,现在他们展示的是一个MeasureWidget的类,可能用于测量长度,涉及到单位转换和坐标处理。 首先,我应该分析头文件MeasureWidget.h。这个类继承自QWidget,包含UI的命名空间,有构造函数、析构函数,重写了closeEvent和changeEvent。还有信号和槽,比如sig_close、sig_set,以及一些私有槽函数和变量。看起来这个控件是用来显示和设置测量单位的,可能用于图像处理或绘图应用中的实际长度计算。 接下来是MeasureWidget.cpp的实现。构造函数中设置了UI,添加了单位选项,连接了按钮点击的槽函数。closeEvent发送关闭信号,changeEvent处理语言切换。slot_btn_set_clicked处理设置像素比例,并更新显示的长度值。slot_pos_update根据坐标更新水平和垂直长度,并计算笛卡尔距离。 用户的需求可能是希望理解这段代码的结构,或者需要帮助添加注释以便维护。他们可能不太清楚某些部分的功能,比如为什么在计算长度时加1,或者sig_set信号的作用。需要解释每个部分的作用,特别是涉及单位转换和像素计算的地方。 另外,注意到在slot_pos_update中,len_h和len_v的计算使用了abs(pos1_x - pos2_x) +1,这可能是因为像素位置从0开始,所以两点之间的像素数需要加1。例如,从x=0到x=2,实际上是3个像素点,所以长度是2+1=3。需要指出这一点,避免误解。 还需要检查代码是否有潜在问题,比如在slot_btn_set_clicked中,如果用户输入的pixel不是正数,是否有处理。现在代码中如果pixel>0才更新,但未处理非正数的情况,可能需要添加错误提示。 在注释时,要分部分解释每个函数的作用,变量用途,信号和槽的连接关系。特别是pixel变量的作用,它可能代表每个单位对应的像素数,用于将像素距离转换为实际单位(如米)。例如,用户输入1米对应多少像素,然后通过乘以pixel得到实际长度。 还要注意代码中的Qt特性,比如setAttribute和setWindowFlag,解释它们的作用。例如,WA_QuitOnClose设置为false可能表示关闭这个窗口时不退出应用程序,而Qt::Window设置窗口标志为独立窗口。 最后,总结代码的功能,确保用户理解整个MeasureWidget的工作流程,从坐标更新到单位设置,再到长度计算和显示。可能还需要指出潜在改进点,比如输入验证、国际化支持等。</think>以下是对该代码的逐部分解析与注释说明: -------------------- measurewidget.h -------------------- ```cpp // 防止头文件重复包含的经典宏保护 #ifndef MEASUREWIDGET_H #define MEASUREWIDGET_H #include <QWidget> // 前置声明UI命名空间(由Qt Designer自动生成) namespace Ui { class MeasureWidget; } class MeasureWidget : public QWidget { Q_OBJECT // Qt元对象系统必须的宏 public: // 显式构造函数,parent参数用于设置父控件 explicit MeasureWidget(QWidget *parent = nullptr); ~MeasureWidget(); protected: // 重写窗口关闭事件处理函数 void closeEvent(QCloseEvent *e); // 处理界面语言变更事件 void changeEvent(QEvent *event); signals: // 窗口关闭时发出的信号 void sig_close(); // 单位设置信号:传递单位和像素换算比例 void sig_set(QString unit, QString pixel); private slots: // 设置按钮点击槽函数 void slot_btn_set_clicked(); public slots: // 坐标更新槽:接收两个点的坐标 void slot_pos_update(int pos1_x, int pos1_y, int pos2_x, int pos2_y); private: Ui::MeasureWidget *ui; // UI界面指针 // 测量参数存储 double pixel = 1.0; // 像素换算系数(如1像素=多少米) double len_h = 0.0; // 水平方向逻辑长度 double len_v = 0.0; // 垂直方向逻辑长度 double len_c = 0.0; // 笛卡尔距离(斜边长度) }; #endif // MEASUREWIDGET_H ``` -------------------- measurewidget.cpp -------------------- ```cpp #include "measurewidget.h" #include "ui_measurewidget.h" // 构造函数 MeasureWidget::MeasureWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MeasureWidget) { ui->setupUi(this); // 初始化UI布局 // 窗口属性设置 this->setAttribute(Qt::WA_QuitOnClose, false); // 关闭时不终止应用 this->setWindowFlag(Qt::Window); // 设置为独立窗口 // 初始化单位下拉框 ui->com_unit->insertItems(0, QStringList() << "m"); // 添加"米"单位 ui->com_unit->setCurrentIndex(0); // 默认选择第一个 // 连接按钮点击信号与槽函数 connect(ui->btn_set, &QPushButton::clicked, this, &MeasureWidget::slot_btn_set_clicked); } // 析构函数 MeasureWidget::~MeasureWidget() { delete ui; // 释放UI资源 } // 窗口关闭事件处理 void MeasureWidget::closeEvent(QCloseEvent *e) { emit sig_close(); // 发出关闭信号 QWidget::closeEvent(e); // 调用基类处理 } // 语言变更事件处理 void MeasureWidget::changeEvent(QEvent *event) { if(event->type() == QEvent::LanguageChange){ ui->retranslateUi(this); // 重新翻译界面 } QWidget::changeEvent(event); // 调用基类处理 } // 设置按钮点击处理 void MeasureWidget::slot_btn_set_clicked() { if(!ui->ledit_pixel->text().isEmpty()){ pixel = ui->ledit_pixel->text().toDouble(); // 获取像素换算系数 // 输入有效性验证 if(pixel > 0){ // 更新所有长度显示(实际长度 = 逻辑长度 * 像素系数) ui->lab_len_horizontal->setText(QString::asprintf("%.2f", len_h * pixel)); ui->lab_len_vertical->setText(QString::asprintf("%.2f", len_v * pixel)); ui->lab_len_cartesian->setText(QString::asprintf("%.2f", len_c * pixel)); // 发出设置信号(当前单位和像素系数) emit sig_set(ui->com_unit->currentText(), ui->ledit_pixel->text()); } } } // 坐标更新处理 void MeasureWidget::slot_pos_update(int pos1_x, int pos1_y, int pos2_x, int pos2_y) { // 计算各方向逻辑长度(+1处理像素偏移) len_h = abs(pos1_x - pos2_x) + 1; // 水平长度(含两端点) len_v = abs(pos1_y - pos2_y) + 1; // 垂直长度(含两端点) len_c = sqrt(pow(len_h,2) + pow(len_v,2)); // 斜边长度(勾股定理) // 更新坐标显示 ui->lab_pos_start->setText(QString("(%1,%2)").arg(pos1_x).arg(pos1_y)); ui->lab_pos_end->setText(QString("(%1,%2)").arg(pos2_x).arg(pos2_y)); // 更新带单位的长度显示 ui->lab_len_horizontal->setText(QString::asprintf("%.2f", len_h * pixel)); ui->lab_len_vertical->setText(QString::asprintf("%.2f", len_v * pixel)); ui->lab_len_cartesian->setText(QString::asprintf("%.2f", len_c * pixel)); } ``` 主要功能总结: 1. **测量工具窗口**:实现了一个可独立显示的测量工具窗口 2. **坐标处理逻辑**: - 通过`slot_pos_update`接收两个点坐标 - 计算水平、垂直、斜边三种距离(基础长度计算) 3. **单位换算系统**: - 使用`pixel`变量存储像素到物理单位(如米)的换算系数 - 通过`slot_btn_set_clicked`设置换算系数并更新显示 4. **国际化支持**: - 通过`changeEvent`实现界面语言动态切换 5. **信号通知机制**: - `sig_close`通知主窗口关闭事件 - `sig_set`传递单位设置参数 潜在改进建议: 1. **输入验证增强**:可添加对非数字输入的过滤 2. **单位扩展**:在`com_unit`中添加更多单位(如cm、mm) 3. **错误处理**:当`pixel<=0`时给出用户提示 4. **精度控制**:允许用户自定义显示的小数位数 5. **坐标显示优化**:增加参考坐标系标识(如原点位置)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值