【QT(九)】—— 窗口

前言

在之前的学习中,了解了 Qt 当中的常用控件,现在来学习 窗口

Qt窗口 是通过QMainWindow类实现的

QMainWindow类是为用户提供主窗口程序的类,继承子 QWidget类;并且QMainWindow还提供了一个预定义的布局:

一个QMainWindow窗口包含:一个菜单栏、多个工具栏、多个浮动窗口、一个状态栏和一个中心部件。

这里学习 QMainWindow窗口,在创建项目时选择的类就不再是 QWidget了,而是QMainWindow

菜单栏 QMenuBar

对于一个菜单栏,其中有很多菜单,而每一个菜单又有很多菜单项,每一个菜单项中也可以用子菜单。

创建菜单栏

  1. 如果默认生成了ui文件,自带一个menubar菜单栏

在对应的ui界面中,输入内容(菜单、菜单项)即可完成添加菜单、菜单项。

  1. 通过代码创建菜单栏

这里可以使用new,创建一个新的菜单栏,然后把这个菜单栏设置到QMainWindow主窗口中。

也可以使用QMainWindow类中,内置的方法menubar,来获取当前窗口菜单栏(如果不存在就创建)。

注意 :一个窗口只能用一个菜单栏,使用new新建一个菜单栏并设置到QMainWindow主窗口中,如果已经存在了菜单栏就会造成之前的菜单栏丢失,造成内存泄露问题。

cpp 复制代码
    // new 菜单栏
//    QMenuBar* menubar = new QMenuBar();
//    this->setMenuBar(menubar);
    // 获取当前窗口的菜单栏,不存在就创建
    QMenuBar* menubar = this->menuBar();

添加菜单

对于图像化界面添加菜单,这里就不过多描述了,在对应的界面输入内容即可完成添加。

Qt 当中,QMenu类表示菜单;添加菜单就要调用QMenuBar中的addMenu方法:

cpp 复制代码
    // 获取当前窗口的菜单栏,不存在就创建
    QMenuBar* menubar = this->menuBar();
    // 创建菜单
    QMenu* menu1 = new QMenu("文件");
    QMenu* menu2 = new QMenu("编辑");
    // 添加菜单
    menubar->addMenu(menu1);
    menubar->addMenu(menu2);

预期效果:

添加菜单项

上述添加只是添加了菜单,并没有给每一个菜单添加菜单项;

菜单QMenu,而菜单项对应的类是QAction

使用ui文件图形化界面添加菜单项,直接在对应位置输入即可。

添加QAction

cpp 复制代码
    // 添加菜单项
    QAction* action1 = new QAction("新建");
    QAction* action2 = new QAction("打开");
    QAction* action3 = new QAction("保存");
    menu1->addAction(action1);
    menu1->addAction(action2);
    menu1->addAction(action3);

添加分割线

上面操作中,无论是添加菜单、还是添加菜单项,都是没有设置分隔线的。

我们也可以在菜单和菜单之间、每一个菜单项之间设置分隔线:

cpp 复制代码
    menu1->addAction(action1);
    menu1->addSeparator();
    menu1->addAction(action2);
    menu1->addSeparator();
    menu1->addAction(action3);

子菜单

此外,在菜单中不仅仅可以添加菜单项,也可以添加子菜单。(对应接口:addMenu

cpp 复制代码
    QMenu* childmenu = new QMenu("子菜单");
    childmenu->addAction(action1);
    childmenu->addAction(action2);
    childmenu->addAction(action3);
    menu1->addMenu(childmenu);

菜单项信号处理

这里这是设置了菜单栏、添加了菜单、菜单项;但是在实际的点击菜单项时,并没有什么反应。

QAction类,在被点击时会触发一个信号:triggered

我们就可以绑定槽函数,在信号触发时执行特定的代码。

cpp 复制代码
    connect(action1,&QAction::triggered,this,[](){
        qDebug() << "新建";
    });

此外, 这里的菜单栏QMenuBar、菜单QMenu、菜单项QAction都是可以设置图标的。(调用setIcon方法即可)

工具栏 QToolBar

工具栏是应用程序中集成各种功能实现的快捷键使用的一个区域。可以存在多个工具栏,也可以没有工具栏。

工具栏是一个可移动的组件,其中的每一个元素是各种窗口组件(可以是QAction,通常情况下都设置图标)

创建工具栏

默认情况下,ui文件中是不会新建工具栏的。

所以工具栏就需要我们通过代码创建 QToolBar对象来创建一个工具栏,并为整个窗口MainWindow添加上工具栏。

cpp 复制代码
    QToolBar* toolbar = new QToolBar();
    this->addToolBar(toolbar);

添加组件

在工具栏中添加组件也是非常容易的,这里可以添加QAction对象、也可以添加各种控件。

并且这里的QAction对象也可以设置图像。

cpp 复制代码
    QAction* action1 = new QAction("新建");
    action1->setIcon(QIcon(":/1.jpg"));
    QAction* action2 = new QAction("打开");
    action2->setIcon(QIcon(":/2.jpg"));
    QAction* action3 = new QAction("保存");
    action3->setIcon(QIcon(":/3.jpg"));
    toolbar->addAction(action1);
    toolbar->addAction(action2);
    toolbar->addAction(action3);

这里鼠标停靠在对应图标位置,会提示出设置的文本内容;

也可以通过设置ToolTip

设置停靠位置

对于工具栏,它是可以拖动的,我们也可以设置这个停靠位置。

  • 创建工具栏的同时指定停靠位置。
  • 调用QToolBar 提供的 setAllowedAreas()函数设置工具栏允许停靠位置。
  • Qt::LeftToolBarArea : 停靠在左侧
  • Qt::RightToolBarArea : 停靠在右侧
  • Qt::TopToolBarArea : 停靠在顶部
  • Qt::ButtomToolBarArea : 停靠在底部
  • Qt::AllToolBarArea : 上下左右四个位置都可以停靠
cpp 复制代码
    QToolBar* toolbar = new QToolBar();
//    this->addToolBar(toolbar); // 默认停靠在顶部
    this->addToolBar(Qt::LeftToolBarArea,toolbar); // 设置初始位置在左侧
    toolbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); // 设置只允许停靠在左、右侧

设置了运行停靠位置后,拖动工具栏就可以将工具栏拖动到指定位置停靠。

设置是否允许 浮动和移动

上述虽然设置了停靠位置,但是工具栏默认是允许浮动的:

我们可以通过设置Floatable属性来设置是否运行工具栏浮动。

  • setFloatabletrue表示允许浮动,false表示不允许浮动。

此外,有些情况下工具栏是不能移动的,这里就可以通过设置movable属性来设置工具栏是否可以移动。

  • setMovabletrue表示允许移动,false表示不允许移动。
cpp 复制代码
    toolbar->setFloatable(false); // 设置不允许浮动
    toolbar->setMovable(false);   // 设置不允许移动

状态栏 QStatusBar

状态栏是应用程序输出简要信息的区域;一般情况下位于主窗口的最底部,一个窗口最多只能用一个状态栏。

在Qt当中,状态栏对应的类 QStatusBar

在状态栏中一般显示内容:当前程序状态(状态信息 )、程序版本号、进度条/百分比(进度信息

创建状态栏

如果在创建项目时,默认生成了ui文件,那默认是存在一个状态栏的;所以,创建状态栏就和创建菜单栏一样:

推荐使用:statusBar方法来获取当前状态栏(如果不存在就创建)

cpp 复制代码
    QStatusBar* statusbar = this->statusBar();
    this->setStatusBar(statusbar);

设置信息

创建好了状态栏,运行程序和之前没什么区别,因为在状态栏中什么都没有。

要在状态栏中显示信息,可以调用QStatusBar提供的 showMessage方法

参数

  • text : 要显示的文本
  • timeout : 信息的显示时间,单位ms(默认为0,表示一直显示)
cpp 复制代码
    // 设置状态栏信息
//    statusbar->showMessage("提示信息,3秒后消失",3000); // 显示3s后消失
    statusbar->showMessage("你能看见我吗");  // 一直显示

添加控件

除了可以在状态栏中设置信息之外,还可以在状态栏中增加一些控件(QLabelQProgressBar等等)

cpp 复制代码
    // 添加控件
    QLabel* label1 = new QLabel("提示信息");
    QLabel* label2 = new QLabel("右侧提示信息");
    QProgressBar* progressbar = new QProgressBar();
    progressbar->setValue(25);
    // 从左往右添加控件
    statusbar->addWidget(label1);
    statusbar->addWidget(progressbar);
    // 从右往左添加控件
    statusbar->addWidget(label2);

浮动窗口 QDockWidget

Qt 当中,浮动窗口也称为 铆接部件。对应的类 : QDockWidget

浮动窗口一般是位于核心部件的周围,可以存在多个。

创建浮动窗口

创建浮动窗口,其实就是通过代码创建一个QDockWidget对象,然后把这个QDockWidget对象添加到主窗口中。

注意 : 在将QDockWidget添加到主窗口(调用addDockWidget方法)时,需要指明初始停靠位置。

cpp 复制代码
    QDockWidget* dockwidget1 = new QDockWidget();
    this->addDockWidget(Qt::TopDockWidgetArea,dockwidget1);

这里没有设置窗口标题、图标等属性;也可以调用setWindowTitle方法来设置窗口标题

设置停靠位置

在调用addDockWidget方法时,需要指明初始停靠位置;

在程序运行起来时,通过鼠标拖动也是可以设置窗口的停靠位置的。

这里设置停靠位置和工具栏QToolBar一样,是设置可以停靠在上、下、左、右的哪些位置。

  • Qt::LeftDockWidgetArea : 停靠在左侧
  • Qt::RightDockWidgetArea : 停靠在右侧
  • Qt::TopDockWidgetArea : 停靠在顶部
  • Qt::ButtomDockWidgetArea : 停靠在底部
  • Qt::AllDockWidgetArea : 上下左右四个位置都可以停靠
cpp 复制代码
    //dockwidget1->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); // 设置可以停靠在左、右侧
    dockwidget1->setAllowedAreas(Qt::AllDockWidgetAreas); // 设置可以停靠在上、下、左、右位置

对话框 QDialog

对话框是GUI程序中不可或缺的组成部分;通常是一个顶层窗口,出现在程序的最上层,来实现简洁的用户交互。

Qt 常用的内置对话框: QMessageBox(消息对话框)、 QFiledialog(文件对话框)、QColorDialog(颜色对话框)、QFontDialog(字体对话框)、QInputDialog(输入对话框)

模态/非模态

  • 模态对话框:显示后无法和父窗口进行交互;阻塞式对话框。(调用exec函数
  • 非模态对话框:显示之后可以与父窗口进行交互;非阻塞对话框。(调用show函数

自定义对话框

要自定义对话框,就要基于QDialog类,实现一个子类;在特定情况(点击按钮)时,弹出这个对话框

cpp 复制代码
// dialog 自定义对话框
Dialog::Dialog(QWidget* parent) : QDialog(parent)
{
    QLabel* label = new QLabel("都说了啥也没有");
    QPushButton* button = new QPushButton("点击关闭");
    QVBoxLayout* layout = new QVBoxLayout();
    this->setLayout(layout);
    layout->addWidget(label);
    layout->addWidget(button);
    connect(button,&QPushButton::clicked,this,&Dialog::close);
}
Dialog::~Dialog()
{
    qDebug() << "调用 Dialog 析构函数";
}
// pushButton 关联槽函数
void MainWindow::on_pushButton_clicked()
{
    Dialog* dialog = new Dialog(this);
    dialog->show(); // 非模态对话框
    //dialog->exec(); // 模态对话框
}

这里就存在一个问题:通过点击按钮弹出的对话框,无论是点击关闭按钮还是窗口右上角关闭,对话框是关闭了,但是创建的Dialog对象并没有释放啊,当程序退出(主窗口关闭)时,才会被析构。

QDialog类中存在一个属性:Attribute ,将这个属性设置成 Qt::WA_DeleteOnClose ,在窗口关闭时,QDialog对象就会自动被释放了。

cpp 复制代码
void MainWindow::on_pushButton_clicked()
{
    Dialog* dialog = new Dialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->show(); // 非模态对话框
//    dialog->exec(); // 模态对话框
}

此外,这里还可以给对话框设置窗口标题,图标等等属性。

消息框 QMessageBox

消息对话框是应用程序中最常用的界面对话框,主要用于为用户提示主要信息,让用户进行选择。

QMessageBox类 定义了静态函数,可以根据需要调用不同风格的消息对话框:

对话框图标

  • Question : 用于正常操作中的提问
  • Information : 用于报告正常运行信息
  • Warning : 用于报告非关键错误(警告)
  • Critical : 用于报告严重错误

函数原型

参数

  • parent : 指定父元素
  • title : 对话框窗口标题
  • text : 对话框中显示的文本
  • buttons : 设置按钮(在对话框中都存在哪些按钮)

按钮类别

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton,&QPushButton::clicked,this,[this](){
        // 创建QMessageBox
//        QMessageBox* messagebox = new QMessageBox(this);
//        messagebox->setAttribute(Qt::WA_DeleteOnClose);
//        messagebox->setWindowTitle("对话框");
//        messagebox->setText("这是一个正常的对话框");
//        messagebox->setIcon(QMessageBox::Question);
//        messagebox->setStandardButtons(QMessageBox::Ok | QMessageBox::Close);
//        messagebox->show();

//        QMessageBox::warning(this,"对话框","这是一个简单的对话框");
        // 设置按钮集
        QMessageBox::question(this,"question","这是一个question对话框",QMessageBox::Ok | QMessageBox::Close);
    });
}

颜色对话框 QColorDialog

颜色对话框QColorDialog类,提供了一个静态方法:getColor

调用该方法,弹出一个颜色对话框,用户选择完一个颜色并点击确认后,getColor就会返回,并根据用户选择的颜色返回一个QColor对象。

示例:通过颜色对话框,获取用户选择的颜色,然后修改窗口的背景色

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 颜色对话框
    connect(ui->pushButton,&QPushButton::clicked, ui->pushButton,[this](){
        // 获取用户选择的颜色
        QColor color = QColorDialog::getColor();
        qDebug() << color;
        // 修改背景颜色
        QString style = "background-color: rgb(" + QString::number(color.red()) +", " + QString::number(color.green()) + "," + QString::number(color.blue()) + ");";
        this->setStyleSheet(style);
    });
}

文件对话框 QFileDialog

QFileDialog,文件对话框,可以选择文件打开、保存文件等等。

打开文件

保存文件

对于打开和保存文件,QFileDialog类提供了静态方法:QFileDialog::getOpenNameQFileDialog::getSaveName

函数原型

cpp 复制代码
    static QString getOpenFileName(QWidget *parent = nullptr,
                                   const QString &caption = QString(),
                                   const QString &dir = QString(),
                                   const QString &filter = QString(),
                                   QString *selectedFilter = nullptr,
                                   Options options = Options());
    static QUrl getOpenFileUrl(QWidget *parent = nullptr,
                               const QString &caption = QString(),
                               const QUrl &dir = QUrl(),
                               const QString &filter = QString(),
                               QString *selectedFilter = nullptr,
                               Options options = Options(),
                               const QStringList &supportedSchemes = QStringList());
    static QString getSaveFileName(QWidget *parent = nullptr,
                                   const QString &caption = QString(),
                                   const QString &dir = QString(),
                                   const QString &filter = QString(),
                                   QString *selectedFilter = nullptr,
                                   Options options = Options());
    static QUrl getSaveFileUrl(QWidget *parent = nullptr,
                               const QString &caption = QString(),
                               const QUrl &dir = QUrl(),
                               const QString &filter = QString(),
                               QString *selectedFilter = nullptr,
                               Options options = Options(),
                               const QStringList &supportedSchemes = QStringList());

Url返回的是一个 QUrl对象,其支持本地/网络路径;而Name系列返回一个QString对象,支持本地文件路径

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QMenuBar* menubar = this->menuBar();
    this->setMenuBar(menubar);

    QMenu* menu = new QMenu("文件");
    QAction* action1 = new QAction("打开");
    QAction* action2 = new QAction("保存");
    menu->addAction(action1);
    menu->addSeparator();
    menu->addAction(action2);
    menubar->addMenu(menu);

    connect(action1,&QAction::triggered, this,[this](){
        //QUrl url = QFileDialog::getOpenFileUrl();
        //qDebug() << url;
        QString path = QFileDialog::getOpenFileName();
        qDebug() << path;
    });
    connect(action2,&QAction::triggered, this,[this](){
        QString path = QFileDialog::getSaveFileName();
        qDebug() << path;
    });
}

这里在选择要打开/保存的文件后,只是输出了文件路径,并没有进行文件读取/写入操作。

字体对话框 QFontDialog

QFontDialog字体对话框,可以让用户选择字体、大小等属性。

创建对话框也很简单,可以使用new的方式创建一个QFontDialog对象;

当然这里也可以调用 QFontDialog类提供的静态方法 getFont

参数

  • ok:输出型参数,true表示用户点击确认、false表示用户点击 取消。
  • initial:字体对话框中,初始的字体属性。
  • parent:指定父元素
  • title:窗口标题

示例:根据用户选择,设置按钮的字体属性

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton,&QPushButton::clicked,this,[this](){
        bool ok = false;
        QFont init = ui->pushButton->font();
//        QFont font = QFontDialog::getFont(&ok);
        QFont font = QFontDialog::getFont(&ok,init,this,"字体属性");
        if(!ok)
            return;
        qDebug() << font;
        ui->pushButton->setFont(font);
    });
}

输入对话框 QInputDialog

QInputDialog输入对话框,让用户进行输入,支持intdoubleitem

  1. 整数输入框
cpp 复制代码
    static int getInt(QWidget *parent, const QString &title, const QString &label, int value = 0,
                      int minValue = -2147483647, int maxValue = 2147483647,
                      int step = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());

在调用该静态方法时,需要传参:parent(父元素)、title(窗口标题)、label(文本内容);

也可以指定value(初始值)、minValue(最小值)、maxValue(最大值)、step(微调框每次调整的大小)、ok(输出型参数,表示用户点击Ok还是Cancel)

  1. 浮点数输入框
cpp 复制代码
    static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0,
                            double minValue = -2147483647, double maxValue = 2147483647,
                            int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
    // ### Qt 6: merge overloads
    static double getDouble(QWidget *parent, const QString &title, const QString &label, double value,
                            double minValue, double maxValue, int decimals, bool *ok, Qt::WindowFlags flags,
                            double step);

参数和getInt类似,其中decimal表示小数的位数。

  1. 文本输入框
cpp 复制代码
    static QString getItem(QWidget *parent, const QString &title, const QString &label,
                           const QStringList &items, int current = 0, bool editable = true,
                           bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(),
                           Qt::InputMethodHints inputMethodHints = Qt::ImhNone);

在文本输入框中存在一个下拉框(也可以进行输入),在调用QInputDialog::getItem方法时,就需要传递一个QStringList对象,来初始化这个下拉框中的选项。

QStringListQList<QString>的子类,其用法也类似于数组。

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton_int,&QPushButton::clicked,this,[this](){
        int value = QInputDialog::getInt(this,"int输入框","请输入一个整数");
        qDebug() << value;
    });
    connect(ui->pushButton_double,&QPushButton::clicked,this,[this](){
        double value = QInputDialog::getDouble(this,"double输入框","请输入一个小数");
        qDebug() << value;
    });
    connect(ui->pushButton_text,&QPushButton::clicked,this,[this](){
        QStringList str_list;
        str_list.push_back("选项一");
        str_list.push_back("选项二");
        str_list.push_back("选项三");
        QString value = QInputDialog::getItem(this,"int输入框","请输入一个整数",str_list);
        qDebug() << value;
    });
}
:clicked,this,[this](){
        int value = QInputDialog::getInt(this,"int输入框","请输入一个整数");
        qDebug() << value;
    });
    connect(ui->pushButton_double,&QPushButton::clicked,this,[this](){
        double value = QInputDialog::getDouble(this,"double输入框","请输入一个小数");
        qDebug() << value;
    });
    connect(ui->pushButton_text,&QPushButton::clicked,this,[this](){
        QStringList str_list;
        str_list.push_back("选项一");
        str_list.push_back("选项二");
        str_list.push_back("选项三");
        QString value = QInputDialog::getItem(this,"int输入框","请输入一个整数",str_list);
        qDebug() << value;
    });
}

本篇文章到这里就结束了,感谢支持

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

相关推荐
程序员敲代码吗2 小时前
用Python监控系统日志并发送警报
jvm·数据库·python
m5655bj2 小时前
使用 C# 将 Excel 表格转换为 DataTable
数据库·c#
丁丁点灯o2 小时前
帆软指定某个列连续相同的数值合并单元格
数据库
DBA小马哥2 小时前
文档型数据库MongoDB迁移替换至金仓数据库在电商商品信息存储中的应用
数据库·mongodb
世界尽头与你2 小时前
CVE-2025-14847_ MongoDB 未授权内存泄露漏洞
数据库·安全·mongodb·网络安全·渗透测试
冬奇Lab2 小时前
Android 15存储子系统深度解析(一):Vold与存储管理框架
android·车载系统·系统架构
火山上的企鹅2 小时前
QGC 中修改原生 Android 串口 BUG 实操
qt·串口·qgc·无人机开发
小北方城市网2 小时前
Redis 缓存设计与避坑实战:解决穿透 / 击穿 / 雪崩
java·大数据·数据库·redis·python·elasticsearch·缓存
心态还需努力呀2 小时前
从 Oracle 到 KingbaseES:一次真实项目的数据库国产化迁移实录
数据库·oracle