2 QMainWindow及其控件
2.1 QMainWindow菜单栏和工具栏
-
QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。
-
菜单栏只能有一个,但工具栏可以有多个。本节主要讲述菜单栏和工具栏的基本创建方法。
类名 | 功能 | 方法 |
---|---|---|
菜单栏类QMenuBar | 将菜单栏放入窗口 | void QMainWindow::setMenuBar(QMenuBar *menuBar) |
创建菜单 | QMenu *QMenuBar::addMenu(const QString &title) | |
菜单类QMenu | 创建菜单项 | QAction *QMenu::addAction(const QString &text) |
菜单栏添加分割线 | QAction *QMenu::addSeparator() | |
菜单项类QAction | ||
工具栏类QToolBar | 将工具栏放入窗口并指定初始停靠位置 | QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar) |
指定工具栏可以停靠的位置 | void *QToolBar::setAllowedAreas(Qt::ToolBarAreas areas) | |
指定工具栏是否可以浮动 | void *QToolBar::setFloatable(bool floatable) | |
指定工具栏是否可以移动 | void *QToolBar::setMovable(bool movable) | |
创建菜单项 | QAction *QToolBar::addAction(const QString &text) | |
工具栏添加分割线 | QAction *QToolBar::addSeparator() | |
工具栏添加控件 | QAction *QToolBar::addWidget(QWidget *widget) |
//菜单栏创建,最多只能有一个
QMenuBar *bar=new QMenuBar;
//将菜单栏放入窗口中
setMenuBar(bar);
//创建菜单
QMenu *fileMenu=bar->addMenu("文件");
QMenu *editMenu=bar->addMenu("编辑");
QMenu *buildMenu=bar->addMenu("构建");
//创建菜单项
QAction *newAction=fileMenu->addAction("新建");
//添加分割线
fileMenu->addSeparator();
QAction *openAction=fileMenu->addAction("打开");
//工具栏创建,可以有多个
QToolBar *toolBar=new QToolBar(this);
//将工具栏放入窗口并指定初始停靠位置
addToolBar(Qt::LeftToolBarArea,toolBar);
//指定工具栏可以停靠的位置
toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//指定工具栏是否可以浮动
toolBar->setFloatable(false);
//指定工具栏是否可以移动
toolBar->setMovable(true);
//工具栏中创建菜单项
toolBar->addAction(newAction);
//添加分割线
toolBar->addSeparator();
// 工具栏中添加控件
QPushButton *btn=new QPushButton("aa",this);
toolBar->addWidget(btn);
2.2 QMainWindow状态栏、铆接部件和中心部件
- 状态栏只能有一个,且停留在窗口的下方。铆接部件可以有多个,可以理解成浮动窗口,中心部件只能有一个,但它不是一个具体的类,本例中使用文字编辑框QTextEdit作为中心部件。
状态栏类QStatusBar | 将状态栏放入窗口 | void QMainWindow::setStatusBar(QStatusBar *statusbar) |
---|---|---|
状态栏左端添加控件(常添加标签QLabel) | void QStatusBar::addWidget(QWidget *widget, int stretch = 0) | |
状态栏右端添加控件(常添加标签QLabel) | void QStatusBar::addPermanentWidget(QWidget *widget, int stretch = 0) | |
标签类QLabel | ||
铆接部件类QDockWidget | 将铆接部件放入窗口并指定初始停靠位置 | void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget) |
指定铆接部件可以停靠的位置 | void *QDockWidget::setAllowedAreas(Qt::DockWidgetAreas areas) | |
文字编辑框类QTextEdit | ||
中心部件 | 设…为中心部件 | void QMainWindow::setCentralWidget(QWidget *widget) |
//状态栏最多只有一个
QStatusBar *stBar=new QStatusBar;
setStatusBar(stBar);
//放标签控件
QLabel *label1=new QLabel("提示信息",this);
stBar->addWidget(label1);
QLabel *label2=new QLabel("右侧提示信息",this);
stBar->addPermanentWidget(label2);
//铆接部件(浮动窗口),可以有多个
QDockWidget *dockWidget=new QDockWidget("浮动",this);
addDockWidget(Qt::TopDockWidgetArea,dockWidget);
dockWidget->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea);
//设置中心部件
QTextEdit *edit=new QTextEdit("123",this);
setCentralWidget(edit);
2.3 UI窗口编辑和资源文件的添加
- 在新建时勾选
Generate Form
即可添加UI界面。
- 右侧对象列表可以清晰看到所有类对象,并可在属性栏更改属性。
-
注意添加菜单项的时候先输入英文,再在text里改成中文。
-
有些组件需要添加图标(Icon),则需要添加资源文件。
-
**步骤1:右击项目->添加新文件->Qt->Qt Resource File->设置名称res **即可添加资源文件res.qrc。
-
步骤2:右击资源文件->Open in Editor->Add Prefix(添加前缀)不加可以写/ ->Add Files 即可添加图片资源(要先把资源文件放到工程目录下)。
-
-
更改图标用代码实现有两种方式:绝对路径/相对路径(推荐)。
//绝对路径,需要敲出完整路径代码
ui->actionnew->setIcon(QIcon("E:/Qt Projects/2_28_3/Icon/xinwen.png"));
//相对路径,需要写 :/ + 前缀 + 路径 + 文件名
ui->actionnew->setIcon(QIcon(":/Icon/xinwen.png"));
- 更改图标也可在UI界面实现,选择资源,找到图标即可。
2.4 模态和非模态对话框创建
- 模态对话框打开时不可以对其他窗口进行操作,非模态对话框可以。
#include <QDialog>
connect(ui->actionnew,&QAction::triggered,[=](){
//模态对话框,不可以对其他窗口进行操作
QDialog dlg(this);
dlg.resize(200,100);
dlg.setWindowTitle("模态");
//代码阻塞到这行,直到关闭模态对话框
dlg.exec();
qDebug()<<"模态对话框弹出了";
//非模态对话框,可以对其他窗口进行操作,放在堆区防止一闪而过
QDialog *dlg2=new QDialog(this);
dlg2->resize(200,100);
dlg2->setWindowTitle("非模态");
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose);//关闭时自动释放,防止内存泄露
qDebug()<<"非模态对话框弹出了";
});
- 注意点:模态对话框可以在堆区创建,也可不在堆区创建,因为代码阻塞无法自动释放。非模态对话框必须在堆区创建,并调用show方法显示,且显示时代码已经运行到下面了(未阻塞)。因为每次创建非模态对话框都在堆区创建,直到关闭程序才会释放所有堆区变量,为了避免内存泄漏,可以调用
setAttribute
方法让非模态对话框关闭时自动释放。
2.5 消息对话框
-
所谓标准对话框
<QMessageBox>
,是 Qt 内置的一系列对话框,用于简化开发。事实上,有很多对话框都是通用的,比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。Qt 的内置对话框大致分为以下几类:
-
QColorDialog: 选择颜色;
-
QFileDialog: 选择文件或者目录;
-
QFontDialog: 选择字体;
-
QInputDialog: 允许用户输入一个值,并将其值返回;
-
QMessageBox: 模态对话框,用于显示信息、询问问题等;
-
QPageSetupDialog: 为打印机提供纸张相关的选项;
-
QPrintDialog: 打印机配置;
-
QPrintPreviewDialog: 打印预览;
-
QProgressDialog: 显示操作过程。
-
-
消息对话框最常用,我们可以使用一些静态方法来很简单的调用:
对话框类型 | 返回值 | 方法 |
---|---|---|
关于 | void | about(QWidget *parent, const QString &title, const QString &text) |
关于QT | void | aboutQt(QWidget *parent, const QString &title = QString()) |
错误 | QMessageBox::StandardButton | critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton) |
信息 | QMessageBox::StandardButton | information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton) |
提问 | QMessageBox::StandardButton | question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = StandardButtons(Yes | No), QMessageBox::StandardButton defaultButton = NoButton) |
警告 | QMessageBox::StandardButton | warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton) |
- 以提问对话框为例,第一个参数为父亲,第二个参数为对话框标题,第三个参数为对话框文字,第四个参数为对话框上要显示的标准按钮,第五个参数为回车指向的默认按钮。
QMessageBox::question(this,"保存提示","关闭前是否要保存此文件?",QMessageBox::Cancel|QMessageBox::Save,QMessageBox::Save);
- 以提问对话框为例,因为返回值是
StandardButtons
类型,可以用if
接收去比较。
if(QMessageBox::Cancel == QMessageBox::question(this,"保存提示","关闭前是否要保存此文 件?",QMessageBox::Cancel|QMessageBox::Save,QMessageBox::Save);)
{
//执行语句
}
2.6 其他对话框
颜色对话框
- 需要包含头文件
<QColorDialog>
,其中常用的是选择颜色QColorDialog::getColor
函数。
connect(btn,&QPushButton::clicked,[=](){
QColor color = QColorDialog::getColor(QColor(255,255,255),this,"选择颜色!");
qDebug()<<"r:"<<c.red()<<" g:"<<c.green()<<" b:"<<c.blue();
});
- 返回值是颜色类型。第一个参数是默认颜色,第二个参数是父亲,第三个参数是标题名,第四个参数是选项(默认即可)。可以通过
.red()
等方法获取用户选择的颜色数值。
文件对话框
- 需要包含头文件
<QFileDialog>
,其中常用的是打开文件QFileDialog::getOpenFileName
函数。
connect(btn,&QPushButton::clicked,[=](){
QString qstr = QFileDialog::getOpenFileName(this,"打开文件","C:/Users/Divin\\Desktop","(*.txt)");
qDebug()<<qstr;
});
- 返回值是选择的文件路径。第一个参数是父亲,第二个参数是标题名,第三个参数是默认路径(其中
/
和\
通用,但是\
需要双写成\\
才能识别成转义字符\
),第四个参数是限定的后缀名。
字体对话框
- 需要包含头文件
<QFontDialog>
,其中常用的是获取字体QFontDialog::getFont
函数。
connect(btn,&QPushButton::clicked,[=](){
bool ok;
QFont font=QFontDialog::getFont(&ok,QFont("微软雅黑",36),this,"选择字体");
if(ok)
{
//用户选择了某字体
qDebug()<<"字体:"<<font.family().toUtf8().data()<<"字号:"<<font.pointSize()<<"是否加粗:"<<font.bold()<<"是否斜体:"<<font.italic();
}
else
{
//用户关闭了对话框,选用默认字体
qDebug()<<"字体:"<<font.family().toUtf8().data()<<"字号:"<<font.pointSize()<<"是否加粗:"<<font.bold()<<"是否斜体:"<<font.italic();
}
});
- 返回值是字体类型。第一个参数是运行完可能会改变的一个布尔值,表征用户是否通过"ok"键完成选择,第二个参数是默认字体字号,第三个参数是父亲,第四个参数是标题名。可以通过
.family()
方法获取字体名,pointSize()
方法获取字号,bold()
方法获取是否加粗(布尔值),italic()
方法获取是否斜体(布尔值)。
2.7 登录界面设计
- 在QT的UI窗口中可以很轻易地利用界面布局等工具设计一个登录界面。
- 上方两个
Label
控件和两个Line Edit
控件使用栅格布局,再用两个弹簧顶起来,下方登录和退出按钮使用水平布局,左右使用弹簧,中间也使用了弹簧,且设定了定长。 - 想设定窗口不可随意拖拽可以设定
maxmumSize
和minimumSize
为相同的大小。 - 布局都可以设置水平策略和垂直策略,将策略改为
Fixed
可以让它就占据它本身大小的位置(默认是Preferred
)。 - 布局中可以更改
layoutLeftMargin
等属性调整布局边缘间隙,在栅格布局中还可更改layoutHorizontalSpacing
等属性调整表格横竖的宽度占据。
2.8 按钮组
- 按钮组中主要有下面四种比较常见的按钮:普通按钮、工具按钮、单选按钮、复选按钮。
工具按钮Tool Button
- 工具按钮常用于显示文字+图片的形式,图片通过
Icon
属性添加并可改变图标大小,在输入文本后,需要更改toolButtonStyle
属性将文字放在图标下方或者旁边。可以更改autoRaise
属性更改按钮显示是否透明。
单选按钮Radio Button
- 单选按钮常常以一组的形式出现,需要放在
Group Box
控件中分组并修改布局。
- 代码中可以设定默认选择项,也可设定在用户点击按钮时触发相应事项。
//默认选择“男”
ui->rBtnMan->setChecked(true);
//用户选择“女”后打印一行字
connect(ui->rBtnWoman,&QRadioButton::clicked,[=](){
qDebug()<<"选中了女";
});
复选按钮Check Box
-
复选按钮和单选按钮类似,也需要分组并调整布局。
-
复选按钮可以在属性中勾选
tristate
三态属性,就可以让用户选择“半选”。
- 代码中可以设定默认选择项,也可设定在用户切换状态时触发相应事项
//默认选择半选
ui->cBox->setCheckState(Qt::PartiallyChecked);
//用户切换某复选按钮状态时打印状态
connect(ui->cBox,&QCheckBox::stateChanged,[=](int state){
qDebug()<<state;
});
2.9 ListWidget列表窗口控件(可直接双击编辑)
-
列表窗口可以在里面写几行诗,也可以设置居中格式(只有第一种方式可以)。
-
基本元素:
QListWidgetItem(QString str)
- 添加列表元素方法:
addItem(QString str)
addItem(QListWidgetItem* item)
addItems(QStringList strl)
- 添加列表元素方法:
//添加QListWidgetItem类
QListWidgetItem *item=new QListWidgetItem("床前明月光");
ui->listWidget->addItem(item);
//设置居中格式
item->setTextAlignment(Qt::AlignHCenter);
//直接添加文本
ui->listWidget->addItem("疑是地上霜");
//添加一个QStringList 类似于list<string>
QStringList list;
list<<"举头望明月"<<"低头思故乡";
ui->listWidget->addItems(list);
2.10 TreeWidget树窗口控件(可直接双击编辑)
- 可以做出下图表格树的效果。
- 基本元素:
QTreeWidgetItem(QStringList strl)
- 设置水平头方法:
setHeaderLabels(QStringList strl)
- 添加顶层节点方法:
addTopLevelItem(QTreeWidgetItem* item)
- 添加子节点方法:
addChild(QTreeWidgetItem *item)
- 设置水平头方法:
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"英雄简介");
QTreeWidgetItem *liItem=new QTreeWidgetItem(QStringList()<<"力量");
QTreeWidgetItem *minItem=new QTreeWidgetItem(QStringList()<<"敏捷");
QTreeWidgetItem *zhiItem=new QTreeWidgetItem(QStringList()<<"智力");
//加载顶层节点
ui->treeWidget->addTopLevelItem(liItem);
ui->treeWidget->addTopLevelItem(minItem);
ui->treeWidget->addTopLevelItem(zhiItem);
//追加子节点
QTreeWidgetItem *l1=new QTreeWidgetItem(QStringList()<<"法师"<<"造成大量法术伤害");
liItem->addChild(l1);
QTreeWidgetItem *l2=new QTreeWidgetItem(QStringList()<<"战士"<<"拥有钢铁般的盔甲");
liItem->addChild(l2);
QTreeWidgetItem *m1=new QTreeWidgetItem(QStringList()<<"盗贼"<<"来无影去无踪");
minItem->addChild(m1);
QTreeWidgetItem *z1=new QTreeWidgetItem(QStringList()<<"牧师"<<"具有超出常人的智慧");
zhiItem->addChild(z1);
2.11 TableWidget表格窗口控件(可直接双击编辑)
-
可以做表格(可编辑)。
-
基本元素:
QTableWidgetItem(QString str)
- 设置行数列数方法:
setColumnCount(int col)
setRowCount(int row)
- 设置表头方法:
setHorizontalHeaderLabels(QStringList strl)
- 设置元素方法:
setItem(row,col,QTableWidgetItem* item)
- 设置行数列数方法:
//设置行数、列数
ui->tableWidget->setColumnCount(3);
ui->tableWidget->setRowCount(5);
//设置表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
//ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟")); //可逐个添加
QStringList nameList;
nameList<<"赵云"<<"张飞"<<"关羽"<<"甄姬"<<"曹操";
QList<QString> sexList;
sexList<<"男"<<"男"<<"男"<<"女"<<"男";
for (int i=0;i<5;i++) {
int col=0;
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(nameList.at(i)));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexList.at(i)));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
}
QStringList
与QList<QString>
等价,都可以用.at()
或[]
索引。- 本例使用
for
循环遍历并利用数组将元素逐个填入。
2.12 其他控件
Containers容器
Scroll Area滚动区域
- 将控件拖拽进去,可以实现滚动效果。
Tool Box工具箱
- 可将不同控件拖拽到不同页面,实现QQ聊天中切换分组的效果。
- 更改页面名字在属性中
currentItemText
更改,添加页需要在右侧右击工具箱控件,点击插入页。
Tab Widget选项卡部件
-
可将不同控件拖拽到不同页面,实现浏览器中切换选项卡的效果。
Stacked Widget堆栈部件
- 可将不同页面拖动到不同的栈,实现切换页面的效果。
- 用户不能直接切换栈的页面,需要设置一些接口,如上图的三个按钮接口。
//设置初始页面为页面2
ui->stackedWidget->setCurrentIndex(2);
//按下saBtn切换到页面0
connect(ui->saBtn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(0);
});
//按下tbBtn切换到页面1
connect(ui->tbBtn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(1);
});
//按下twBtn切换到页面2
connect(ui->twBtn,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(2);
});
Input Widgets输入部件
Combo Box下拉框
- 可让用户下拉选择,也可设定按钮选择。
//添加可选项
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("奥迪");
//点击按钮选中奥迪
connect(ui->audiBtn,&QPushButton::clicked,[=](){
ui->comboBox->setCurrentIndex(2);
});
Display Widgets展示部件
Label标签
- 标签不仅可以显示文字,还可以显示图片,甚至动图(最好图片的宽和高要和控件的大小相同)。
//标签控件显示图片
ui->label_Image->setPixmap(QPixmap(":/music/Icon/aite.png"));
//标签控件显示动图
QMovie* movie=new QMovie(":/movie/movie/movie.gif");
ui->label_Image->setMovie(movie);
//注意需要播放才能正常显示
movie->start();