目录
Widget(组件),是Qt的核心概念,常叫做“控件”。控件是构成图形化界面的基本要素。
常见的控件有:按钮,输入框,下拉框,窗口等
在开发图形化界面时,为了布局和功能,控件有多种属性和管理对应属性的API
在Qt Designer中,已经有简便我们开发的图形化界面
- 左侧是Qt提供的所有的控件,可通过拖拽到程序界面的方式添加控件
- 选中一个控件,右下方会显示该控件的objectName,和其属性。后续使用代码开发时,可以通过ui->objectName的方式访问到该控件对象
一. enabled——是否可用
控件的首要目的是让用户使用,接受用户事件。而enabled属性是标识该控件是否可用
- 不可用,即“禁用”指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色
- 如果一个widget被禁用,则该widget的子元素也被禁用。例如一个窗口被禁用了,那么该窗口上的按钮,输入框等也会被禁用
API | 说明 |
isEnabled() | 获取该控件的可用状态 |
setEnabled() | 设置该控件是否可用,true表示可用,false表示禁用 |
示例:
通过拖拽添加两个按钮:pushButton和pushButton_enabled(各自的objectName)
接着右键控件,选中“转到槽”,再选择要关联的信号——clicked。
该部分知识设计信号与槽,可参看【Qt】信号与槽
接着就可以在代码编写界面实现具体的槽函数。widget.cpp代码如下:
#include "widget.h" #include "ui_widget.h" #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { qDebug() << "当前按钮可用";//pushButton的打印测试 } void Widget::on_pushButton_enabled_clicked() { bool enabled = ui->pushButton->isEnabled(); if(enabled) ui->pushButton->setEnabled(false);//设置不可用 else ui->pushButton->setEnabled(true);//设置可用 }
不可用的控件一般为灰色,按钮点击效果如下:
在Qt Designer中也可以通过右下方的控件属性改变控件的可用状态
二. geometry——几何位置
在Qt中,界面的分布使用左手坐标系,如图所示
描述一个控件所在界面位置,通过这四个属性——x,y,height,width
Qt将这四个属性封装在了QRect(矩阵)中
API | 说明 |
geometry() | 获取到控件的位置和尺寸.返回值是一个QRect |
setGeometry(QRect) | 设置控件的位置和尺寸,通过QRect设置 |
setGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸,通过四个属性分别设置 |
示例:通过四个按钮,控制一个按钮的上下左右移动
界面布局,即各按钮的objectName如下
控制移动的四个按钮都关联clicked信号,各自槽函数实现如下:
void Widget::on_pushButton_up_clicked() { QRect rect = ui->pushButton->geometry(); rect.setY(rect.y() - 5);//向上移动5个像素点 ui->pushButton->setGeometry(rect); } void Widget::on_pushButton_down_clicked() { QRect rect = ui->pushButton->geometry(); rect.setY(rect.y() + 5);//向下移动5个像素点 ui->pushButton->setGeometry(rect); } void Widget::on_pushButton_left_clicked() { QRect rect = ui->pushButton->geometry(); rect.setX(rect.x() - 5);//向左移动5个像素点 ui->pushButton->setGeometry(rect); } void Widget::on_pushButton_right_clicked() { QRect rect = ui->pushButton->geometry(); rect.setX(rect.x() + 5);//向右移动5个像素点 ui->pushButton->setGeometry(rect); }
实际程序运行效果如下:
实际程序运行发现,该方式设置的控件位置,不仅会改变控件对象的左上角位置,还可以改变控件的height和width。
如果要想实现控件对象的平移,相应槽函数可以如下编写
void Widget::on_pushButton_up_clicked() { QRect rect = ui->pushButton->geometry(); //向上移动5个像素点 // rect.setY(rect.y() - 5); // ui->pushButton->setGeometry(rect); ui->pushButton->setGeometry(rect.x(), rect.y() - 5, rect.width(),rect.height()); } void Widget::on_pushButton_down_clicked() { QRect rect = ui->pushButton->geometry(); //向下移动5个像素点 // rect.setY(rect.y() + 5); // ui->pushButton->setGeometry(rect); ui->pushButton->setGeometry(rect.x(), rect.y() + 5, rect.width(),rect.height()); } void Widget::on_pushButton_left_clicked() { QRect rect = ui->pushButton->geometry(); //向左移动5个像素点 // rect.setX(rect.x() - 5); // ui->pushButton->setGeometry(rect); ui->pushButton->setGeometry(rect.x() - 5, rect.y(), rect.width(),rect.height()); } void Widget::on_pushButton_right_clicked() { QRect rect = ui->pushButton->geometry(); //向右移动5个像素点 // rect.setX(rect.x() + 5); // ui->pushButton->setGeometry(rect); ui->pushButton->setGeometry(rect.x() + 5, rect.y(), rect.width(),rect.height()); }
程序运行效果如下:
window frame
实际上Qt的QWidget的位置信息,有两个参照物。我们在Qt Designer中操作的界面是不包含标题栏和边框的
边框和标题栏都是Qt帮我们自动生成的,这就是window frame,是操作系统提供的,有特定API,在Qt中,window frame是在QWidget的构造函数中创建的
所以相对位置就有两个参照物, 包含window frame的和不包含window frame的
上述的geometry()和setGeometry()就是不包含window framede的
包含window frame
API | 说明 |
frameGeometry() | 获取到控件的位置和尺寸.返回值是一个QRect,包含window frame |
setFrameGeometry(QRect) | 设置控件的位置和尺寸,通过QRect设置 |
setFrameGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸,通过四个属性分别设置 |
还有直接获取位置信息的方法,其返回值也是包含window frame的位置信息
ui->pushButton->x(); ui->pushButton->y(); ui->pushButton->width(); ui->pushButton->height();
而通过geometry返回的QRect获取的位置信息就不包含window frame的
ui->pushButton->geometry().x(); ui->pushButton->geometry().y(); ui->pushButton->geometry().width(); ui->pushButton->geometry().height();
三. windowTitle——窗口标题
windowTitle顾名思义,就是窗口的标题
API | 说明 |
setWindowTitle | 设置当前控件的窗口标题 |
注意:只有最外层的窗口设置窗口标题才会有效果,如果是窗口中一个按钮调用setWindowTitle方法,是没有任何效果的
四. windowIcon——窗口图标
窗口图标就是图形化程序左上角的图标,任务列表中也会显示窗口图标,例如:
API | 说明 |
windowIcon() | 获取控件的窗口图标,返回QIcon对象 |
setWindowIcoen(const QIcon& icon) | 设置控件的窗口图标 |
setWindowIcon和setWindowTitle一样,只对最外层/顶层的窗口有效
API | 说明 |
QIcon(const char*) | 将该路径的图片转为二进制,构造出QIcon对象 |
示例:
#include "widget.h" #include "ui_widget.h" #include <QIcon> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); QIcon icon(R"(C:\Users\Lenovo\Desktop\code\7.jpg)");//使用原始字符串字面量 this->setWindowIcon(icon); } Widget::~Widget() { delete ui; }
qrc文件
上述构造windowIcon使用的图片是绝对路径,这是不合理的
- 用户不一定有该路径,比如绝对路径是F:/image/1.jpg,但如果用户只有C盘和D盘,那该路径就不存在
- 如果该路径的图片丢失,则无法加载窗口图标
使用相对路径的方式,可以保证路径存在
假设基准目录是D:/,给定的相对路径是./image/1.jpg =》 在基准目录下找image目录,再在image目录中找1.jpg
. 表示当前目录 ..表示上级目录
对于Qt程序来说,当前工作可能是变化的。比如通过Qt Creator运行的程序,当前工作目录是项目的构建目录;直接双击.exe运行,工作目录则是exe所在目录
所谓构建目录,是和Qt项目并列的,专门用来放生成的临时文件和最终exe的目录
但相对路径的方式无法解决路径图片丢失的问题,Qt提供的解决方法是qrc文件
qrc文件是一种xml格式的资源配置文件,用xml(标签)记录硬盘上的文件和对于的随意指定的资源名称,应用程序通过资源名称来访问这些资源
在Qt开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源,这些资源文件可以位于qrc文件所在目录的同级或其子目录下
在构建程序的过程中,Qt会把资源文件的二进制数据转成cpp代码,编译到exe中,从而使依赖资源变得“路径无关”
使用qrc文件设置窗口图标
1. 点击文件,选择新建文件
2. 选择“文件和类”中的Qt
3. 选择Qt Resource File
4. 填写文件名,路径名 ,注意文件名和路径名都要包含中文和特殊符号
版本控制根据自己的项目,跟创建项目时选择一致即可
Qt Creator为我们提供了qrc文件的图形化开发界面
5. 在qrc编辑器中,添加前缀(prefix)
所谓的前缀,可以理解为“目录” . 该前缀决定了后续我们如何在代码中访问资源。
此处我添加了一个"/"前缀
6. 选择添加的图片——Add Files
Qt要求添加的文件必须是在qrc文件的同级目录,或者同级目录的子目录中,所以需要提前把图片复制到该目录下
如果选择其他目录下的图片,Qt不允许添加
如下是添加成功的效果,然后我们就可以在代码中使用该图片
#include "widget.h" #include "ui_widget.h" #include <QIcon> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); QIcon icon(":/7.jpg");//:开头表示从qrc中获取资源,/是我们设置的前缀,7.jpg是资源名 this->setWindowIcon(icon); } Widget::~Widget() { delete ui; }
运行程序后,在项目的构建目录下,我们可以看到目录多了一个qrc_XXX.cpp和qrc_XXX.o文件。这两个文件都是Qt的元编程生成的:Qt基于qrc文件生成C++代码(qrc_XXX.cpp),在程序编译时一同编译(qrc_XXX.o),最后链接生成.exe文件
其中,图片是被转换成了一个字符数组,内置在程序代码中
如此就既不需要关心图片资源的路径问题,也不需要关心图片丢失的问题
缺点:qrc文件是通过将图片资源转化为字符数组的形式存储在程序中,这势必会增加程序的大小,导致程序的编译,加载,运行更消耗资源。
五. windowOpacity——透明度
windowOpacity用于控制控件的透明度,其数值为0.0 ~ 1.0,数值越大越不透明。0.0表示全透明,1.0表示完全不透明
如此的数值含义,理解为不透明度更合适,数值越大越不透明
API | 说明 |
windowOpacity() | 返回float类型,控件的不透明度 |
setWindowOpacity(float n) | 设置控件的不透明度 |
示例:添加两个按钮,一个增大不透明度,一个减小不透明度
1. 使用Qt Designer添加按钮,设置objectName
2. 关联信号和槽
void Widget::on_pushButton_add_clicked() { //增加不透明度 float opacity = this->windowOpacity(); if(opacity >= 1.0) return; opacity += 0.1; this->setWindowOpacity(opacity); } void Widget::on_pushButton_sub_clicked() { //减小不透明度 float opacity = this->windowOpacity(); if(opacity <= 0.0) return; opacity -= 0.1; this->setWindowOpacity(opacity); }
3. 运行程序,点击“-”,降低不透明度
六. cursor——光标
在Qt中,我们可以通过设置鼠标移动到不同控件,显示不同光标来增加程序的丰富性和美观
API | 说明 |
cursor() | 获取当前控件的光标属性,返回QCursor对象 当鼠标悬停在该控件上,就会显示出对应形状 |
setCursor(const QCursor &cursor) | 设置该控件的光标,仅鼠标停留在该控件上生效 |
QGuiApplication::setOverrideCursor(const QCursor &cursor) | 设置全局光标的形状,整个程序的控件都会生效,覆盖各自控件setCursor设置的内容 |
图形化开发
直接通过属性的cursor选择
代码编写
Qt封装了一个枚举类,枚举了内置的光标类型
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); QCursor cursor(Qt::WaitCursor); ui->pushButton->setCursor(cursor); } Widget::~Widget() { delete ui; }
自定义光标
为了让程序更加美观,我们也可以自定义光标,将图标做成光标
图片导入项目的方法也是使用qrc文件的方式,此处不过多赘述
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); QPixmap pixmap(":/candy.png");//位图对象 pixmap = pixmap.scaled(40, 40);//对图片进行缩放——尺寸40 * 40像素 QCursor cursor(pixmap, 0, 0);//构造光标 ui->pushButton->setCursor(cursor);//设置光标 } Widget::~Widget() { delete ui; }
- QCursor构造函数的后两个参数是指明热点的位置,热点就是光标实际点击的点,此处设置的位置是相对光标的左上角的位置,(0, 0)就代表光标的最左上角
- QPixmap的scaled函数不是对原本图标的改变,是返回一个改变后的图标的副本
七. font——字体
Qt封装了QFont类,实现对控件中字体的管理,其属性包括字体家族,字体大小,字体粗细等等
属性 | 说明 |
family | 字体家族,如“楷体”,“宋体”,“微软雅黑”等 |
pointSize | 字体大小 |
weight | 字体粗细,以数值方式表示粗心程度取值范围[0,99],数值越大,字体越粗 |
bold | 是否加粗,bool值,设置true,相当于weight = 75,false相当于weight = 50 |
italic | 是否倾斜 |
underline | 是否有下划线 |
strikeOut | 是否带有删除线 |
相关API
API | 说明 |
font() | 获取当前控件的字体信息,返回QFont对象 |
setFont(const QFont &font) | 设置当前控件的字体信息 |
示例:
图形化开发
使用Qt Designer可以直接在属性处选择字体信息
代码编写
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); QFont font = ui->label->font();//获取字体信息 font.setBold(true);//加粗 font.setFamily("宋体");//设置字体家族 font.setPointSize(10);//设置大小 font.setItalic(true);//设置倾斜 ui->label->setFont(font); } Widget::~Widget() { delete ui; }
八. toolTip——提示栏
当用户将鼠标悬置在控件上方时,我们可以添加提示栏来告诉用户如何使用该控件或者显示一些信息。例如在编译器中,我们将鼠标悬停在一个方法上,编译器就会弹出一个窗口显示其方法声明,这就是提示栏
相关API
API | 说明 |
toolTip() | 返回提示栏的文本,返回值为QString |
setToolTip(const QString &string) | 设置提示栏文本 |
toolTipDuration() | 返回提示栏持续时间,int类型,单位为毫秒 |
setToolTipDuration(const int msec) | 试着提示栏持续时间,单位为毫秒。传-1代表提示栏不消失 |
示例:
图形化开发
可直接设置toolTip文本和toolTipDuration持续时间
代码编写
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); ui->pushButton_yes->setToolTip("Yes按钮"); ui->pushButton_yes->setToolTipDuration(-1); ui->pushButton_no->setToolTip("No按钮"); ui->pushButton_no->setToolTipDuration(4000); } Widget::~Widget() { delete ui; }
九. focusPolicy——焦点策略(选中策略)
所谓“焦点”,指的是能选中这个元素的方法,比如键盘操作。
“”焦点“”对于输入框、单选框、复选框等控件很重要
常见的焦点策略(选中策略)有点击和Tab
相关API
API | 说明 |
focusPolicy() | 获取该控件的focusPolicy,返回值类型为Qt::FocusPolicy |
setFocusPolicy(const Qt::FocusPolicy) | 设置该控件的focusPolicy |
Qt::FocusPolicy是Qt内置的一个枚举类,取值如下:
- Qt::NoFocus:该控件不会接受键盘焦点,不可被选中
- Qt::TabFocus:该控件可通过Tab键接受焦点,可通过Tab选中
- Qt::ClickFocus:该控件可通过鼠标点击接受焦点,看通过点击选中
- Qt::StrongFocus:该控件可通过Tab键和点击选中
- Qt::WheelFocus:该控件可通过Tab键,点击,鼠标滚轮选中
示例:
图形化开发
代码编写
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); ui->lineEdit->setFocusPolicy(Qt::StrongFocus); } Widget::~Widget() { delete ui; }
十. styleSheet——样式表
Qt可以通过CSS设置widget样式
CSS(Cascading Style Sheets 层叠样式表) 是网页前端技术,主要就是用来描述界面的样式
所谓“样式”,包括但不限于大小、位置、颜色、间距、字体、背景、边框等
CSS中可以设置的样式属性非常多,基于这些属性,Qt可以支持其中一部分,称为QSS(Qt Style Sheets)。具体的支持情况可以参看Qt文档中"Qt Style Sheets Reference"章节
示例:设置文本样式
图形化开发
(1). 在Qt Designer添加一个Label标签,右键,选择“改变样式表”,使用CSS设置样式
语法同CSS,使用键值对的方式设置样式,其中键和值之间使用 :分隔。键值对之间使用;分隔
Qt Designer只能对样式的基本格式进行校验,不能检测出哪些样式不被Qt支持
比如text-align:center,这样的文本居中操作,就无法支持
代码实现
API | 说明 |
styleSheet() | 返回该控件的样式表,返回值为QString |
setStyleSheet(const QString &styleSheet) | 设置样式表,使用QSS风格字符串 |
ui->label->setStyleSheet("font-family:微软雅黑; font-size:30px; ");