Qt——窗口

目录

概述

菜单栏

创建菜单栏

创建子菜单

添加分割线

添加图标

工具栏

创建工具栏

设置初始位置和停靠位置 

设置浮动属性

设置移动属性

状态栏

创建状态栏

显示实时消息

添加控件

浮动窗口

创建浮动窗口

对话框

创建对话框

对话框的分类

Qt 内置对话框

QMessageBox

QColorDialog

QFileDialog

QFontDialog

QInputDialog

总结


概述

        我们前面所学的代码都是基于QWidget,这是一个控件,它更多的是作为别的窗口的一个部分,当我们在创建Qt项目的时候就会选择使用QWidget,还可以使用QMainWindow,它就相当于一个窗口的完全体。

        QmainWindow 是一个为用户提供主窗口程序的类,继承自 QWidget 类,并且提供了一个预定义的布局。QMainWindow 包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个子窗口(铆接部件)(dock widgets)、⼀个状态栏(status bar) 和⼀个中心部件(central widget),它是许多应用程序的基础,如文本编辑器,图片编辑器等。


菜单栏

         Qt 中的菜单栏是通过 QMenuBar 这个类实现的,一个主窗口最多只有一个菜单栏,位于主窗口顶部,主窗口标题栏下面,拿Qt Creater举例,中间的就是菜单栏,里面是一个个菜单 ,点击一个菜单就会出现菜单项。

        我们创建一个 QMainWindow 项目,转到图形化界面,这个窗口中默认就有这几个,有centralwidget、MenuBar和StatusBar。

        第一栏就是菜单栏,直接往菜单栏中添加几个菜单,都是仿照 Qt 设置的,就会看到菜单栏中出现了变化,每个菜单都是QMenu,菜单项是QAction。

创建菜单栏

        在操作的时候难免会出现一些小Bug,这也是避免不了的,可能是Qt Creater自身的问题,既然图形化界面有Bug,那么就使用代码创建菜单栏。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 1. 创建一个菜单栏
    QMenuBar* menuBar = new QMenuBar();
    this->setMenuBar(menuBar); // 设置到窗口

    // 2. 创建菜单
    QMenu* menu1 = new QMenu("文件");
    QMenu* menu2 = new QMenu("编辑");
    QMenu* menu3 = new QMenu("构建");
    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
    menuBar->addMenu(menu3);

    // 3. 创建菜单项
    QAction* action1 = new QAction("新建");
    QAction* action2 = new QAction("打开");
    QAction* action3 = new QAction("保存");
    QAction* action4 = new QAction("另存为");
    QAction* action5 = new QAction("退出");
    menu1->addAction(action1);
    menu1->addAction(action2);
    menu1->addAction(action3);
    menu1->addAction(action4);
    menu1->addAction(action5);

}

        既然创建出了菜单项,那就是要让菜单项提供某种功能,当用鼠标点击菜单项的时候,这次触发的就不是clicked信号了,而是triggered信号。

// 4. 连接信号和槽
connect(action5, &QAction::triggered, this, &QMainWindow::close); // 点击这个菜单项就退出

        Qt Creater中的菜单栏中还带有快捷键,使用Alt + 字母的方式就可以触发对应的菜单,打开对应的菜单项,我们上一篇中也提到了两种设置快捷键的方式,一种是通过QShortCut,但是这种设置比较麻烦,还有一种就是(&字母),通过这种方式就可以设置快捷键了。

    // 2. 创建菜单
    QMenu* menu1 = new QMenu("文件(&F)");
    QMenu* menu2 = new QMenu("编辑(&E)");
    QMenu* menu3 = new QMenu("构建(&B)");
    menuBar->addMenu(menu1);
    menuBar->addMenu(menu2);
    menuBar->addMenu(menu3);

    // 3. 创建菜单项
    QAction* action1 = new QAction("新建(&N)");
    QAction* action2 = new QAction("打开(&O)");
    QAction* action3 = new QAction("保存(&L)");
    QAction* action4 = new QAction("另存为");
    QAction* action5 = new QAction("退出(&X)");

        这样就设置好了快捷键,并且&符号也没有显示出来。

创建子菜单

        既然可以添加菜单,那么菜单中不仅可以添加菜单项,也应该可以添加菜单。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QMenuBar* menuBar = new QMenuBar();
    this->setMenuBar(menuBar); // 设置到窗口

    QMenu* menuParent = new QMenu("父菜单");
    QMenu* menuChild = new QMenu("子菜单");

    menuBar->addMenu(menuParent);
    menuParent->addMenu(menuChild);

    QAction* action1 = new QAction("菜单项1");
    QAction* action2 = new QAction("菜单项2");
    QMenu* menuChild2 = new QMenu("子菜单2");

    menuChild->addAction(action1);
    menuChild->addAction(action2);
    menuChild->addMenu(menuChild2);
}

添加分割线

        如果菜单中的菜单项特别多,那就可以通过分割线进行分组,比如创建和打开项目可以是一组,保存文件也可以是一组。QMenu 中提供了 addSeparator 这样的函数。

// 3. 创建菜单项
QAction* action1 = new QAction("新建(&N)");
QAction* action2 = new QAction("打开(&O)");
QAction* action3 = new QAction("保存(&L)");
QAction* action4 = new QAction("另存为");
QAction* action5 = new QAction("退出(&X)");
menu1->addAction(action1);
menu1->addAction(action2);
menu1->addSeparator();
menu1->addAction(action3);
menu1->addAction(action4);
menu1->addSeparator();
menu1->addAction(action5);

添加图标

        Qt 中也可以看到菜单不仅有菜单,还可以有它自己的图标。

        保存图片还是使用qrc文件,创建这个菜单项后就可以通过QIcon设置菜单项的图标了。

        还要注意的一点就是,这里设置的是菜单项,菜单也是可以设置图标的,但是菜单栏中的QMenu是在QMenuBar上的,所以图标就会覆盖文本,文本也就不显示了。

        最后还有一点要注意,如果构造函数中什么都不写,项目自动生成的ui文件中会自动带有QMenuBar,如果在构造函数中new一个 QMenuBar ,这就会导致旧的脱离 Qt 的对象树,后续也就无法自动释放了,这就造成了内存泄漏。

        如果程序关闭,对象树释放了,进程结束后所有的内存都会被系统回收,这种内存泄漏也不会造成影响。

        如果在一个多窗口程序中,窗口频繁的跳转和切换,也就对应了窗口的创建和销毁,这种内存泄漏还要严重一点。

        实际上,现在的计算机内存都比较充裕,这种内存泄漏不会有太大的影响,这是因为是客户端程序,如果一个服务器出现内存泄漏,那就是致命的,服务器要一直运行,处理请求的过程中,每次都泄漏一点,时间久了就会泄漏很多。

        所以我们也尽量不要出现这种内存泄漏,如何解决,那就不创建新的QMenuBar就好了。

        这个操作就是如果QMenuBar存在,直接获取并返回;如果不存在,就创建一个再返回。


工具栏

创建工具栏

        工具栏是应用程序中集成各种功能实现快捷键使用的一个区域,可以有多个,也可以没有,它并不是应用程序中必须存在的组件,往往是把我们常用的一些工具放到这里面。它是⼀个可移动的组件,它的元素可以是各种窗口组件,它的元素通常以图标按钮的方式存在。

        现在就简单实现一个工具栏。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 手动创建工具栏
    QToolBar* toolBar = new QToolBar();
    this->addToolBar(toolBar); // 这里使用的add(添加),而菜单栏使用的是set(替换),由此也可以看出工具栏可以有多个,而菜单栏只能有一个
    QAction* action1 = new QAction("新建文件或项目");
    QAction* action2 = new QAction("打开文件或项目");

    // 添加到工具栏,并加上图标
    toolBar->addAction(action1);
    action1->setIcon(QIcon(":/image/file.png"));
    toolBar->addAction(action2);
    action2->setIcon(QIcon(":/image/directory.png"));

}

        从这个ToolTip就可以看到,工具栏也是把文本覆盖,如果想要改变,那就重新设置一下ToolTip,我们平常看到的工具栏也是一个一个的图标。

        一个菜单项不仅可以添加到工具栏,也可以添加到菜单中,我们可以获取菜单栏,创建一个菜单,将菜单项分别添加到菜单和工具中,工具栏也是从菜单栏中取出常用的工具而已。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 获取菜单栏
    QMenuBar* menuBar = this->menuBar();
    this->setMenuBar(menuBar);

    // 创建菜单
    QMenu* menu = new QMenu("文件");
    menuBar->addMenu(menu);

    // 手动创建工具栏
    QToolBar* toolBar = new QToolBar();
    this->addToolBar(toolBar); // 这里使用的add(添加),而菜单栏使用的是set(替换),由此也可以看出工具栏可以有多个,而菜单栏只能有一个

    // 创建两个菜单项
    QAction* action1 = new QAction("新建文件或项目");
    QAction* action2 = new QAction("打开文件或项目");

    // 添加到工具栏,并加上图标
    toolBar->addAction(action1);
    action1->setIcon(QIcon(":/image/file.png"));
    toolBar->addAction(action2);
    action2->setIcon(QIcon(":/image/directory.png"));

    // 也可以添加到菜单栏
    menu->addAction(action1);
    menu->addAction(action2);
}

设置初始位置和停靠位置 

        由上图可知,这个工具栏不仅可以在菜单栏的下方,还可以在右侧,可以浮动在界面上,也可以有多个工具栏,所以可以对工具栏进行一些设置:

  • 出现的初始位置
  • 允许停放到哪些边缘
  • 是否允许浮动
  • 是否可以移动

        在 QMainWindow 的 addToolBar中可以指定工具栏初始出现的位置,具体的选项也包括这几个。

Qt::LeftToolBarArea   // 停靠在左侧
Qt::RightToolBarArea  // 停靠在右侧
Qt::TopToolBarArea    // 停靠在顶部
Qt::BottomToolBarArea // 停靠在底部
Qt::AllToolBarAreas   // 以上四个位置都可停靠

        还可以设置允许停放到哪些边缘,通过 QToolBar 中的 setAllowedAreas 方法就可以设置。我们可以设置工具栏1只能停在上下,工具栏2只能停在左右。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 获取菜单栏
    QMenuBar* menuBar = this->menuBar();
    this->setMenuBar(menuBar);

    // 创建两个工具栏
    QToolBar* toolBar1 = new QToolBar();
    this->addToolBar(toolBar1);
    QToolBar* toolBar2 = new QToolBar();
    this->addToolBar(Qt::LeftToolBarArea, toolBar2);

    toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
    toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

    // 创建两个菜单项
    QAction* action1 = new QAction("新建文件或项目");
    QAction* action2 = new QAction("打开文件或项目");

    // 添加到工具栏,并加上图标
    toolBar1->addAction(action1);
    action1->setIcon(QIcon(":/image/file.png"));
    toolBar2->addAction(action2);
    action2->setIcon(QIcon(":/image/directory.png"));
}

设置浮动属性

        工具栏默认是可以浮动的,也就是拖动工具栏可以让他停在界面中,如果设置了不可浮动,那么工具栏就会自动停靠,设置方法就要通过QToolBar中的setFloatable方法。

// ...

// 创建两个工具栏
QToolBar* toolBar1 = new QToolBar();
this->addToolBar(toolBar1);
QToolBar* toolBar2 = new QToolBar();
this->addToolBar(Qt::LeftToolBarArea, toolBar2);

// 设置允许停靠位置
toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

// 设置浮动属性
toolBar1->setFloatable(false);
toolBar2->setFloatable(false);

//...

设置移动属性

        如果工具栏设置成了不可移动,那么工具栏就只能停留在初始位置了,想要设置移动属性就要通过QToolBar中的setMovable。

// 创建两个工具栏
QToolBar* toolBar1 = new QToolBar();
this->addToolBar(toolBar1);
QToolBar* toolBar2 = new QToolBar();
this->addToolBar(Qt::LeftToolBarArea, toolBar2);

// 设置允许停靠位置
toolBar1->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
toolBar2->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

// 设置浮动属性
toolBar1->setFloatable(false);
toolBar2->setFloatable(false);

// 设置不可移动
toolBar1->setMovable(false);
toolBar2->setMovable(false);

        效果就是工具栏只能停在初始位置,而且可拖动的图标也不见了。


状态栏

        状态栏往往是界面最下面一行,是应用程序中输出简要信息的区域,在Qt中是通过QStatusBar实现的,在状态栏中可以显示的消息类型有:

  • 实时消息:如当前程序状态。
  • 永久消息:如程序版本号。
  • 进度消息:如进度条,百分号形式提示。

创建状态栏

        上面我们也展示过ui文件中会创建MenuBar,也会创建StatusBar,所以它也要注意内存泄漏的问题。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 获取状态栏
    QStatusBar* statusBar = this->statusBar();
    this->setStatusBar(statusBar);
}

显示实时消息

        通过 showMessage 方法来实现。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 获取状态栏
    QStatusBar* statusBar = this->statusBar();
    this->setStatusBar(statusBar);

    // 显示实时消息
    statusBar->showMessage("这是一个消息,3000毫秒后消失", 3000);

}

        这个方法第一个参数就是文本,类型为QString;第二个参数为时间,类型为int,单位为ms,如果不填默认为0,消息永久存在。

添加控件

        在状态栏中也是可以添加控件的,添加控件的方式有两种,分别是addWidget和addPermanentWidget,第一种是从左往右添加控件,第二种是从右往左添加控件,而且控件之间也可以设置拉伸系数。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 获取状态栏
    QStatusBar* statusBar = this->statusBar();
    this->setStatusBar(statusBar);

    QLabel* label = new QLabel("这是一个QLabel");
    statusBar->addWidget(label, 1);

    QLineEdit* lineEdit = new QLineEdit();
    lineEdit->setPlaceholderText("这是一个QLineEdit");
    statusBar->addPermanentWidget(lineEdit, 1);
}


浮动窗口

        在 Qt 中,浮动窗口也被称为子窗口,浮动窗口是通过 QDockWidget 来实现浮动的功能。浮动窗口一般是位于核心部件的周围,可以有多个。

创建浮动窗口

        创建浮动窗口就要使用QDockWidget,这个函数也有两个参数,一个是位置参数,一个是要添加的浮动窗口。

        位置参数和上面的工具栏的参数差不多,名字是不同的。

Qt::LeftDockWidgetArea 停靠在左侧
Qt::RightDockWidgetArea 停靠在右侧
Qt::TopDockWidgetArea 停靠在顶部
Qt::BottomDockWidgetArea 停靠在底部
Qt::AllDockWidgetAreas 以上四个位置都可停靠

        这就可以把我们之前学习过的控件结合起来。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 给主窗口添加一个子窗口
    QDockWidget* dockWidget = new QDockWidget();
    // 使用addDockWidget方法把浮动窗口添加到主窗口中
    this->addDockWidget(Qt::TopDockWidgetArea, dockWidget);

    // 设置浮动窗口的标题
    dockWidget->setWindowTitle("这是一个浮动窗口");

    // 给浮动窗口内部添加一些其他控件
    // 但是一个dockWidget只能添加一个控件,所以要添加一个QWidget,再往QWidget中添加控件
    // 最后再把QWidget设置到dockWidget中
    QWidget* widget = new QWidget();
    dockWidget->setWidget(widget);

    // 创建水平布局管理器,把管理器添加到QWidget中
    QVBoxLayout* layout = new  QVBoxLayout();
    widget->setLayout(layout);

    // 创建一个其他控件到layout中
    QLabel* label = new QLabel("这是一个QLabel");
    QPushButton* button = new QPushButton("这是一个按钮");
    layout->addWidget(label);
    layout->addWidget(button);
}


对话框

        对话框时图形化开发程序中不可或缺的组成部分。它就是平常使用电脑时弹出的一个框,主要就是为了实现一些“短平快”的操作,它通常是一个顶层窗口 ,出现在程序的最上层,Qt中常用的内置对话框有:QFileDialog(文件对话框)、QColordialog(颜色对话框)、QFontDialog(字体对话框)、QInputDialog(输入对话框)和QMessageBox(消息框)。

        在创建项目的时候也是除了可以选择创建QWidget和QMainWindow,还可以选择创建QDialog,这几种项目的创建就是改了一下继承的类名,差别也不大。除了QMainWindow,它和QWidget也是差不多的。

        它也继承了QWidget,并且也有自己的属性。

        当然实际开发中往往不会在创建项目时就创建一个继承了的QDiglog,而是在代码中创建额外的类,让这个类继承QDialog。

        我们还是使用QMainWindow来实现对话框,通过点击一个按钮,弹出一个对话框。

void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);
    // 设置标题
    dialog->setWindowTitle("对话框标题");
    // 调整大小
    dialog->resize(300, 200);
    // show方法,显示对话框
    dialog->show();
}

        我们可以不断点击按钮来创建对话框,不同于其他控件的是,每次都会创建一个新的对话框,但是不释放就会造成内存泄漏。

        既然出现内存泄漏,那简单,释放一下不就好了吗,在槽函数最后delete一下这个QDialog,那就会出现新的问题,这个对话框也就存在了一瞬间,每次点击按钮clicked函数中创建和销毁都会执行,所以也不能在这里delete。

        正确的方式是在点击对话框的关闭按钮再释放。

void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);
    // 设置标题
    dialog->setWindowTitle("对话框标题");
    // 调整大小
    dialog->resize(300, 200);
    // show方法,显示对话框
    dialog->show();

    // 把delete和关闭按钮的点击信号关联起来
    // Qt中给QDialog设置一个属性就可以在关闭的时候触发delete,参数是Qt内置的功能
    dialog->setAttribute(Qt::WA_DeleteOnClose);
}

创建对话框

        前面也说过,想要自定义对话框通常要继承QDialog创建一个类,我们先来通过代码的方式创建一个对话框。

        我们先新建一个类,类名和它的父类写上,点击下一步就可以了。

        在构造函数中添加一个参数,这样就可以让我们的类也指定一个父元素,从而挂到对象树上。

        在mainwindow.cpp中包含dialog.h(头文件),槽函数没有太大变化。

        现在对话框就可以显示出来了,再向里面加入一些控件,现在Dialog就是父窗口了,所以就要在dialog.cpp中也就是dialog的构造函数中添加控件。

        

        以上就是代码的创建方式,下面我们就来看看如何使用图形化界面的方式设置对话框,在创建项目的时候选择下面的文件和类中的Qt,选择Qt 设计师界面类。

        界面模版还是选择Dialog,并且没有button的这一个。

        创建好后就可以看到项目中出现了两个ui文件。

        之后我们就可以通过拖拽把控件添加到界面。

        然后写好两个槽函数就可以了。

对话框的分类

        上面我们说对话框也有自己的属性,其中有一个是modal,把对话框分为模态对话框非模态对话框

        模态对话框弹出的时候,用户无法操作父窗口,必须要执行完对话框的操作,关闭对话框之后才可以操作父窗口;非模态对话框弹出的时候,用户是可以操作父窗口的。

        可以试一下,如果不勾选这个属性,那么弹出对话框就可以一直操作,弹出无数个对话框。

        所以模态就用于关键场合,用户必须做出决策。

        前面我们使用的是show这个方法,还有一个方法是exec,这就可以生成一个模态对话框。

Qt 内置对话框

        对话框一开始我就说过了Qt中有多种内置的可复用的对话框,他们都继承了QDialog,下面我们就逐个看看他们是怎样的。

QMessageBox

        消息对话框是应用程序中最常用的界面元素。消息对话框主要用于为用户提示重要信息,强制用户进行选择操作。

void MainWindow::on_pushButton_clicked()
{
    // 创建 QMessageBox
    QMessageBox* messageBox = new QMessageBox(this);
    messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放
    
    messageBox->setWindowTitle("MessageBox标题");
    messageBox->setText("MessageBox本文");
    messageBox->setIcon(QMessageBox::Warning); // 图标
    messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); // 按钮
    
    // QMessageBox通常是模态的
    messageBox->exec();
    
}

         这些图标和按钮也是Qt内置的,是自动生成的。

enum Icon {
    // keep this in sync with QMessageDialogOptions::Icon
    NoIcon = 0,      // 无图标
    Information = 1, // 提示
    Warning = 2,     // 警告
    Critical = 3,    // 严重
    Question = 4     // 疑问
};

enum StandardButton {
    // keep this in sync with QDialogButtonBox::StandardButton and QPlatformDialogHelper::StandardButton
    NoButton           = 0x00000000,
    Ok                 = 0x00000400,
    Save               = 0x00000800,
    SaveAll            = 0x00001000,
    Open               = 0x00002000,
    Yes                = 0x00004000,
    YesToAll           = 0x00008000,
    No                 = 0x00010000,
    NoToAll            = 0x00020000,
    Abort              = 0x00040000,
    Retry              = 0x00080000,
    Ignore             = 0x00100000,
    Close              = 0x00200000,
    Cancel             = 0x00400000,
    Discard            = 0x00800000,
    Help               = 0x01000000,
    Apply              = 0x02000000,
    Reset              = 0x04000000,
    RestoreDefaults    = 0x08000000,

    FirstButton        = Ok,                // internal
    LastButton         = RestoreDefaults,   // internal

    YesAll             = YesToAll,          // obsolete
    NoAll              = NoToAll,           // obsolete

    Default            = 0x00000100,        // obsolete
    Escape             = 0x00000200,        // obsolete
    FlagMask           = 0x00000300,        // obsolete
    ButtonMask         = ~FlagMask          // obsolete
};

        除了QMessageBox中的setStandardButtons方法,使用Qt自动生成的按钮,还可以添加按钮,使用的是addButton方法,这个方法的第一个参数为要添加的按钮,第二个参数为ButtonRole类型,这也是QMessageBox中的一个枚举类型。

void MainWindow::on_pushButton_clicked()
{
    // 创建 QMessageBox
    QMessageBox* messageBox = new QMessageBox(this);
    messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放

    messageBox->setWindowTitle("MessageBox标题");
    messageBox->setText("MessageBox本文");
    messageBox->setIcon(QMessageBox::Warning); // 图标

    QPushButton* button = new QPushButton("按钮", messageBox);
    messageBox->addButton(button, QMessageBox::AcceptRole); // 表示Ok,接受

    // QMessageBox通常是模态的
    messageBox->exec();

}

        如果不添加我们自己创建的按钮,那该如何使用信号和槽呢?Qt中setStandardButtons是自动生成的按钮,也无法关联槽函数。

        关联信号和槽也比较“麻烦”,不使用信号和槽也可以获取按钮信息,对话框设置好后,需要使用exec方法弹出模态对话框,这个方法就可以获取点击按钮的返回值,通过这个返回值就可以知道用户点击了那个按钮。

void MainWindow::on_pushButton_clicked()
{
    // 创建 QMessageBox
    QMessageBox* messageBox = new QMessageBox(this);
    messageBox->setAttribute(Qt::WA_DeleteOnClose); // 关闭后释放

    messageBox->setWindowTitle("MessageBox标题");
    messageBox->setText("MessageBox本文");
    messageBox->setIcon(QMessageBox::Warning); // 图标
    messageBox->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel); // 按钮

    // QMessageBox通常是模态的
    int result = messageBox->exec();
    if (result == QMessageBox::Ok)
    {
        qDebug() << "Ok";
    }
    else if (result == QMessageBox::Save)
    {
        qDebug() << "Save";
    }
    else if (result == QMessageBox::Cancel)
    {
        qDebug() << "Cancel";
    }
}

        创建对话框的方法不止这一种,还有一种就是使用QMessageBox中的静态函数。

void MainWindow::on_pushButton_clicked()
{
    QMessageBox::warning(this, "MessageBox标题", "MessageBox文本", QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel);
}

        就这短短的一行就可以支持我们刚才的功能,这个函数也是支持返回值的,所以想要获取返回值就可以拿一个int类型的变量获取。

        所以,如果想要在对话框中实现一些简单的功能,就可以使用这种方式,如果想要在对话框中添加一些控件,还是使用上面的方式更好。

QColorDialog

        颜色对话框是允许用户选择颜色的,它也继承了QDialog,具体的就是显示一个调色板。

        下面我们就看看Qt中如何弹出一个QColorDialog。

void MainWindow::on_pushButton_clicked()
{
    QColorDialog* colorDialog = new QColorDialog(this);
    colorDialog->exec();

    colorDialog->setAttribute(Qt::WA_DeleteOnClose);
}

        但是通常不会使用这种方法,我们使用的是QColorDialog中的getColor方法,这个方法能够弹出一个模态对话框,用户选择颜色,确认后关闭,getColor返回一个值,这就是用户选择的值,是不是很像QMessageBox中的静态函数,它其实也是一个静态函数,不用创建对话框对象就可以直接使用。

void MainWindow::on_pushButton_clicked()
{
    QColor color = QColorDialog::getColor(QColor(0, 0, 0), this, "QColorDialog");
    qDebug() << color;
}

        这个函数的第一个参数类型为QColor,为初始默认值;第二个参数为parent,为父元素;第三个参数为标题;第四个参数是一个选项。

        通过打印返回值我们可以看到,返回值的形式是ARGN的形式,A为alpha,不透明度,所以第一个参数就是它,后面也是使用0~1的小数表示RGB的值。

void MainWindow::on_pushButton_clicked()
{
    QColor color = QColorDialog::getColor(QColor(0, 0, 0), this, "QColorDialog");
    qDebug() << color;

    // 基于这个颜色修改窗口的背景色
    // 可以通过QSS的方式设置背景色
    QString style = "background-color: rgb(" + QString::number(color.red()) + ", " \
                                             + QString::number(color.green()) + ", "\
                                             + QString::number(color.blue()) + ");";

    this->setStyleSheet(style);
}

QFileDialog

        文件对话框用于应用程序中需要打开一个外部文件或需要当前内容存储到指定的外部文件。

        它的常用方法有:

  • 打开文件 (一次只能打开一个文件)
    QString getOpenFileName(QWidget *parent = nullptr, 
                            const QString &caption = QString(), 
                            const QString &dir = QString(), 
                            const QString &filter = QString(), 
                            QString *selectedFilter = nullptr, 
                            QFileDialog::Options options = Options());
  •  打开多个文件 (一次可以打开多个文件)
    QStringList getOpenFileNames(QWidget *parent = nullptr, 
                                 const QString &caption = QString(),
                                 const QString &dir = QString(), 
                                 const QString &filter = QString(), 
                                 QString *selectedFilter = nullptr, 
                                 QFileDialog::Options options = Options());
  • 保存文件
    QString getSaveFileName(QWidget *parent = nullptr, 
                            const QString &caption = QString(), 
                            const QString &dir = QString(), 
                            const QString &filter = QString(), 
                            QString *selectedFilter = nullptr, 
                            QFileDialog::Options options = Options());

        下面看看弹出的对话框是什么样的。

void MainWindow::on_pushButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this);
    qDebug() << filePath;
}

void MainWindow::on_pushButton_2_clicked()
{
    QString filePath = QFileDialog::getSaveFileName(this);
    qDebug() << filePath;
}

        在打开文件的对话框中,点击按钮,点击打开就会返回这个文件的路径,上面还有一个类似ComboBox的下拉框,这就是文件的类型,可以在getOpenFileName的filter参数中设置。

        保存文件的对话框据需要输入要保存文件的文件名,输入后点击保存就会返回这文件的路径。

        虽然可以返回路径,由于没有后续操作,所以只是返回路径而已,上述两种功能都是需要额外去实现的。

QFontDialog

        Qt 中提供了预定义的字体对话框类,这个对话框可以支持选择字体,使用方法也是类似的,getFont,返回一个QFont对象。

void MainWindow::on_pushButton_clicked()
{
    bool ok = false;
    QFont font = QFontDialog::getFont(&ok, this);
    qDebug() << ok;
    qDebug() << font;
}

        这个方法的参数第一个是一个bool值,作为输出型参数,如果点击了OK,返回true,如果直接关闭的对话框或点击Cancel,那就是false。

        我们就可以通过获取的QFont对象给其他控件设置Font属性。

void MainWindow::on_pushButton_clicked()
{
    bool ok = false;
    QFont font = QFontDialog::getFont(&ok, this);
    qDebug() << ok;
    qDebug() << font;

    if (ok == true)
        ui->pushButton->setFont(font);
}

QInputDialog

        Qt 中提供了预定义的输入对话框类,用于临时数据的输入。

        它有这几个静态方法,getInt(输入整数)、getDouble(输入双精度浮点数)、getItem他们几个的静态方法都差不多,参数也差不多,一看也就明白了。

void MainWindow::on_pushButton_clicked()
{
    int result = QInputDialog::getInt(this, "整数输入", "请输入一个整数");
    qDebug() << result;
}


void MainWindow::on_pushButton_2_clicked()
{
    double result = QInputDialog::getDouble(this, "浮点数输入", "请输入一个浮点数");
    qDebug() << result;
}

void MainWindow::on_pushButton_3_clicked()
{
    QStringList items;
    items.push_back("第1个");
    items.push_back("第2个");
    items.push_back("第3个");
    QString item = QInputDialog::getItem(this, "条目型输入", "请输入", items);
    qDebug() << item;
}


总结

        对于 Qt 中窗口的设置已经了解的差不多了。现在我们知道,一个窗口包括:

  • 菜单栏(QMenuBar)
    • 菜单(QMenu)
      • 菜单项(QAction)
  • 工具栏(QToolBar)
    • 菜单项(QAction)
  • 子窗口(QDockWidget)
    • QWidget
      • 其他控件
  • 状态栏(QStatusBar)
    • QWidget
  • 对话框(QDialog)
    • 内置的对话框

        一个窗口可以包含这么多的元素,上一篇中的Widget可能只是一个窗口,但实际的程序就有多个窗口多个对话框等一同构成的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FreeRTOS学习笔记-基于stm32(14)内存管理

一、FreeRTOS 内存管理简介 FreeRTOS有两种方法来创建任务&#xff0c;队列&#xff0c;信号量等&#xff0c;一种动态一种静态。静态方法需要手动定义任务堆栈。使用动态内存管理的时候 FreeRTOS 内核在创建任务、队列、信号量的时候会动态的申请 RAM。 我们在移植FreeRTOS时可…

由于人工智能,他们的语言更容易理解

密歇根大学、墨西哥国家天体物理研究所和光学与电子研究所的研究人员正在使用人工智能模型来破译狗的语言。 在国际会议上提出的新研究展示了先进的人工智能 模型如何帮助人类了解动物。 密歇根大学人工智能实验室主任 Rada Mihalcea 强调了这项研究的重要性&#xff1a;对于…

Javaweb03-Servlet技术1(Servlet,ServletConfig,ServletContext)

Servlet技术(Servlet,ServletConfig,ServletContext) 1.Servlet的概述 Servlet是运行在Web服务器端的Java应用程序&#xff0c;它使用Java语言编写。与Java程序的区别是&#xff0c;Servlet 对象主要封装了对HTTP请求的处理&#xff0c;并且它的运行需要Servlet容器(Tomcat)的…

【五】Linux软件仓库Yum源--SSH远程控制--SCP远程传输

RPM&#xff08;红帽软件包管理器&#xff09; RPM建立统一的数据库文件&#xff0c;记录软件信息并分析依赖关系。目前RPM的优势已经被公众所认可&#xff0c;使用范围也已不局限在红帽系统中了。常见RPM命令如下&#xff1a; 安装软件 rpm -ivh file…

BitSet位图进行去重海量数据

问题 怎么在40亿个整数中找到唯一重复的数字? 1.Set的不可重复性 if(set.contains(x))System.out.println("重复的数字是"x);else{set.add(x);}但是&#xff0c;contains()方法消耗的时间&#xff0c;消耗的空间很大&#xff0c;毕竟有约40亿的数据&#xff0c;所…

Vue--》打造细腻颗粒感 —— 细分组件颗粒图

写文背景&#xff1a;当涉及到前端开发时&#xff0c;我们经常会发现自己在不同的组件中复用相似的逻辑&#xff0c;在过去我们可能会通过混入、高阶组件或者全局组件等方式来实现代码的复用&#xff1b;或者一个组件逻辑太多&#xff0c;写出了超多的响应式ref数据和五花八门的…

[大模型]LLaMA3-8B-Instruct langchain 接入

环境准备 在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1 接下来打开刚刚租用服务器的 JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下载和运行演示。 pip 换…

华为鲲鹏应用开发基础:鲲鹏处理器及关键硬件特性介绍(二)

1. 鲲鹏简介 1.1 鲲鹏处理器简介 鲲鹏处理器是华为自研的基于ARMv8指令集开发的数据中心级处理器 1.2 基于鲲鹏主板的多样化计算产品 1.3 基于鲲鹏920的华为TaiShan(泰山) 200服务器 1.3.1 TaiShan 2280服务器内部视图 1.3.2 TaiShan 2280服务器物理结构 1.3.3 TaiShan 2280服…

【Java】解决Java报错:IOException during File Operations

文章目录 引言一、IOException的定义与概述1. 什么是IOException&#xff1f;2. IOException的常见触发场景3. 示例代码 二、解决方案1. 检查文件是否存在2. 使用try-with-resources语句3. 捕获和处理IOException4. 使用NIO进行文件操作 三、最佳实践1. 检查文件状态2. 使用try…

缓冲区的奥秘:解析数据交错的魔法

目录 一、理解缓存区的好处 &#xff08;一&#xff09;直观性的理解 &#xff08;二&#xff09;缓存区的好处 二、经典案例分析体会 &#xff08;一&#xff09;文件读写流&#xff08;File I/O Buffering&#xff09; BufferedOutputStream 和 BufferedWriter 可以加快…

四川古力未来科技抖音小店打造品质生活,可靠之选引领潮流

在当今数字化快速发展的时代&#xff0c;电商平台如雨后春笋般涌现&#xff0c;抖音小店作为其中的佼佼者&#xff0c;凭借其独特的短视频电商模式&#xff0c;迅速吸引了大批年轻消费者的目光。而在众多的抖音小店中&#xff0c;四川古力未来科技抖音小店凭借其卓越的品质和专…

数字时代网络安全即服务的兴起

在日益数字化的世界里&#xff0c;威胁形势不断演变&#xff0c;网络攻击变得越来越复杂和频繁。当组织努力保护敏感数据并保持运营完整性时&#xff0c;传统的网络安全措施往往不够。 这为更具动态性和可扩展性的解决方案铺平了道路&#xff1a;网络安全即服务 (CSaaS)。网络…

数据结构---排序算法

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

【短剧看剧系统之投流版】短剧看剧系统功能更新,前端uniapp搭建开发

目录 一、常规款短剧系统和投流版的区别&#xff1f; 二、后端体系 1.管理端&#xff1a; 2.代理投流端 三、功能区别 总结&#xff1a; 前言&#xff1a; 短剧看剧系统目前在抖音端是比较热门的&#xff0c;最重要的功能就是可以接入第三方cps&#xff0c;包含类目报白…

如何将JPG/PNG位图免费快速一键转换成SVG格式的矢量图

环境&#xff1a; JPG/PNG位图 问题描述&#xff1a; 如何将JPG/PNG位图快速一键转换成SVG格式的矢量图 解决方案&#xff1a; 是一个人工智能驱动的图片转换工具&#xff0c;可以帮助用户将」JPG/PNG位图快速转换成SVG格式的矢量图&#xff0c;方便设计人员对图片进行二次…

AIGC提示词---如何写提示词?

你真的了解你的AI助手吗&#xff1f; 想象一下&#xff0c;你和别人使用相同的AI工具&#xff0c;但为何他的工作效率总是高出一截&#xff1f;秘诀可能就藏在那些看似简单的提示词里。精准的提示词是解锁AI潜能的关键&#xff0c;它们能让AI更好地理解你的需求&#xff0c;从…

【AI大模型】Transformers大模型库(八):大模型微调之LoraConfig

目录 一、引言 二、LoraConfig配置参数 2.1 概述 2.2 LoraConfig参数说明 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库&#xff0c;为huggingface上数以万计的预训练大模型提供预测、训练等服务。 &#x1f917; Transformers …

Spring中事务的隔离级别和传播机制

上一篇博客中讲解了关于事务的两种使用方式包括Transactional的详解。 Transactional 注解当中的三个常⻅属性: 1. rollbackFor: 异常回滚属性. 指定能够触发事务回滚的异常类型. 可以指定多个异常类型 2. Isolation: 事务的隔离级别. 默认值为 Isolation.DEFAULT 3. propagat…

原腾讯云副总裁张纾翔加入矩阵起源,共筑人工智能新篇章

近日&#xff0c;原腾讯云副总裁张纾翔先生正式加入矩阵起源&#xff0c;担任合伙人兼高级副总裁&#xff0c;全面负责矩阵起源商业化工作。 矩阵起源成立于2021年。公司创始团队来自腾讯云、Snowflake等国内外一流的互联网企业、软件公司、数字化企业和开源社区&#xff0c;核…

什么是PMP,含金量高吗?

01PMP是什么&#xff1f; PMP(Project Management Professional)是项目管理领域的高级认证&#xff0c;它被PMI在全球200多个国家和地区广泛推广&#xff0c;被视为项目管理领域内最具含金量的认证之一。持有PMP证书的项目经理不仅能提升其项目管理能力&#xff0c;同时也显著…