Qt——窗口

news2024/12/26 11:49:06

目录

概述

菜单栏

创建菜单栏

创建子菜单

添加分割线

添加图标

工具栏

创建工具栏

设置初始位置和停靠位置 

设置浮动属性

设置移动属性

状态栏

创建状态栏

显示实时消息

添加控件

浮动窗口

创建浮动窗口

对话框

创建对话框

对话框的分类

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可能只是一个窗口,但实际的程序就有多个窗口多个对话框等一同构成的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于.Net 框架实现WebSocket 简单通信——服务端

新建项目 创建一个.Net 框架的控制台程序。 添加包 项目 → 管理 NuGet 程序包打开包管理窗口&#xff0c;添加SuperWebSocket 程序包。 实现 项目 → 添加类打开添加新项窗口&#xff0c;添加一个C#类。 启动监听 WebSocketServer socket new WebSocketServer();Conso…

浅谈DALL-E2

目录 1.概述 2.诞生背景 3.作用 4.版本历史 5.模型和技术 6.应用场景 6.1.十个应用场景 6.2.游戏开发 7.接口 8.未来展望 9.总结 1.概述 DALL-E2 是由 OpenAI 开发的一个图像生成模型&#xff0c;可以根据文本描述生成高质量的图像。DALL-E2 是 DALL-E 的升级版&am…

【小白学Python】自定义图片的生成(一)

目录标题 安装Pillowdemo代码初次代码计划 个人需要&#xff0c;基于文字生成图片。 除了AI外&#xff0c;对于简单的图片&#xff0c;Python在这方面也非常擅长。 我算是一个Python小白&#xff0c;除了业余时尝试过Python基本语法的练习&#xff0c;从未真正使用过Python。…

电流的本质是什么

话说很久以前&#xff0c;科学发现纯靠人眼识别。有一天&#xff0c;泰勒斯(古希腊哲学家&#xff0c;被称为科学的祖师爷)一时手痒&#xff0c;拿着琥珀与皮毛摩擦。 结果他发现那种半透明的小石头&#xff0c;居然产生了吸引小物体的魔力。 面对这个现象&#xff0c;老泰开始…

CRM客户关系管理:全方位客户关系管理解决方案

CRM客户关系管理系统&#xff0c;基于Spring Cloud Alibaba、Spring Boot、MybatisPlus、Redis和VUE3 ElementUI微服务架构&#xff0c;提供全面的客户关系管理功能。系统智能化地管理客户信息、线索跟踪、商机开发、合同管理、回款计划等&#xff0c;助力企业提升客户满意度&a…

资产管理系统是什么?主要有哪些功能?

资产管理系统主要对企业的固定资产、流动资产、长期投资等进行综合管理&#xff0c;通过先进的条形码技术对资产实物从购置、领用、清理、盘点、借用归还、维修到报废进行全方位准确监管。 一、资产管理系统主要包括哪些功能&#xff1f; 1、资产管理 &#xff08;1&#xf…

掌握Python的全方位教程,2024年最新版本,初学者必备指南

哈喽&#xff0c;大家好&#xff01;热烈欢迎你迈出成为python开发者的第一步。我想这一定非常激动人心&#xff0c;对吧&#xff1f;无论你是刚刚开始学习编程&#xff0c;还是曾经用过其他语言有一定的编程经验&#xff0c;本书中课程将帮助你加速实现你学习python的目标。作…

vue30:组件通信

父子关系 1&#xff1a;父组件通过props将数据传递给子组件 2&#xff1a;子组件利用$emi通知父组件修改更新

CISP究竟适合谁?这四类人没跑了

在信息技术飞速发展的现在&#xff0c;网络安全已经成为了一个不可忽视的话题。 CISP&#xff0c;即注册信息安全专业人员&#xff0c;是网络安全领域内一项备受认可的专业认证。 但CISP究竟适合谁考呢&#xff1f;这不仅是一个技术问题&#xff0c;更是一个职业规划的问题。…

用友U8 许可更新

当登录U8客户端提示下面的界面时&#xff0c;需要联网更新许可 登录服务器&#xff0c;打开Win下面的许可管理 导入许可——在线同步许可 更新完成即可

重温react-01

创建react项目 // 第一步 npm install create-react-app -g // 第二步 create-react-app my-app目录介绍 my-app/README.md# 项目第三方依赖包node_modules/package.json# 一般用来存放静态依赖public/index.htmlfavicon.ico# 存放项目源代码&#xff0c;注意只有放在scr目录…

java:使用JSqlParser给sql语句增加tenant_id和deleted条件

# 示例代码 【pom.xml】 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-core</artifactId><version>3.4.3.1</version> </dependency>【MyJSqlParserTest.java】 package com.chz.myJSqlParser;pu…

短视频矩阵源码---矩阵托管1000个账号如何正规开发规则实现

一、短视频矩阵源码开发实现规则&#xff1a; 1.首先是确保各个官方平台api接口的稳定性&#xff0c;一定要是各个平台正规的api 2.其次是保证服务器运行&#xff0c;带宽保证能够并行&#xff0c;目前我们这边用的是源码所需服务器配置&#xff1a;规格:最低8核16G2、硬盘:系…

基于Sentry+OpenTelemetry实现微服务前后端全链路监控

文章目录 前⾔背景技术⽅案Sentry私有化部署部署环境准备 项目集成前端后端agent探针集成sentry sdk集成增强探针为⽇志注⼊TraceID异常处理SDK⾃定义开发sentry sdk⾃定义开发⾃定义SentryEvent注⼊otel追踪信息⾃定义全局异常上报issue事件新增动态过滤功能 Java Agent Exten…

【重拾数学知识】导数、极值和最值

前言 在深度学习中&#xff0c;梯度下降法是一种常用的优化算法&#xff0c;用于更新模型参数以最小化损失函数。这梯度下降法中涉及到数学中的导数、极值等相关知识&#xff0c;因此我们重新回顾相关内容&#xff0c;以便加深理解。 相关概念 导数 一个问题 如何求得一个…

Project 项目管理软件真的好用吗?

作为一个普通的职场人&#xff0c;或许只要掌握office全家桶&#xff0c;即可应对大部分工作。 但对项目经理来说&#xff0c;这是远远不够的。项目经理需要实时掌握项目进度、把关项目质量、应对项目风险、实时分析项目数据&#xff0c;做出正确的决策等等… 而拥有一款高效…

开发自动发消息插件需要用到的源代码!

在现今的数字化时代&#xff0c;自动发消息插件成为了许多应用程序中不可或缺的一部分&#xff0c;这些插件能够帮助我们自动化地完成消息发送任务&#xff0c;提高工作效率&#xff0c;节省时间成本。 那么&#xff0c;开发一个自动发消息插件究竟需要用到哪些关键的源代码呢…

C++STL初阶(4):初识vector

vector是一个类模版&#xff0c;是一个顺序容器&#xff0c;底层思维就是顺序表&#xff0c;而顺序表的本质就是一个可以改变size的数组。本篇基于string的学习基础&#xff0c;我们对vector进行一个大致的了解和学习 1.基本介绍 1. vector 是表示可变大小数组的序列容器&#…

【Unity自动化游戏框架】通用自动化游戏框架 爽到起飞的工作流 巨幅提升效率 质量 产能

https://github.com/sunsvip/GF_HybridCLRhttps://github.com/sunsvip/GF_HybridCLR 开始GF_HybridCLR自动化通用游戏框架&#xff0c;功能设计和用法的系列博文&#xff1b; GF_HybridCLR通用框架介绍 自动化工作流框架打包/HybridCLR热更流程 万人同屏战斗项目模板 前言: &…

2025年QS世界大学排名,美国大学表现如何?

大多数访问学者申请&#xff0c;在探讨QS大学排名中美国大学的表现时&#xff0c;我们不难发现这些学府在全球高等教育舞台上占据着举足轻重的地位。QS排名作为评估全球大学综合实力的重要指标之一&#xff0c;充分展示了美国大学在学术声誉、科研实力、教学质量和国际影响力等…