“ 别告诉孩子,我是危险的魔鬼~ ”
如何理解控件?
控件是GUI(图形用户界面)的通用概念,不止出现在QT中。当完全没有控件时,需要通过⼀些绘图 API ⼿动的绘制出按钮或者输⼊框等内容, 代码编写繁琐。
—— 前言
QWidget(QT核心控件)
(1) QWidget简介
在QT中,使⽤ QWidget 类表⽰ "控件"。按钮, 视图, 输⼊框, 滚动条等具体的控件类, 都是继承⾃QWidget。
如下图中,QPushButton类默认继承自QWidget:
我们打开Qt Creator自带的Qt Designer,会展示整个QT Widget属性:
当我们可以试着拖动PushButton按钮到该界面中,会自动生成该类属性的界面:
由此,我们可以直接通过QtDesigner 会直接修改, 也可以通过代码的⽅式修改。
(2) QWidget核⼼属性概览
下列表格列出了 QWidget 中部分属性及其作⽤.
属性 | 作用 |
enabled | 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ |
geometry | 位置和尺⼨. 包含 x, y, width, height 四个部分 |
windowTitle | 设置 widget 标题 |
windowIcon | 设置 widget 图标 |
windowOpacity | 设置 widget 透明度 |
font | 字体相关属性 |
…… | …… |
🎈 enabled
API | 说明 |
isEnabled() | 获取到控件的可⽤状态 |
setEnabled | 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ |
注:禁用意味着该控件不能接收任何⽤⼾的输⼊事件, 并且外观上往往是灰⾊的.
如果⼀个 widget 被禁⽤, 则该 widget 的⼦元素也被禁⽤.
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* btn = new QPushButton(this);btn->setText("这是一个受到禁用的按钮~");btn->setEnabled(false);
}
我们可以设计一个场景 —— 通过切换按钮,对button1的禁用、使用状态进行切换~
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
private:Ui::Widget *ui;QPushButton* mybutton;QPushButton* button1;
public slots:// 槽函数void exchange_button_status();
}void Widget::exchange_button_status()
{bool flag = button1->isEnabled();button1->setEnabled(!flag);
}Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{// ...// 槽函数 exchange_button_status() 与 信号函数 QPushButton::clicked关联connect(mybutton,&QPushButton::clicked,this,&Widget::exchange_button_status); // ...
}
点击按钮前:
点击切换后:
🎈 Geometry
位置和尺⼨. 其实是四个属性的统称:
• x 横坐标• y 纵坐标• width 宽度• height ⾼度
API | 说明 |
geometry() | 获取到控件的位置和尺⼨ 返回结果为一个QRect |
setGeometry(QRect) | 直接设置⼀个 QRect |
setGeometry(int x, int y, int width, int height) | 四个属性单独设置. |
例如,我们可以写一个场景,控制一个物体的上下左右:
经历一系列的小动作后 ~
🎈 Windows Frame
x(), y(), frameGeometry(), pos(), move() 都是按照包含 window frame ⽅式来计算。
包含 Windows frame | 不包含 |
x() 获取横坐标 | width() 获取宽度 |
y() 获取纵坐标 | height() 获取⾼度 |
pos() 返回 QPoint 对象, | size() 返回 QSize 对象 |
frameSize() 返回 QSize 对象 | rect() 返回 QRect 对象 |
frameGeometry() 返回 QRect 对象 | geometry() 返回 QRect 对象 |
setGeometry() 直接设置窗⼝的位置和尺⼨ 不包含 window frame 对象 |
以代码的方式,感受geometry 与 frameGeometry的区别:
QRect rect1 = this->geometry();QRect rect2 = this->frameGeometry();qDebug() << "geometry(): " << rect1;qDebug() << "frameGeometry(): " << rect2;
在构造⽅法中, Widget 刚刚创建出来, 还没有加⼊到对象树中. 此时也就不具备 Window
frame.在按钮的 slot 函数中, 由于⽤⼾点击的时候, 对象树已经构造好了, 此时 Widget 已经具备了 Window frame, 因此在位置和尺⼨上均出现了差异.
所以,对于PushButton而言,geometry 与 frameGeometry就没有任何区别了 ...
🎈 windowTitle
API | 说明 |
windowTitle() | 获取到控件的窗⼝标题 |
setWindowTitle(const QString& title) | 设置控件的窗⼝标题. |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("这是一个Widget标题");
}
🎈 windowIcon
API | 说明 |
windowIcon() | 获取到控件的窗⼝图标. 返回 QIcon 对象 |
setWindowIcon(const QIcon& icon) | 设置控件的窗⼝图标 |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("这是一个Widget标题");QIcon icon = QIcon("d:/rose.jpg");this->setWindowIcon(icon);
}
🎈 windowOpacity
API | 说明 |
windowOpacity() | 获取到控件的不透明数值. 返回 float, 取值为 0.0 -> 1.0 其中 0.0 表⽰全透明, 1.0 表⽰完全不透明 |
setWindowOpacity(float n) |
void Widget::on_pushButton_clicked()
{float opacity = this->windowOpacity();if(opacity >= 1.0){return;}qDebug() << opacity;opacity += 0.1;this->setWindowOpacity(opacity);
}void Widget::on_pushButton_2_clicked()
{float opacity = this->windowOpacity();if(opacity <= 1.0){return;}qDebug() << opacity;opacity -= 0.1;this->setWindowOpacity(opacity);
}
由此,我们可以控制Widget中的不透明度~
🎈 cursor
API | 说明 |
cursor() | 获取到当前 widget 的 cursor 属性, 返回 QCursor 对象. |
setCursor(const QCursor& cursor) | 设置该 widget 光标的形状 |
QGuiApplication::setOverrideCursor(co nst QCursor& cursor ) | 设置全局光标的形状 |
QPixmap pixmap("d:/huaji.png");pixmap = pixmap.scaled(64, 64);QCursor cursor(pixmap, 2, 2);ui->pushButton_3->setCursor(cursor);
想要什么效果,通过ui设置十分便利.
但,也许默认提供的图标不能满足你的需求,所以也可以进行自定义cursor
🎈 font
API | 说明 |
font() | 获取当前 widget 的字体信息. 返回 QFont 对象 |
setFont(const QFont& font) | 设置当前 widget 的字体信息 |
关于 QFont
属性 | 说明 |
family | 字体家族. ⽐如 "楷体", "宋体", "微软雅⿊" 等 |
pointSize | 字体⼤⼩ |
weight | 字体粗细 |
bold | 是否加粗 |
italic | 是否倾斜 |
underline | 是否带有下划线 |
strikeOut | 是否带有删除线 |
ui->label->setText("这是⼀段⽂本");QFont font; font.setFamily("仿宋");font.setPointSize(20);font.setBold(true);font.setStrikeOut(true);// 设置文本ui->label->setFont(font);
🎈 toolTip
API | 说明 |
setToolTip | 设置 toolTip. |
setToolTipDuring | 设置 toolTip 提⽰的时间. |
理解为,说明解释按钮 ~
我们同样可以为其设置延迟时间
ui->pushButton_4->setToolTipDuration(200);
🎈 focusPolicy
设置控件获取到焦点的策略. ⽐如某个控件能否⽤⿏标选中或者能否通过 tab 键选中。这种特别类似于,游戏里“选中”的特点。
API | 说明 |
focusPolicy() | 获取该 widget 的 focusPolicy, 返回 Qt::FocusPolicy |
setFocusPolicy(Qt::FocusPolicy policy) | 设置 widget 的 focusPolicy |
通过设置选中策略,可以通过不同的方式对目标框进行访问~
🎈 styleSheet
通过 CSS 设置 widget 的样式
另外, Qt Designer 只能对样式的基本格式进⾏校验, 不能检测出哪些样式不被 Qt ⽀持。
当然,以上并非Qwidget的全部内容,但也涉猎其中不少。
附
在上面一动方块那栏中,可能存在几个需要优化的小地方 ...
🎨 一直通过点击鼠标,让该Object进行移动是在太累了,能不能使键盘关联其槽函数??
🎨 英文太low了,能不能做出好看的icon??
什么是qrc
当我们想要在程序中引入本地磁盘上准备妥当的图像时,唔我们大概会在程序中这样编写
// 图片路径
QIcon icon = QIcon("C:\\Users\\WGZZS7\\Desktop\\qt\\code\\new\\huahua.jpg");
QPushButton* btn = new QPushButton(this);
// 将图片替换进 Button中
btn->setIcon(icon);
// Q_DECL_CONSTEXPR QSize(int w, int h) noexcept;
btn->setIconSize(QSize(500,500));
我们如愿能得到一张十分帅气的图片。
但,如果此时你一旦将图片移除该目录或者该项目的整个路径转移到了其他路径下。
你就会得到一个空白 ....
导致这个问题的根本原因还是在于,我们在加载图片时,使用到的是 "绝对路径" !当产品被发布,会被不同的用户安装在不同的路径下,也许在你的测试下,通过绝对路径能够找到对应的资源,但对于用户而言这是存在风险的。这迫使我们在设置路径时, 需要保证其相对性 —— 相对路径
给QT项目引入一个额外的xml文件,并以.qrc作为后缀标识。我们通过将资源导入到该文件中,从而形成数据资源在xml中进行记录。QT在编译项目时,就会根据qrc描述的图片信息,提取这些数据信息,最终编译进你的代码中。
所以,提出qrc机制需要从解决上述两个问题:
🎆 确保该图片所在路径是在机器上存在的.
🎆 图片不会被用户搞没了.
可是,用户的使用情况你完完全全是不知情的,你无法保证用户不会误操作将你辛辛苦苦整合的资源弄丢。
非中文名的.qrc文件名称.
完成创建.
"prefix1" 可以理解为QT创建的一个虚拟目录,便于QT更容易找到你的图片文件。因为本文件就在当前项目目录,所以改为 " / " 即可.
当prefix前缀完成后,就可以添加文件了,添加好的新文件就是在这个prefix之下。
注:文件导入时,确保与.qrc文件处于同目录或同级目录的子目录下
// 本质: :prefix/icon.jpg
QIcon icon = QIcon(":/huahua.jpg");
对其进行编译后,我们会找到这两个由QT生成的C++代码.
快捷键与连发
我们通常可以使用setAutoRepeat() 、setShortcut() 实现对快捷键绑定与连发
// 设置连发ui->up->setAutoRepeat(true);ui->down->setAutoRepeat(true);ui->left->setAutoRepeat(true);ui->right->setAutoRepeat(true);// 设置快捷键ui->up->setShortcut(Qt::Key_W);ui->down->setShortcut(Qt::Key_S);ui->left->setShortcut(Qt::Key_A);ui->right->setShortcut(Qt::Key_D);
通过"wsad" 完成对图像的控制.
本篇到此结束,感谢你的阅读。
祝你好运,向阳而生~