Qt 模态对话框和非模态对话框

一、模态对话框

在 GUI 编程中,模态对话框是一种特殊的窗口,当它显示时,会阻止用户与应用程序的其他窗口(通常是它的父窗口)进行交互。用户必须先完成与该对话框的交互(例如,点击确定、取消按钮或关闭它),然后才能继续操作父窗口或其他应用程序窗口。

它的主要特点是:

  1. 阻塞性:模态对话框会阻塞应用程序的事件循环(更准确地说,是阻塞调用 exec() 的那个事件循环),直到对话框被关闭。
  2. 独占焦点:用户只能与该对话框交互,无法操作其父窗口或其他窗口(除非是系统级操作或另一个应用的窗口)。
  3. 强制响应:通常用于需要用户立即关注并做出决策的关键操作,如确认删除、输入必要信息、显示错误警告等。

1、Qt 中如何创建模态对话框?

在 Qt 中,创建并显示一个模态对话框主要有两种方式:

1.1、 使用 QDialog::exec() 方法(推荐)

这是实现模态对话框最标准的方式。

void MainWindow::showModalDialog() {
    // 1. 创建对话框对象
    QDialog dialog(this); // 通常指定父窗口,便于内存管理和居中显示

    // 2. 设置对话框内容(添加按钮、标签、布局等)
    QVBoxLayout *layout = new QVBoxLayout(&dialog);
    QLabel *label = new QLabel("这是一个模态对话框!", &dialog);
    QPushButton *okButton = new QPushButton("确定", &dialog);
    layout->addWidget(label);
    layout->addWidget(okButton);

    // 3. 连接按钮的信号(可选,但常见)
    connect(okButton, &QPushButton::clicked, &dialog, &QDialog::accept);

    // 4. 关键:使用 exec() 显示模态对话框
    int result = dialog.exec();

    // 5. 处理对话框返回的结果(exec() 返回后才执行这里)
    if (result == QDialog::Accepted) {
        qDebug() << "用户点击了确定";
    } else if (result == QDialog::Rejected) {
        qDebug() << "用户取消了对话框";
    }
}
  • exec() 的行为:调用 exec() 会启动一个局部的事件循环。这个循环会一直运行,直到对话框被关闭(通过 accept()reject() 或用户关闭)。在此期间,主窗口的事件循环(或其他调用 exec() 的事件循环)会被阻塞。
  • 返回值exec() 返回一个 int 值,通常是 QDialog::AcceptedQDialog::Rejected(也可以使用自定义的返回值)。这取决于对话框是如何被关闭的(调用 accept()reject())。
  • 优点:逻辑清晰,代码执行流直观(显示对话框 -> 等待用户操作 -> 根据结果执行后续代码)。内存管理简单,如果对话框是栈上创建的(如示例),退出作用域会自动销毁;如果是 new 的,需要在 exec() 返回后 delete(或使用智能指针)。

1.2、使用 QDialog::open() 方法配合事件循环(Qt 5.10+)

open()exec() 的非阻塞替代方案,它使对话框成为模态窗口,但立即返回。你需要自己管理一个事件循环来等待它完成。

void MainWindow::showModalDialogWithOpen() {
    // 1. 创建对话框对象 (通常用 new)
    QDialog *dialog = new QDialog(this);

    // ... 设置对话框内容 ...

    // 2. 使用 open() 显示模态对话框
    dialog->open();

    // 3. 创建一个局部事件循环等待对话框关闭
    QEventLoop loop;
    connect(dialog, &QDialog::finished, &loop, &QEventLoop::quit);
    loop.exec(); // 阻塞直到对话框 finished

    // 4. 处理结果
    int result = dialog->result();
    qDebug() << "对话框结果:" << result;

    // 5. 删除对话框 (如果是 new 的)
    delete dialog;
}
  • 行为open() 使对话框模态化并显示它,但函数立即返回。然后你需要创建一个 QEventLoop 并连接到对话框的 finished(int) 信号来等待它关闭。
  • 适用场景:在事件处理函数中需要显示模态对话框但又不想阻塞整个事件循环时(例如,在 paintEvent 中调用 exec() 会导致问题),或者需要更精细地控制等待过程时。但通常 exec() 更简单直接。

3.3、使用 QDialog::setModal(true) 后调用 show() (不推荐用于严格模态)

void MainWindow::showModalDialogWithSetModal() {
    QDialog *dialog = new QDialog(this);
    dialog->setModal(true); // 设置为模态
    dialog->show();         // 非阻塞显示

    // 注意:show() 立即返回,后续代码会继续执行!
    // 你需要通过信号(如 finished)来获取结果。
    connect(dialog, &QDialog::finished, this, [dialog](int result) {
        qDebug() << "对话框结果:" << result;
        dialog->deleteLater(); // 安全删除
    });
}
  • 行为setModal(true) 告诉 Qt 该对话框 应该 是模态的。调用 show() 后对话框显示,show() 立即返回。父窗口或其他窗口 可能 会被禁用(取决于平台和窗口管理器的行为),但这并不像 exec() 那样严格保证阻塞调用它的代码执行流。应用程序的事件循环仍在运行。
  • 缺点:行为不如 exec() 可靠和一致(尤其是在跨平台时)。代码执行流是异步的,需要通过信号槽来处理结果,逻辑可能更分散。内存管理也更需要注意(通常用 deleteLater)。
  • 适用场景:当你想让对话框模态化,但又希望调用函数能立即返回,并且愿意通过异步方式处理结果时。但对于需要严格阻塞后续逻辑的场景,exec() 是更好的选择。

2、模态对话框与非模态对话框的区别

特性模态对话框 (exec())非模态对话框 (show())
阻塞性阻塞调用 exec() 的代码流非阻塞,show() 立即返回
用户交互独占焦点,必须关闭才能操作父窗口可与父窗口或其他窗口同时操作
事件循环启动局部事件循环使用主应用程序事件循环
常用创建方式exec()show()
结果获取通过 exec() 返回值通过信号 (如 finished(int))
内存管理栈对象或 exec()delete通常 new,需手动管理或 deleteLater
典型用途确认、错误提示、关键输入查找替换、工具面板、进度显示

4、使用模态对话框的注意事项

  1. 避免长任务阻塞:在模态对话框的事件循环中(即 exec() 执行期间),避免执行耗时的计算或网络请求,否则会导致界面冻结。如果需要在模态对话框中处理耗时任务,应使用线程或异步操作,并确保任务完成后关闭对话框。
  2. 父窗口指定:创建对话框时最好指定父窗口。这有助于:
    • 内存管理:父窗口删除时,子对话框通常也会自动删除(取决于创建方式)。
    • 窗口居中:对话框通常会相对于父窗口居中显示。
    • 模态范围:模态通常作用于父窗口及其子窗口。
  3. 结果处理:清晰定义并处理对话框的返回值 (Accepted, Rejected, 或自定义值),以决定后续操作。
  4. 用户体验:模态对话框会中断用户当前操作流,应谨慎使用。只应在确实需要用户立即关注和决策时使用。对于非关键信息或可选操作,考虑使用非模态对话框或状态栏提示。

5、总结

QDialog::exec() 是实现 Qt 模态对话框最可靠、最常用的方式。它提供清晰的阻塞式执行流,强制用户响应,并简化了结果处理和内存管理。理解 exec() 启动局部事件循环的原理对于掌握其行为至关重要。虽然 open()setModal(true) + show() 提供了替代方案,但它们在严格阻塞性和代码清晰度上通常不如 exec()。根据你的具体需求(是否需要严格阻塞代码流)来选择合适的模态实现方式。

二、非模态对话框

非模态对话框是 GUI 编程中的一种对话框类型。其核心特点是:当它显示时,不会阻止用户与应用程序的其他窗口或对话框进行交互

  • 类比理解:想象你在使用文本编辑器(主窗口)时,打开了一个查找替换对话框。如果这个对话框是非模态的,你可以一边在查找替换对话框中输入内容,一边点击主文本编辑区域进行编辑。两个窗口可以同时操作。
  • 与模态对话框的区别
    • 模态对话框:当其显示时,会阻塞程序执行流,用户必须先完成与该对话框的交互(关闭它),才能继续操作应用程序的其他部分。例如,常见的文件保存对话框通常是模态的。
    • 非模态对话框:显示后,程序执行流继续,用户可以在对话框和主窗口(或其他窗口)之间自由切换焦点和操作。

1、如何创建和显示非模态对话框?

在 Qt 中,创建和显示一个非模态对话框通常涉及以下步骤:

  1. 创建对话框对象:使用 new 运算符在堆上动态创建对话框对象。这是关键点! 非模态对话框通常需要较长的生命周期(可能伴随主窗口存在),因此需要在堆上分配内存,并妥善管理其生命周期,避免内存泄漏。

    MyNonModalDialog *dialog = new MyNonModalDialog(this); // 通常将父窗口指针(如 this)传递给构造函数
    
    • 传递父窗口指针(this)非常重要,这利用了 Qt 的对象树机制。当父对象(通常是主窗口)被销毁时,Qt 会自动递归销毁其所有子对象(包括这个对话框),帮助管理内存。
  2. 设置窗口属性 (可选但推荐)

    dialog->setAttribute(Qt::WA_DeleteOnClose); // 对话框关闭时自动删除对象
    
    • Qt::WA_DeleteOnClose 属性确保了当用户关闭对话框窗口时,Qt 会自动调用 delete 来销毁对话框对象。这是管理非模态对话框内存的常用且便捷的方法,尤其当父对象可能不立即销毁时。
  3. 显示对话框:使用 show() 方法,而不是用于模态对话框的 exec()

    dialog->show();
    
    • show() 方法使对话框可见并立即返回,不会阻塞程序执行。对话框显示后,用户就可以自由操作它和应用程序的其他部分了。

2、生命周期与内存管理

这是使用非模态对话框时需要特别注意的地方:

  • 堆上分配:如前所述,非模态对话框通常需要在堆上创建 (new)。
  • 父对象机制:在创建时将主窗口(或其他合适的父窗口)作为父对象传递,是最简单、最推荐的内存管理方式。父对象销毁时,子对象自动销毁。
  • Qt::WA_DeleteOnClose:强烈建议设置此属性。这样,当用户点击对话框标题栏的关闭按钮时,对话框窗口关闭并且对象被自动删除。如果不设置此属性,仅调用 close() 或点击关闭按钮只会隐藏窗口,对象仍然存在于内存中(除非父对象销毁它)。
  • 手动管理 (谨慎使用):如果不使用父对象机制和 WA_DeleteOnClose,你需要在合适的时机(例如主窗口关闭时,或通过其他信号)手动调用 delete dialog; 来销毁对象。这种方法容易出错导致内存泄漏,应尽量避免。

3、与主窗口的通信

非模态对话框通常需要与主窗口或其他部分交换数据。Qt 的信号和槽机制是实现这种通信的理想方式。

  • 对话框发出信号:在对话框类中定义信号。例如,对话框完成某项操作(如用户点击了“应用”按钮)时发出信号。

    // 在 MyNonModalDialog 类声明中
    signals:
        void settingsApplied(const QString &newSetting);
    
    // 在 MyNonModalDialog 的某个方法中(如按钮点击槽函数)
    emit settingsApplied(newValue); // 发出信号
    
  • 主窗口连接信号:在主窗口(或其他对象)中,创建对话框后,将其信号连接到主窗口的槽函数。

    MyNonModalDialog *dialog = new MyNonModalDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    connect(dialog, &MyNonModalDialog::settingsApplied, this, &MainWindow::handleSettingsApplied);
    dialog->show();
    
    • 这里 MainWindow::handleSettingsApplied 是一个槽函数,用于接收来自对话框的信号并执行相应操作。

4、 处理对话框关闭

  • 当用户关闭对话框(点击关闭按钮)时:
    • 如果设置了 Qt::WA_DeleteOnClose,对话框对象会被删除。
    • 如果没有设置,对话框对象仍然存在(只是窗口隐藏了),你需要决定何时销毁它(通常还是通过父对象或手动管理)。
  • 如果对话框有自己的“确定”、“取消”、“应用”等按钮,通常在这些按钮的点击槽函数中调用 accept()reject()close() 来关闭窗口。close() 会触发窗口关闭事件。
  • 你可以重写对话框的 closeEvent(QCloseEvent *event) 函数,在窗口关闭前执行一些操作(如保存状态、提示用户)。记得调用 event->accept()event->ignore() 来决定是否真正关闭窗口。

5、应用场景

非模态对话框适用于需要用户长时间交互或需要同时操作多个窗口的场景,例如:

  • 查找/替换对话框
  • 工具选项板/属性面板
  • 聊天窗口
  • 监控窗口
  • 进度指示器(如果设计为对话框形式)

三、自定义对话框

1、效果展示

在这里插入图片描述

2、messageDialog.h

#ifndef MESSAGEDIALOG_H
#define MESSAGEDIALOG_H

#include <QDialog>
#include <QGraphicsDropShadowEffect>
#include <QPropertyAnimation>
#include <QEventLoop>
#include <QTimer>

namespace Ui {
class MessageDialog;
}

class MessageDialog : public QDialog
{
    Q_OBJECT
public:
    typedef enum
    {
        messageError,
        messageWarning,
        messageNotice,
        messageAsk,
        messageWait,
    }messageDialogType;
public:
    explicit MessageDialog(QWidget *parent = nullptr);
    ~MessageDialog();

    void setValue(messageDialogType type,QString title,QString message);
    int execRun(QWidget* parent,messageDialogType type,QString title,QString message);
protected:
    bool eventFilter(QObject *object, QEvent *event) override;
private:
    void controlInit();
    void widgetShake(QWidget *widget, int range);
private slots:
    void animationFinishedSlot();
    void btnClickedSlot();
private:
    Ui::MessageDialog *ui;
    QPropertyAnimation *btnConfirmAnimation,*btnCancelAnimation;
    QEventLoop eventLoop;	//循环事件
    bool isStatic = false;	//是否是使用静态对象显示对话框
    int returnVal;
};

#endif // MESSAGEDIALOG_H

3、messageDialog.cpp

#include "messageDialog.h"
#include "ui_messageDialog.h"

MessageDialog::MessageDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MessageDialog)
{
    ui->setupUi(this);
    this->controlInit();
}

MessageDialog::~MessageDialog()
{
    delete ui;
}


void MessageDialog::controlInit()
{
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground, true);

    this->installEventFilter(this);
    //实例阴影shadow
    QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this->ui->frame);
    shadow->setOffset(0, 0);
    shadow->setColor(QColor(32, 101, 165));
    shadow->setBlurRadius(10);
    this->ui->frame->setGraphicsEffect(shadow);

//    this->ui->labelTitle->setText("");
//    this->ui->labelMessage->setText("");

    btnConfirmAnimation = new QPropertyAnimation(this->ui->btnConfirm,"pos");
    btnConfirmAnimation->setEasingCurve(QEasingCurve::Linear);
    btnConfirmAnimation->setDuration(600);

    btnCancelAnimation = new QPropertyAnimation(this->ui->btnCancel,"pos");
    btnCancelAnimation->setEasingCurve(QEasingCurve::Linear);
    btnCancelAnimation->setDuration(300);

    this->ui->btnConfirm->hide();
    this->ui->btnCancel->hide();

    QSizePolicy btnConfirmRetainPolicy = this->ui->btnConfirm->sizePolicy();
    btnConfirmRetainPolicy.setRetainSizeWhenHidden(true);
    this->ui->btnConfirm->setSizePolicy(btnConfirmRetainPolicy);

    QSizePolicy btnCancelRetainPolicy = this->ui->btnCancel->sizePolicy();
    btnCancelRetainPolicy.setRetainSizeWhenHidden(true);
    this->ui->btnCancel->setSizePolicy(btnCancelRetainPolicy);


    this->ui->frame->setFrameShape(QFrame::StyledPanel);
    this->ui->frame->setFrameShadow(QFrame::Raised);

    connect(btnConfirmAnimation,&QPropertyAnimation::finished,this,&MessageDialog::animationFinishedSlot);

    this->ui->frame->installEventFilter(this);

    connect(this->ui->btnConfirm,&QPushButton::clicked,this,&MessageDialog::btnClickedSlot);
    connect(this->ui->btnCancel,&QPushButton::clicked,this,&MessageDialog::btnClickedSlot);  
}

void MessageDialog::widgetShake(QWidget *widget, int range)
{
    int nX = widget->x();
    int nY = widget->y();
    QPropertyAnimation *pAnimation = new QPropertyAnimation(widget,"geometry");
    pAnimation->setEasingCurve(QEasingCurve::InOutSine);
    pAnimation->setDuration(300);
    pAnimation->setStartValue(QRect(QPoint(nX,nY),widget->size()));

    int nShakeCount = 20; //抖动次数
    double nStep = 1.0/nShakeCount;
    for(int i = 1; i < nShakeCount; i++){
        range = i&1 ? -range : range;
        pAnimation->setKeyValueAt(nStep*i,QRect(QPoint(nX + range,nY),widget->size()));
    }

    pAnimation->setEndValue(QRect(QPoint(nX,nY),widget->size()));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
void MessageDialog::setValue(messageDialogType type, QString title, QString message)
{
    switch(type)
    {
        case messageError:this->ui->labelIcon->setStyleSheet("image: url(:/image/messageDialog/resources/images/messageDialog/error.svg);");break;
        case messageWarning:this->ui->labelIcon->setStyleSheet("image: url(:/image/messageDialog/resources/images/messageDialog/warning.svg);");break;
        case messageNotice:this->ui->labelIcon->setStyleSheet("image: url(:/image/messageDialog/resources/images/messageDialog/notice.svg);");break;
        case messageAsk:this->ui->labelIcon->setStyleSheet("image: url(:/image/messageDialog/resources/images/messageDialog/ask.svg);");break;
        case messageWait:this->ui->labelIcon->setStyleSheet("image: url(:/image/messageDialog/resources/images/messageDialog/wait.svg);");break;
    }
    this->ui->labelTitle->setText(title);
    this->ui->labelMessage->setText(message);
}

int MessageDialog::execRun(QWidget *parent, messageDialogType type, QString title, QString message)
{
    Q_UNUSED(parent);
    this->setValue(type,title,message);
    this->setModal(true);
    this->show();
    this->isStatic = true;
    this->eventLoop.exec();
    return returnVal;
}

bool MessageDialog::eventFilter(QObject *object, QEvent *event)
{
    if(object == this->ui->frame)
    {
        if(event->type() == QEvent::FocusOut)
        {
            this->widgetShake(this,50);
        }
    }
    else
    {
        if(event->type() == QEvent::Close)
        {
            this->ui->btnConfirm->hide();
            this->ui->btnCancel->hide();
            if(this->isStatic)
            {
                eventLoop.exit();
            }
        }
        else if(event->type() == QEvent::Show)
        {

            btnConfirmAnimation->setStartValue(QPoint(0,this->ui->btnConfirm->geometry().y()));
            btnConfirmAnimation->setEndValue(QPoint(this->ui->frame->width()-this->ui->btnConfirm->width(),
                                                    this->ui->btnConfirm->geometry().y()));
            btnConfirmAnimation->start();
            this->ui->btnConfirm->show();
        }
    }

    return QDialog::eventFilter(object,event);
}

void MessageDialog::animationFinishedSlot()
{  
    btnCancelAnimation->setStartValue(QPoint(0,this->ui->btnCancel->geometry().y()));
    btnCancelAnimation->setEndValue(QPoint(this->ui->frame->width()-this->ui->btnConfirm->width()-this->ui->btnCancel->width()
                                           -10,this->ui->btnCancel->geometry().y()));
    btnCancelAnimation->start();
    this->ui->btnCancel->show();
}

void MessageDialog::btnClickedSlot()
{
    QPushButton *btn = qobject_cast<QPushButton *>(sender());

    if(this->isStatic)
    {
        if(btn == this->ui->btnConfirm)
        {
            this->returnVal = QDialog::Accepted;
        }
        else if(btn == this->ui->btnCancel)
        {
            this->returnVal = QDialog::Rejected;
        }
        this->close();
    }
    else
    {
        if(btn == this->ui->btnConfirm)
        {
            this->accept();
        }
        else if(btn == this->ui->btnCancel)
        {
            this->reject();
        }
    }
}

4、messageDialog.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MessageDialog</class>
 <widget class="QDialog" name="MessageDialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>410</width>
    <height>210</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QFrame" name="frame">
     <property name="mouseTracking">
      <bool>true</bool>
     </property>
     <property name="focusPolicy">
      <enum>Qt::StrongFocus</enum>
     </property>
     <property name="styleSheet">
      <string notr="true">QFrame#frame{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 170, 0,255), stop:1 rgba(255, 255, 255, 255));
border:1px groove gray;border-radius:10px;padding:5px;
}</string>
     </property>
     <property name="frameShape">
      <enum>QFrame::StyledPanel</enum>
     </property>
     <property name="frameShadow">
      <enum>QFrame::Raised</enum>
     </property>
     <layout class="QGridLayout" name="gridLayout_2">
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="topMargin">
       <number>0</number>
      </property>
      <property name="rightMargin">
       <number>0</number>
      </property>
      <property name="bottomMargin">
       <number>0</number>
      </property>
      <property name="spacing">
       <number>0</number>
      </property>
      <item row="0" column="0">
       <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,2">
        <item>
         <layout class="QVBoxLayout" name="verticalLayout" stretch="1,2,1">
          <item>
           <spacer name="verticalSpacer">
            <property name="orientation">
             <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
              <width>20</width>
              <height>40</height>
             </size>
            </property>
           </spacer>
          </item>
          <item>
           <widget class="QLabel" name="labelIcon">
            <property name="styleSheet">
             <string notr="true">image: url(:/messageDialog/image/messageDialog/ask.png);</string>
            </property>
            <property name="text">
             <string/>
            </property>
            <property name="scaledContents">
             <bool>false</bool>
            </property>
            <property name="alignment">
             <set>Qt::AlignCenter</set>
            </property>
            <property name="wordWrap">
             <bool>false</bool>
            </property>
           </widget>
          </item>
          <item>
           <spacer name="verticalSpacer_2">
            <property name="orientation">
             <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
              <width>20</width>
              <height>40</height>
             </size>
            </property>
           </spacer>
          </item>
         </layout>
        </item>
        <item>
         <layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,2,1">
          <item>
           <widget class="QLabel" name="labelTitle">
            <property name="font">
             <font>
              <family>楷体</family>
              <pointsize>14</pointsize>
             </font>
            </property>
            <property name="styleSheet">
             <string notr="true">color: rgb(145, 102, 14);</string>
            </property>
            <property name="text">
             <string>这是标题</string>
            </property>
            <property name="alignment">
             <set>Qt::AlignCenter</set>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QLabel" name="labelMessage">
            <property name="font">
             <font>
              <family>黑体</family>
              <pointsize>10</pointsize>
             </font>
            </property>
            <property name="mouseTracking">
             <bool>false</bool>
            </property>
            <property name="styleSheet">
             <string notr="true">color: rgba(0, 0, 0, 200);</string>
            </property>
            <property name="text">
             <string>这是内容</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
            </property>
           </widget>
          </item>
          <item>
           <layout class="QHBoxLayout" name="horizontalLayoutBtn" stretch="1,1">
            <item>
             <widget class="QPushButton" name="btnCancel">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="maximumSize">
               <size>
                <width>16777215</width>
                <height>35</height>
               </size>
              </property>
              <property name="focusPolicy">
               <enum>Qt::NoFocus</enum>
              </property>
              <property name="styleSheet">
               <string notr="true">QPushButton
{
background-color: rgba(255,127,39,130);
border-radius: 10px;
border:1px groove red;
font-family: \&quot;Microsoft YaHei\&quot;;
font-size: 14px;
color: #333333;
}
QPushButton::hover
{
background:rgba(255,127,39, 170)
}
QPushButton::pressed
{
background:rgba(255,127,39, 255)
}</string>
              </property>
              <property name="text">
               <string>取消</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QPushButton" name="btnConfirm">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="maximumSize">
               <size>
                <width>16777215</width>
                <height>35</height>
               </size>
              </property>
              <property name="focusPolicy">
               <enum>Qt::NoFocus</enum>
              </property>
              <property name="styleSheet">
               <string notr="true">QPushButton
{
background-color: rgba(255,127,39,130);
border-radius: 10px;
border:1px groove red;
font-family: \&quot;Microsoft YaHei\&quot;;
font-size: 14px;
color: #333333;
}
QPushButton::hover
{
background:rgba(255,127,39, 170)
}
QPushButton::pressed
{
background:rgba(255,127,39, 255)
}</string>
              </property>
              <property name="text">
               <string>确定</string>
              </property>
             </widget>
            </item>
           </layout>
          </item>
         </layout>
        </item>
       </layout>
      </item>
     </layout>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

5、说明

如果模态显示就调用execRun函数,非模态调用show函数。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小灰灰搞电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值