第一节 常用控件
1. QWidget 核心属性
1.1 objectName

1.2 enabled
| API | 说明 |
| isEnabled() | 获取到控件的可⽤状态 |
| setEnabled() | 设置控件是否可使⽤. true 表⽰可⽤, false 表⽰禁⽤ |

1.3 geometry && window frame
geometry: x y width height
| API | 说明 |
| geometry() | 获取到控件的位置和尺⼨. 返回结果是⼀个 QRect, 包含了 x, y, width, height. 其 中 x, y 是左上⻆的坐标 |
| setGeometry(QRect) setGeometry(int x, int y, int width, int height) | 设置控件的位置和尺⼨. 可以直接设置⼀个 QRect, 也可以分四个属性单独设置. |


- 注意: setGeometry(QRect),使用这个函数可能会改变原来的控件的width 和 height
| API | 说明(以下API: 计算时包含 window frame) |
| x() | 获取横坐标 |
| y() | 获取纵坐标 |
| pos() | 返回 QPoint 对象, ⾥⾯包含 x(), y(), setX(), setY() 等⽅法. |
| frameSize() | 返回 QSize 对象, ⾥⾯包含 width(), height(), setWidth(), setHeight() 等⽅法. |
| frameGeometry() | 返回 QRect 对象. QRect 相当于 QPoint 和 QSize 的结合体. 可以获取 x, y, width, size. |
| API | 说明(以下API: 计算时不包含 window frame) |
| width() | 获取宽度 |
| height() | 获取⾼度 |
| size() | 返回 QSize 对象, ⾥⾯包含 width(), height(), setWidth(), setHeight() 等⽅法. |
| rect() | 返回 QRect 对象. QRect 相当于 QPoint 和 QSize 的结合体. 可以获取并设置 x, y, width, size. |
| geometry() | 返回 QRect 对象. QRect 相当于 QPoint 和 QSize 的结合体. 可以获取 x, y, width, size |
| setGeometry() | 直接设置窗⼝的位置和尺⼨. 可以设置 x, y, width, height, 或者 QRect 对象 |


1.4 windowTitie
| API | 说明 |
| windowTitle() | 获取到控件的窗⼝标题. |
| setWindowTitle(const QString& title) | 设置控件的窗⼝标题 |

1.5 windowlcon
| API | 说明 |
| windowIcon() | 获取到控件的窗⼝图标. 返回 QIcon 对象 |
| setWindowIcon(const QIcon& icon) | 设置控件的窗⼝图标 |
通过 qrc 管理图⽚作为图标
给Qt项目引入一个额外的xml文件(后缀名使用.qrc表示),在这个xml中把要使用的图片资源给导入进来,并且在xml中记录
Qt在编译项目的时候,就会根据qrc中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转换成C++代码,最终编译到exe里
新建qrc文件

-
注意: 添加的⽂件必须是在 qrc ⽂件的同级⽬录, 或者同级⽬录的⼦⽬录中.

- 在引入了qrc机制之后,就可以直接用相对路径访问的这个图片
- qrc机制主要解决2个问题:
问题一:确保图片所在的路径在目标用户机器上存在
问题二:确保图片不会被用户搞没了
1.6 windowOpacity
| API | 说明 |
| windowOpacity() | 获取到控件的不透明数值. 返回 float, 取值为 0.0 -> 1.0 |
| setWindowOpacity(float n) | 设置控件的不透明数值. |


- 注意: 窗口的不透明度,变化并非是精确的,这主要和浮点数在内存中的存储有关
1.7 cursor
| API | 说明 |
| cursor() | 获取到当前 widget 的 cursor 属性, 返回 QCursor 对象. 当⿏标悬停在该 widget 上时, 就会显⽰出对应的形状 |
| setCursor(const QCursor& cursor) | 设置该 widget 光标的形状. 仅在⿏标停留在该 widget 上时⽣效. |
| QGuiApplication::setOverrideCursor(co nst QCursor& cursor) | 设置全局光标的形状. 对整个程序中的所有 widget 都会⽣效. 覆盖 上⾯的 setCursor 设置的内容. |
- QPixmap是一个位图对象
1.8 font
| API | 说明 |
| font() | 获取当前 widget 的字体信息. 返回 QFont 对象 |
| setFont(const QFont& font) | 设置当前 widget 的字体信息 |
关于 QFont
| 属性 | 说明 |
| family | 字体家族. ⽐如 "楷体", "宋体", "微软雅⿊" 等. |
| pointSize | 字体⼤⼩ |
| weight | 字体粗细. 以数值⽅式表⽰粗细程度取值范围为 [0, 99], 数值越⼤, 越 粗 |
| bold | 是否加粗. 设置为 true, 相当于 weight 为 75. 设置为 false 相当于 weight 为 50 |
| italic | 是否倾斜 |
| underline | 是否带有下划线 |
| strikeOut | 是否带有删除线 |

- 也可以使用ui界面直接修改

1.9 tooltip(解释说明的意思)
就是鼠标悬停时出现的一个提示信息
| API | 说明 |
| setToolTip | 设置 toolTip. ⿏标悬停在该 widget 上时会有提⽰说明. |
| setToolTipDuring | 设置 toolTip 提⽰的时间. 单位 ms. 时间到后 toolTip ⾃动消失 |

1.10 focusPolicy(设置控件获取到焦点)
设置控件获取到焦点的策略. ⽐如某个
控件能否⽤⿏标选中或者能否通过 tab 键选中.
| API | 说明 |
| focusPolicy() | 获取该 widget 的 focusPolicy, 返回 Qt::FocusPolicy |
| setFocusPolicy(Qt::FocusPolicy policy) | 设置 widget 的 focusPolicy. |

- Qt::NoFocus :控件不会接收键盘焦点
- Qt::TabFocus :控件可以通过Tab键接收焦点
- Qt::ClickFocus :控件在⿏标点击时接收焦点
- Qt::StrongFocus :控件可以通过Tab键和⿏标点击接收焦点 (默认值)
-
Qt::WheelFocus : 类似于 Qt::StrongFocus , 同时控件也通过⿏标滚轮获取到焦点 (新增
的选项, ⼀般很少使⽤)

- 在ui界面上也可以直接更改
1.11 styleSheet
通过 CSS 设置 Qwidget 的样式

- 也可以在ui界面上右键,然后再添加编辑样式表,

- 注意:这里的css样式别写错了,如果写错了Qt是不会报错的
2 按钮类
2.1 Pushbutton(普通按钮)
| API | 说明 |
| text | 按钮中的⽂本 |
| icon | 按钮中的图标 |
| iconSize | 按钮中图标的尺⼨ |
| shortCut | 按钮对应的快捷键 |
| autoRepeat | 按钮是否会重复触发. 当⿏标左键按住不放时, 如果设为 true, 则会持续产⽣⿏标点击事件; 如果设为 false, 则必须释放⿏标, 再次按下⿏标时才能产⽣点击事件. (相当于游戏⼿柄上的 "连发" 效果) |
| autoRepeatDelay | 重复触发的延时时间. 按住按钮多久之后, 开始重复触发. |
| autoRepeatInterval | 重复触发的周期. |
说明一下:
- QAbstractButton 作为 QWidget 的⼦类, 当然也继承了 QWidget 的属性. 上⾯
介绍的 QWidget ⾥的各种属性⽤法, 对于 QAbstractButton 同样适⽤

2.2 Radio Buttion(单选)
| API | 说明 |
| checkable | 是否能选中 |
| checked | 是否已经被选中. checkable 是 checked 的前提条件 |
| autoExclusive | 是否排他. 选中⼀个按钮之后是否会取消其他按钮的选中. 对于 QRadioButton 来说默认就是排他的 |

2.3 QButtonGroup(按钮组)

- QButtonGroup表示: 每⼀组内部来控制排他, 但是组和组之间不能排他
2.4 Check Box(多选)
2.5 Tool Button(工具按钮)
QToolButton 的⼤部分功能, 和 QPushButton 是⼀致的. 但是 QToolButton 主要应⽤在⼯
具栏, 菜单等场景.


3 显示类
3.1 Lable(普通文本框)
| 属性 | 说明 |
| text | QLabel 中的⽂本 |
| textFormat | Qt::PlainText 纯⽂本 Qt::MarkdownText markdown 格式 Qt::AutoText 根据⽂本内容⾃动决定⽂本格式 |
| pixmap | QLabel 内部包含的图⽚ |
| scaledContents | 设为 true 表⽰内容⾃动拉伸填充 QLabel 设为 false 则不会⾃动拉伸 |
| alignment | 对⻬⽅式. 可以设置⽔平和垂直⽅向如何对⻬ |
| wordWrap | 设为 true 内部的⽂本会⾃动换⾏. 设为 false 则内部⽂本不会⾃动换⾏. |
| indent | 设置⽂本缩进. ⽔平和垂直⽅向都⽣效 |
| margin | 内部⽂本和边框之间的边距. 不同于于 indent, 它是上下左右四个⽅向都同时有效. ⽽ indent 最多只是两个⽅向有效(具体哪两个⽅向有效取决于 alignment ) |
| openExternalLinks | 是否允许打开⼀个外部的链接. (当 QLabel ⽂本内容包含 url 的时候涉及到) |
| buddy | 给 QLabel 关联⼀个 "伙伴" , 这样点击 QLabel 时就能激活对应的伙伴. 例如伙伴如果是⼀个 QCheckBox, 那么该 QCheckBox 就会被选中 |


-
虽然 QPushButton 也可以通过设置图标的⽅式设置图⽚, 但是并⾮是⼀个好的选择. 更多的时候还是希望通过 QLabel 来作为⼀个更单纯的显⽰图⽚的⽅式.
上述的案例存在一个问题,用户在拉伸窗口时,图片的size并没有随之改变,我们需要引入事件来解决
Qt中,表示用户的操作,有两类概念:一个是信号,另一个是事件~~


- 当用户拖拽窗口大小的时候,就会触发resize事件(resizeEvent)
- 像resize这样的事件,是连续变化的,把窗口尺寸从A拖到B这个过程中,就会触发一系列的resizeEvent,然后就可以借助resizeEvent来完成上述的功能

- 此处设置的缩进,即使文本换行了后续的行也会产生缩进,不仅仅是首行缩进

- 在QT中,QLabel中写的文本,是可以指定"快捷键",但这里的快捷键的规则功能上,要比QPushButton要弱一点
- 它表示快捷键的操作是 & 跟上一个字符来表示快捷键
比如: &A => 通过键盘上的alt+a来触发 - 而绑定了伙伴关系之后,通过快捷键就可以选中对应的单选按钮/复选按钮
3.2 LCD Number(LCD电子数字)
QLCDNumer 是⼀个专⻔⽤来显⽰数字的控件. 类似于 "⽼式计算器" 的效果.
| 属性 | 说明 |
| intValue | QLCDNumber 显⽰的数字值(int). |
| value | QLCDNumber 显⽰的数字值(double). 和intValue 是联动的. 例如给 value 设为 1.5, intValue 的值就是 2. 另外,设置 value 和 intValue 的⽅法名字为 display , ⽽不是 setValue 或 者 setIntValue |
| digitCount | 显⽰⼏位数字. |
| mode | 数字显⽰形式. 1. QLCDNumber::Dec :⼗进制模式,显⽰常规的⼗进制数字。 2. QLCDNumber::Hex :⼗六进制模式,以⼗六进制格式显⽰数字。 3. QLCDNumber::Bin :⼆进制模式,以⼆进制格式显⽰数字。 4. QLCDNumber::Oct :⼋进制模式,以⼋进制格式显⽰数字 只有⼗进制的时候才能显⽰⼩数点后的内容 |
| segmentStyle | 设置显⽰⻛格. 1. QLCDNumber::Flat :平⾯的显⽰⻛格,数字呈现在⼀个平坦的表⾯上。 2. QLCDNumber::Outline :轮廓显⽰⻛格,数字具有清晰的轮廓和阴影效果。 3. QLCDNumber::Filled :填充显⽰⻛格,数字被填充颜⾊并与背景区分开 |
| smallDecimalPoin | 设置⽐较⼩的 ⼩数点. |

关于定时器
- 在C++标准库中,没有提供定时器的实现,但Boost里面提供了对应的功能
- 而在Qt中也封装了对应的定时器~~(结合了信号槽机制)
- 通过QTimer这个类创建处理的对象,就会产生一个timeout这样的信号
- 再结合connect,把这个timeout信号绑定到需要的槽函数中,就可以执行周期性的修改LCDNumber中的数字
不允许在新线程中修改界面的值

- 在Qt里面,界面中有一个专门的线程去负责维护更新(主线程->main函数所在的线程)
- 而对于GUI来说,内部包含了很多的隐藏状态,Qt为了保证修改界面的过程中,线程安全是不会受影响的,所以Qt就禁止了其他线程直接修改界面
ui->lcdNumer->display(value),形如这种操作,就是在修改界面 - 对于Qt的槽函数来说,默认情况下,槽函数都是由主线程调用的,在槽函数中修改界面是没有任何问题的
但要是自己创建了一个新线程,再修改界面就会出错,程序就会异常退出
3.3 ProgressBar(进度条)
| 属性 | 说明 |
| minimum | 进度条最⼩值 |
| maximum | 进度条最⼤值 |
| value | 进度条当前值 |
| alignment | ⽂本在进度条中的对⻬⽅式 Qt::AlignLeft : 左对⻬ Qt::AlignRight : 右对⻬ Qt::AlignCenter : 居中对⻬ Qt::AlignJustify : 两端对⻬ |
| textVisible | 进度条的数字是否可⻅. |
| orientation | 进度条的⽅向是⽔平还是垂直 |
| invertAppearance | 是否是朝反⽅向增⻓进度 |
| textDirection | ⽂本的朝向 |
| format | 展⽰的数字格式. %p :表⽰进度的百分⽐(0-100) %v :表⽰进度的数值(0-100) %m :表⽰剩余时间(以毫秒为单位) %t :表⽰总时间(以毫秒为单位) |

- 进度条的更新也是需要搭配定时器来完成的
3.4 Calendar Widget(日历)
| 属性 | 说明 |
| selectDate | 当前选中的⽇期 |
| minimumDate | 最⼩⽇期 |
| maximumDate | 最⼤⽇期 |
| firstDayOfWeek | 每周的第⼀天(也就是⽇历的第⼀列) 是周⼏ |
| gridVisible | 是否显⽰表格的边框 |
| selectionMode | 是否允许选择⽇期 |
| navigationBarVisible | ⽇历上⽅标题是否显⽰ |
| horizontalHeaderFormat | ⽇历上⽅标题显⽰的⽇期格式 |
| verticalHeaderFormat | ⽇历第⼀列显⽰的内容格式 |
| dateEditEnabled | 是否允许⽇期被编辑 |
重要信号
| 信号 | 说明 |
| selectionChanged(const QDate&) | 当选中的⽇期发⽣改变时发出 |
| activated(const QDate&) | 当双击⼀个有效的⽇期或者按下回⻋键时发出, |
| currentPageChanged(int, int) | 当年份⽉份改变时发出,形参表⽰改变后的新年份和⽉份 |

4. 输入类控件
4.1 Line Edit(单行输入框)
| 属性 | 说明 |
| text | 输⼊框中的⽂本 |
| inputMask | 输⼊内容格式约束 |
| maxLength | 最⼤⻓度 |
| frame | 是否添加边框 |
| echoMode | 显⽰⽅式. • QLineEdit::Normal :这是默认值,⽂本框会显⽰输⼊的⽂本。 • QLineEdit::Password :在这种模式下,输⼊的字符会被隐藏, 通常⽤星号(*)或等号(=)代替。 • QLineEdit::NoEcho :在这种模式下,⽂本框不会显⽰任何输⼊ 的字符 |
| cursorPosition | 光标所在位置 |
| alignment | ⽂字对⻬⽅式, 设置⽔平和垂直⽅向的对⻬ |
| dragEnabled | 是否允许拖拽 |
| readOnly | 是否是只读的(不允许修改) |
| placeHolderText | 当输⼊框内容为空的时候, 显⽰什么样的提⽰信息 |
| clearButtonEnabled | 是否会⾃动显⽰出 "清除按钮" |
核⼼信号
| 属性 | 说明 |
| void cursorPositionChanged(int old, int new) | 当⿏标移动时发出此信号,old为先前的位置,new为新位置 |
| void editingFinished() | 当按返回或者回⻋键时,或者⾏编辑失去焦点时,发出此信号 |
| void returnPressed() | 当返回或回⻋键按下时发出此信号. 如果设置了验证器, 必须要验证通过, 才能触发 |
| void selectionChanged() | 当选中的⽂本改变时,发出此信号 |
| void textChanged(const QString &text) | 当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改能够触发这个信号 |
| void textEdited(const QString &text)) | 当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改不能触发这个信号. |

-
inputMask 只能进⾏简单的输⼊格式校验.
实际开发中, 基于正则表达式的⽅式是更核⼼的⽅法
使⽤正则表达式验证输⼊框的数据
要求在输⼊框中输⼊⼀个合法的电话号码(1 开头, 11 位, 全都是数字). 如果验证不通过, 则确定按钮⽆法点击


说明一下:
- 这里说明一下state validator(QString&,int &)函数的2个参数,
- 第一个参数是要验证的字符串,参数类型是QString & 不是const QString&,所以这里我创建了一个临时对象
- 第二个参数表示,如果这个字符串不符合规则,是从那个位置开始的
4.2 Text Edit(多行输入框)
QTextEdit 表⽰多⾏输⼊框. 也是⼀个富⽂本 & markdown 编辑器. 并且能在内容超出编辑框范围时⾃动提供滚动条
| 属性 | 说明 |
| markdown | 输⼊框内持有的内容. ⽀持 markdown 格式. 能够⾃动的对markdown ⽂本进⾏ 渲染成 html |
| html | 输⼊框内持有的内容. 可以⽀持⼤部分 html 标签. 包括 img 和 table 等 |
| placeHolderText | 输⼊框为空时提⽰的内容. |
| readOnly | 是否是只读 |
| undoRedoEnable | 是否开启 undo / redo 功能. 按下 ctrl + z 触发 undo 按下 ctrl + y 触发 redo |
| autoFormating | 开启⾃动格式化. |
| tabstopWidth | 按下缩进占多少空间 |
| overwriteMode | 是否开启覆盖写模式 |
| acceptRichText | 是否接收富⽂本内容 |
| verticalScrollBarPolicy | 垂直⽅向滚动条的出现策略 Qt::ScrollBarAsNeeded : 根据内容⾃动决定是否需要滚动条。这是默认值。 Qt::ScrollBarAlwaysOff : 总是关闭滚动条。 Qt::ScrollBarAlwaysOn : 总是显⽰滚动条。 |
| horizontalScrollBarPolicy | ⽔平⽅向滚动条的出现策略 Qt::ScrollBarAsNeeded : 根据内容⾃动决定是否需要滚动条。这是默认值。 Qt::ScrollBarAlwaysOff : 总是关闭滚动条。 Qt::ScrollBarAlwaysOn : 总是显⽰滚动条 |
核心信号
| 核心属性 | 说明 |
| textChanged() | ⽂本内容改变时触发 |
| selectionChanged() | 选中范围改变时触发 |
| cursorPositionChanged() | 光标移动时触发 |
| undoAvailable(bool) | 可以进⾏ undo 操作时触发 |
| redoAvailable(bool) | 可以进⾏ redo 操作时触发 |
| copyAvaiable(bool) | ⽂本被选中/取消选中时触发 |

4.3 Combo Box(下拉选择框)
| 属性 | 说明 |
| currentText | 当前选中的⽂本 |
| currentIndex | 当前选中的条⽬下标 |
| editable | 是否允许修改 设为 true 时, QComboBox 的⾏为就⾮常接近 QLineEdit , 也可以设置 validator |
| iconSize | 下拉框图标 (⼩三⻆) 的⼤⼩ |
| maxCount | 最多允许有多少个条⽬ |
核⼼⽅法
| ⽅法 | 说明 |
| addItem(const QString&) | 添加⼀个条⽬ |
| currentIndex() | 获取当前条⽬的下标 从 0 开始计算. 如果当前没有条⽬被选中, 值为 -1 |
| currentText() | 获取当前条⽬的⽂本内容 |
核⼼信号
| 方法 | 说明 |
| activated(int) activated(const QString & text) | 当⽤⼾选择了⼀个选项时发出. 这个时候相当于⽤⼾点开下拉框, 并且⿏标划过某个选项. 此时还没有确认做出选择 |
| currentIndexChanged(int) currentIndexChanged(const QString & text) | 当前选项改变时发出. 此时⽤⼾已经明确的选择了⼀个选项. ⽤⼾操作或者通过程序操作都会触发这个信号 |
| editTextChanged(const QString & text) | 当编辑框中的⽂本改变时发出 (editable 为 true 时有效) |

说明一下:
- 下拉框里的条目,一般都是从网络/文件中读取的
- QString::fromStdString(s);// 把std::string 转换成QString
- s.toStdString();//把QString转换成std::string
4.4 Spin Box(微调框)
| 属性 | 说明 |
| value | 存储的数值 |
| singleStep | 每次调整的 "步⻓". 按下⼀次按钮数据变化多少 |
| displayInteger | 数字的进制. 例如 displayInteger 设为 10, 则是按照 10 进制表⽰. 设为 2 则为 2 进制表⽰ |
| minimum | 最⼩值 |
| maximum | 最⼤值 |
| suffix | 后缀 |
| prefix | 前缀 |
| wrapping | 是否允许换⾏ |
| frame | 是否带边框 |
| alignment | ⽂字对⻬⽅式. |
| readOnly | 是否允许修改 |
| buttonSymbol | 按钮上的图标. UpDownArrows 上下箭头形式 PlusMinus 加减号形式 NoButtons 没有按钮 |
| accelerated (加速的) | 按下按钮时是否为快速调整模式 |
| correctionMode | 输⼊有误时如何修正. QAbstractSpinBox::CorrectToPreviousValue : 如果⽤⼾输⼊了⼀个⽆效的值(例如,在只能显⽰正整数的SpinBox中输⼊了负数),那么SpinBox会恢复为上⼀个有效值。例如,如果SpinBox的初始值是1,⽤⼾ 输⼊了-1(⽆效),然后SpinBox会恢复为1。 QAbstractSpinBox::CorrectToNearestValue : 如果⽤⼾输⼊了⼀个 ⽆效的值,SpinBox会恢复为最接近的有效值。例如,如果SpinBox的初始值是1,⽤⼾输⼊了-1(⽆效),那么SpinBox会恢复为0 |
| keyboardTrack | 是否开启键盘跟踪. 设为 true, 每次在输⼊框输⼊⼀个数字, 都会触发⼀次 valueChanged() 和 textChanged() 信号. 设为 false, 只有在最终按下 enter 或者输⼊框失去焦点, 才会触发 valueChanged() 和 textChanged() 信号. |
核⼼信号
| 信号 | 说明 |
| textChanged(QString) | 微调框的⽂本发⽣改变时会触发. 参数 QString 带有 前缀 和 后缀. |
| valueChanged(int) | 微调框的⽂本发⽣改变时会触发. 参数 int, 表⽰当前的数值 |

4.5 Date Edit & Time Edit (日期&时间微调框)
这⼏个控件⽤法⾮常相似, 这里以 QDateTimeEdit 为例进⾏介绍
| 属性 | 说明 |
| dateTime | 时间⽇期的值. 形如 2000/1/1 0:00:00 |
| date | 单纯⽇期的值. 形如 2001/1/1 |
| time | 单纯时间的值. 形如 0:00:00 |
| displayFormat | 时间⽇期格式. 形如 yyyy/M/d H:mm • y 表⽰年份 • M 表⽰⽉份 • d 表⽰⽇期 • H 表⽰⼩时 • m 表⽰分钟 • s 表⽰秒 注意: 这⾥的格式化符号的含义, 不要记忆. 不同语⾔/库的设定规则 是存在差异的. ⼀定是⽤的时候再去查 |
| minimumDateTime | 最⼩时间⽇期 |
| maximumDateTime | 最⼤时间⽇期 |
| timeSpec | Qt::LocalTime :显⽰本地时间。 Qt::UTC :显⽰协调世界时(UTC)。 Qt::OffsetFromUTC :显⽰相对于UTC的偏移量(时差) |
- UTC 时间是⼀个基于原⼦钟的标准时间
-
如我们使⽤的北京时间, 位于 "东⼋区", 就需要在 UTC 时间基础上 +8 个⼩时的时差
核⼼信号
| 信号 | 说明 |
| dateChanged(QDate) | ⽇期改变时触发. |
| timeChanged(QTime) | 时间改变时触发. |
| dateTimeChanged(QDateTime) | 时间⽇期任意⼀个改变时触发. |

4.6 Dial(旋转按钮)
| 属性 | 说明 |
| value | 持有的数值. |
| minimum | 最⼩值 |
| maximum | 最⼤值 |
| singleStep | 按下⽅向键的时候改变的步⻓ |
| pageStep | 按下 pageUp / pageDown 的时候改变的步⻓ |
| sliderPosition | 界⾯上旋钮显⽰的 初始位置 |
| tracking | 外观是否会跟踪数值变化. 默认值为 true. ⼀般不需要修改. |
| wrapping | 是否允许循环调整. 即数值如果超过最⼤值, 是否允许回到最⼩值. (调整过程能否 "套圈") |
| notchesVisible | 是否显⽰ 刻度线 |
| notchTarget | 刻度线之间的相对位置. 数字越⼤, 刻度线越稀疏 |
核心信号
| 属性 | 说明 |
| valueChanged(int) | 数值改变时触发 |
| rangeChanged(int, int) | 范围变化时触发 |

4.7 Slider(滑动条)
| 属性 | 说明 |
| value | 持有的数值. |
| minimum | 最⼩值 |
| maximum | 最⼤值 |
| singleStep | 按下⽅向键的时候改变的步⻓ |
| pageStep | 按下 pageUp / pageDown 的时候改变的步⻓ |
| sliderPosition | 滑动条显⽰的 初始位置 |
| tracking | 外观是否会跟踪数值变化. 默认值为 true. ⼀般不需要修改 |
| orientation | 滑动条的⽅向是⽔平还是垂直 |
| invertedAppearance | 是否要翻转滑动条的⽅向 |
| tickPosition | 刻度的位置 |
| tickInterval | 刻度的密集程度 |
核⼼信号
| 属性 | 说明 |
| valueChanged(int) | 数值改变时触发 |
| rangeChanged(int, int) | 范围变化时触发 |

- 通过这些设置,就可以让滑动条控制拉伸窗口的大小

- 也可以通过QShortcut这里个类实现快捷键,并connect槽函数
5. 多元素控件
-
QListWidget QListView 列表
-
QTableWidget QTableView 表格
-
QTreeWidget QTreeView 树形
5.0 xxWidget vs xxView是什么区别
-
xxView是MVC结构的一种典型实现,MVC是软件开发中,非常经典的软件结构组织形式
M model数据,V view 视图(界面),C controller控制器 数据和视图之间的业务流程 -
xxView只是负责实现了视图,不负责数据如何存储表示,更不负责数据和视图之间的交互
-
而xxWidget是基于xxView封装而来的,同时吧model和controller都帮我们实现好了
可以直接使用,它提供了功能很方便的api,让我们直接使用
5.1 List Widget(纵向列表)
| 属性 | 说明 |
| currentRow | 当前被选中的是第⼏⾏ |
| count | ⼀共有多少⾏ |
| sortingEnabled | 是否允许排序 |
| isWrapping | 是否允许换⾏ |
| itemAlignment | 元素的对⻬⽅式 |
| selectRectVisible | 被选中的元素矩形是否可⻅ |
| spacing | 元素之间的间隔 |
核⼼⽅法
| ⽅法 | 说明 |
| addItem(const QString& label) addItem(QListWidgetItem *item) | 列表中添加元素 |
| currentItem() | 返回 QListWidgetItem* 表⽰当前选中的元素 |
| setCurrentItem(QListWidgetItem* item) | 设置选中哪个元素 |
| setCurrentRow(int row) | 设置选中第⼏⾏的元素 |
| insertItem(const QString& label, int row) insertItem(QListWidgetItem *item, int row) | 在指定的位置插⼊元素 |
| item(int row) | 返回 QListWidgetItem* 表⽰第 row ⾏的元素 |
| takeItem(int row) | 删除指定⾏的元素, 返回 QListWidgetItem* 表⽰是哪个元素被删 除了 |
核心信号
| 方法 | 说明 |
| currentItemChanged(QListWidgetItem* current, QListWidgetItem* old) | 选中不同元素时会触发. 参数是当前选中的元素和之前选中的元素 |
| currentRowChanged(int) | 选中不同元素时会触发. 参数是当前选中元素的⾏数. |
| itemClicked(QListWidgetItem* item) | 点击某个元素时触发 |
| itemDoubleClicked(QListWidgetItem* item) | 双击某个元素时触发 |
| itemEntered(QListWidgetItem* item) | ⿏标进⼊元素时触发 |

- 对于添加条目,可以直接通过图形化界面的方式

- 使用QListWidget时,记得包含头文件<QListWidget>
5.2 Table Widget(表单)
TableWidget控件相当于二维ListWidget
| 属性 | 说明 |
| item(int row, int column) | 根据⾏数列数获取指定的 QTableWidgetItem* |
| setItem(int row, int column, QTableWidget*) | 根据⾏数列数设置表格中的元素 |
| currentItem() | 返回被选中的元素 QTableWidgetItem* |
| currentRow() | 返回被选中元素是第⼏⾏ |
| currentColumn() | 返回被选中元素是第⼏列 |
| row(QTableWidgetItem* ) | 获取指定 item 是第⼏⾏ |
| column(QTableWidgetItem* ) | 获取指定 item 是第⼏列 |
| rowCount() | 获取⾏数 |
| columnCount() | 获取列数 |
| insertRow(int row) | 在第 row ⾏处插⼊新⾏ |
| insertColumn(int column) | 在第 column 列插⼊新列 |
| removeRow(int row) | 删除第 row ⾏ |
| removeColumn(int column) | 删除第 column 列 |
| setHorizontalHeaderItem(int column, QTableWidget*) | 设置指定列的表头 |
| setVerticalHeaderItem(int row,QTableWidget*) | 设置指定⾏的表头 |
核⼼信号
| 信号 | 说明 |
| cellClicked(int row, int column) | 点击单元格时触发 |
| cellDoubleClicked(int row, int column) | 双击单元格时触发 |
| cellEntered(int row, int column) | ⿏标进⼊单元格时触发 |
| currentCellChanged(int row, int column, int previousRow, int previousColumn) | 选中不同单元格时触发 |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ ui->setupUi(this);ui->lineEdit->setPlaceholderText("请输入一列名");ui->lineEdit_2->setPlaceholderText("请输入一行名");// 初始化表单// 创建 3 行ui->tableWidget->insertRow(0);ui->tableWidget->insertRow(1);ui->tableWidget->insertRow(2);// 给 3 行设定行名ui->tableWidget->setVerticalHeaderItem(0, new QTableWidgetItem("NO.1"));ui->tableWidget->setVerticalHeaderItem(1, new QTableWidgetItem("NO.2"));ui->tableWidget->setVerticalHeaderItem(2, new QTableWidgetItem("NO.3"));// 创建 3 列ui->tableWidget->insertColumn(0);ui->tableWidget->insertColumn(1);ui->tableWidget->insertColumn(2);// 给 3 列设定列名ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("学号"));ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("姓名"));ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("年龄"));// 设置初始数据ui->tableWidget->setItem(0, 0, new QTableWidgetItem("1001"));ui->tableWidget->setItem(0, 1, new QTableWidgetItem("张三"));ui->tableWidget->setItem(0, 2, new QTableWidgetItem("20"));ui->tableWidget->setItem(1, 0, new QTableWidgetItem("1002"));ui->tableWidget->setItem(1, 1, new QTableWidgetItem("李四"));ui->tableWidget->setItem(1, 2, new QTableWidgetItem("21"));ui->tableWidget->setItem(2, 0, new QTableWidgetItem("1003"));ui->tableWidget->setItem(2, 1, new QTableWidgetItem("王五"));ui->tableWidget->setItem(2, 2, new QTableWidgetItem("19"));}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_addrow_clicked()
{int row = ui->tableWidget->rowCount();ui->tableWidget->insertRow(row);const QString& name = ui->lineEdit_2->text();ui->tableWidget->setVerticalHeaderItem(row,new QTableWidgetItem(name));
}void Widget::on_pushButton_addcolum_clicked()
{int col = ui->tableWidget->columnCount();ui->tableWidget->insertColumn(col);const QString& name = ui->lineEdit->text();ui->tableWidget->setHorizontalHeaderItem(col,new QTableWidgetItem(name));
}void Widget::on_pushButton_delrow_clicked()
{int row = ui->tableWidget->currentRow();ui->tableWidget->removeRow(row);
}void Widget::on_pushButton_delcolum_clicked()
{int cur = ui->tableWidget->currentColumn();ui->tableWidget->removeColumn(cur);
}

5.3 Tree Widget (树状形节点表单)
| 属性 | 说明 |
| clear | 清空所有⼦节点 |
| addTopLevelItem(QTreeWidgetItem* item) | 新增顶层节点 |
| topLevelItem(int index) | 获取指定下标的顶层节点. |
| topLevelItemCount() | 获取顶层节点个数 |
| indexOfTopLevelItem(QTreeWidgetItem* item) | 查询指定节点是顶层节点中的下标 |
| takeTopLevelItem(int index) | 删除指定的顶层节点. 返回 QTreeWidgetItem* 表⽰被删除 的元素 |
| currentItem() | 获取到当前选中的节点, 返回 QTreeWidgetItem* |
| setCurrentItem(QTreeWidgetItem* item) | 选中指定节点 |
| setExpanded(bool) | 展开/关闭节点 |
| setHeaderLabel(const QString& text) | 设置 TreeWidget 的 header 名称. |
核心方法
| 方法 | 说明 |
| addChild(QTreeWidgetItem* child) | 新增⼦节点 |
| childCount() | ⼦节点的个数 |
| child(int index) | 获取指定下标的⼦节点. 返回 QTreeWidgetItem* |
| takeChild(int index) | 删除对应下标的⼦节点 |
| removeChild(QTreeWidgetItem* child) | 删除对应的⼦节点 |
| parent() | 获取该元素的⽗节点 |
核⼼信号
| 信号 | 说明 |
| currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* old) | 切换选中元素时触发 |
| itemClicked(QTreeWidgetItem* item, int col) | 点击元素时触发 |
| itemDoubleClicked(QTreeWidgetItem* item, int col) | 双击元素时触发 |
| itemEntered(QTreeWidgetItem* item, int col) | ⿏标进⼊时触发 |
| itemExpanded(QTreeWidgetItem* item) | 元素被展开时触发 |
| itemCollapsend(QTreeWidgetItem* item) | 元素被折叠时触发 |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ ui->setupUi(this);ui->treeWidget->setHeaderLabel("动物");QTreeWidgetItem* item1 = new QTreeWidgetItem();item1->setText(0, "猫");ui->treeWidget->addTopLevelItem(item1);//添加顶层节点QTreeWidgetItem* item2 = new QTreeWidgetItem();item2->setText(0, "狗");ui->treeWidget->addTopLevelItem(item2);//添加顶层节点QTreeWidgetItem* item3 = new QTreeWidgetItem();item3->setText(0, "鸟");ui->treeWidget->addTopLevelItem(item3);//添加顶层节点
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{const QString& text = ui->lineEdit->text();if(text.isEmpty()){return;}// 添加到顶层节点中QTreeWidgetItem* item = new QTreeWidgetItem();item->setText(0,text);ui->treeWidget->addTopLevelItem(item);
}void Widget::on_pushButton_2_clicked()
{const QString& text = ui->lineEdit->text();if (text.isEmpty()) {return;}// 获取到当前选中的节点QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();if (currentItem == NULL) {return;}// 构造新的 itemQTreeWidgetItem* newItem = new QTreeWidgetItem();newItem->setText(0, text);// 添加 item 到选中节点currentItem->addChild(newItem);// 展开父节点currentItem->setExpanded(true);
}void Widget::on_pushButton_3_clicked()
{QTreeWidgetItem* cur = ui->treeWidget->currentItem();if(cur == NULL){return;}// 获取当前节点的父节点QTreeWidgetItem* parent = cur->parent();if(parent == NULL){// 顶层节点// 查询指定节点是顶层节点中的下标int index = ui->treeWidget->indexOfTopLevelItem(cur);ui->treeWidget->takeTopLevelItem(index);}else{// 非顶层节点parent->removeChild(cur);}
}

- QTreeWidget控件虽然是树形结构,但是这个树形结构,没有体现出根节点,
是从根节点的下一次子节点开始计算的 - 针对顶层节点来说,这里也是一个类似于"List"这样的结构
6 容器类控件
6.1 Group Box(控件组)
| 属性 | 说明 |
| title | 分组框的标题 |
| alignment | 分组框内部内容的对⻬⽅式 |
| flat | 是否是 "扁平" 模式 |
| checkable | 是否可选择. 设为 true, 则在 title 前⽅会多出⼀个可勾选的部分 |
| checked | 描述分组框的选择状态 (前提是 checkable 为 true) |

6.2 Tab Widget(多页面)
| 属性 | 说明 |
| tabPosition | 标签⻚所在的位置. • North 上⽅ • South 下⽅ • West 左侧 • East 右侧 |
| currentIndex | 当前选中了第⼏个标签⻚ (从 0 开始计算) |
| currentTabText | 当前选中的标签⻚的⽂本 |
| currentTabName | 当前选中的标签⻚的名字 |
| currentTabIcon | 当前选中的标签⻚的图标 |
| currentTabToolTip | 当前选中的标签⻚的提⽰信息 |
| tabsCloseable | 标签⻚是否可以关闭 |
| movable | 标签⻚是否可以移动 |
核⼼信号
| 属性 | 说明 |
| currentChanged(int) | 在标签⻚发⽣切换时触发, 参数为被点击的选项卡编号 |
| tabBarClicked(int) | 在点击选项卡的标签条的时候触发. 参数为被点击的选项卡编号 |
| tabBarDoubleClicked(int) | 在双击选项卡的标签条的时候触发. 参数为被点击的选项卡编号. |
| tabCloseRequest(int) | 在标签⻚关闭时触发. 参数为被关闭的选项卡编号. |

-
Qt 中使⽤⽗⼦关系决定控件的相对位置
7 布局控件
7.1 QVBoxLayout(垂直布局)
Layout 只是⽤于界⾯布局, 并没有提供信号
| 属性 | 说明 |
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上⽅边距 |
| layoutBottomMargin | 下⽅边距 |
| layoutSpacing | 相邻元素之间的间距 |

- 界⾯上的按钮就存在于布局管理器中. 随着窗⼝尺⼨变化⽽发⽣改变

说明一下:
- 界面上的按钮不会随窗口尺寸变化而发生改变
- 通过 Qt Designer 创建的布局管理器, 其实是先创建了⼀个 widget, 设置过 geometry 属性
的. 再把这个 layout 设置到这个 widget 中.
-
实际上, ⼀个 widget 只能包含⼀个 layout.
7.2 QHBoxLayout(水平布局)
Layout 只是⽤于界⾯布局, 并没有提供信号
| 属性 | 说明 |
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上⽅边距 |
| layoutBottomMargin | 下⽅边距 |
| layoutSpacing | 相邻元素之间的间距 |

- 界⾯上的按钮就存在于布局管理器中. 随着窗⼝尺⼨变化⽽发⽣改变

- 布局控件是可以嵌套的所以 结合 QHBoxLayout 和 QVBoxLayout , 就可以做出各种复杂的界⾯了
7.3 QGridLayout(网格布局)
| 属性 | 说明 |
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上⽅边距 |
| layoutBottomMargin | 下⽅边距 |
| layoutHorizontalSpacing | 相邻元素之间⽔平⽅向的间距 |
| layoutVerticalSpacing | 相邻元素之间垂直⽅向的间距 |
| layoutRowStretch | ⾏⽅向的拉伸系数 |
| layoutColumnStretch | 列⽅向的拉伸系数 |

- 使⽤ addWidget 添加控件到布局管理器中. 但是添加的同时会指定两个坐标. 表⽰放在第⼏⾏, 第⼏列
-
任意调整⾏列, 即可看到不同的效果

-
注意: 如果要设置垂直方法的拉伸直接setRowStretch 效果不明显, 因为每个按钮的⾼度是固定的. 需要
-
把按钮的垂直⽅向的 sizePolicy 属性设置为 QSizePolicy::Expanding 尽可能填
充满布局管理器, 才能看到效果
btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
7.4 QFormLayout(表单布局)
属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局
这种表单布局多⽤于让⽤⼾填写信息的场景. 左侧列为提⽰, 右侧列为输⼊框

7.5 Spacer(空白布局)
使⽤布局管理器的时候, 可能需要在控件之间, 添加⼀段空⽩. 就可以使⽤ QSpacerItem 来表⽰
| 属性 | 说明 |
| width | 宽度 |
| height | ⾼度 |
| hData | ⽔平⽅向的 sizePolicy • QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。 • QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。 • QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。 • QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该 值。 • QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空 间。 • QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应 空间。 |
| vData | 垂直⽅向的 sizePolicy 选项同上. |

- 调整 QSpacerItem 不同的尺⼨, 即可看到不同的间距
第二节 QT窗口
Qt 窗⼝ 是通过 QMainWindow类 来实现的
-
菜单栏(menu bar)
-
⼯具栏(tool bars)
-
浮动窗⼝(铆接部件)(dock widgets)
-
中⼼部件(central widget)
-
状态栏(status bar)
1. 菜单栏
⼀个主窗⼝最多只有⼀个菜单栏

1.1 创建菜单栏&&菜单&&菜单项

- 这里的菜单项和后面的工具栏的工具是同一个类,都是QAction
1.2 添加快捷键 && 链接信号槽

- 菜单项点击的时候会触发triggered信号,和前面那个信号类似
1.3 创建子菜单
- 就是在菜单中嵌套另一个菜单,就叫做子菜单
1.4 设置菜单项图标

说明一下:
- 如果给菜单也加上图标的话,就会把菜单的text覆盖掉
1.5 关于正确创建QMenuBar类


说明一下:
- 如果我们之前创建的项目,没有勾选ui文件,此时这2种代码都是正确的
- 但是如果勾选了自动生成ui文件,那么第2种代码就会引起内存泄漏,因为Qt已经自动生成了一个QMenuBar(在ui文件中,各个类的结构中可以看到),同时后面的QStatusBar也是一样的问题
2. 工具栏
⼯具栏是应⽤程序中集成各种功能实现快捷键使⽤的⼀个区域

2.1 创建工具栏

说明一下:
- 工具栏是可以有多个,并且可以像浮动窗口一样浮动和移动的
2.2 设置工具栏停靠位置

说明一下:
- Qt::LeftToolBarArea 停靠在左侧
- Qt::RightToolBarArea 停靠在右侧
- Qt::TopToolBarArea 停靠在顶部
- Qt::BottomToolBarArea 停靠在底部
- Qt::AllToolBarAreas 以上四个位置都可停靠
- Qt中很多枚举类型值,都不建议死记,建议不清楚的时候查查文档
3. 状态栏
状态栏是应⽤程序中输出简要信息的区域
3.1 关于正确创建工具栏

说明一下:
- addWidget是添加子控件的意思,
- 推荐使用this->statusBar()创建/获得对象,
4 滑动窗口
4.1 创建滑动窗口

说明一下:
-
浮动窗口内部, 添加一些其他的控件,不能直接给这个浮动窗口添加子控件, 而是需要创建出一个单独的 QWidget, 把要添加的控件加入到 QWidget 中
-
然后再把这个 QWidget 设置到 dockWidget 中.
5. 对话框
5.1 创建对话框

- QDialog不同于其他控件,此处QDialog每次按下按钮,都会创建一个新的QDialog对象
- 而一个程序运行过程中,可能会无数次触发点击这个按钮,就会产生无数个这样的对象
不好好处理,就会出现内存泄漏的问题,

说明一下:
- 而Qt为了方便我们使用,就封装了一层,在实际使用的时候,只要给dialog设置上下面这个属性
就会在关闭的时候自动进行delete(这个属于Qt内置的功能) -
dialog->setAttribute(Qt::WA_DeleteOnClose);
5.2 自定义对话框


说明一下:
- 想要自定义对话框,就需要继承自QDialog创建类,这里是通过代码自定义的

说明一下:
- 这个操作会创建出一个ui文件以及对应的类
- 通过图形化的方式创建会比代码创建的更快一些,因为会自动生成ui文件
5.3 模态与非模态

说明一下:
- dialog->show() 非模态: 弹出对话框的时候,用户可以操作父窗口
- dialog->exec() 模态: 弹出对话框的时候,用户无法操作父窗口

- Qt 提供了多种可复⽤的对话框类型,即 Qt 标准对话框。Qt 标准对话框全部继承于 QDialog类
5.4 QMessageBox(消息对话框)
| Question | ⽤于正常操作过程中的提问 |
| Information | ⽤于报告正常运⾏信息 |
| Warning | ⽤于报告⾮关键错误 |
| Critical | ⽤于报告严重错误 |
说明一下:
- QMessageBox 使用场景更多的是模态的(无法操作父窗口)


- 也可以通过QMessageBox中的静态成员函数,快速生成消息对话框
5.5 QColorDialog(调色板对话框)

- 直接调用QColorDialog静态成员函数生成对象是最快的
5.6 QFileDialog(文件对话框)


说明一下:
- 此处的打开/保存这里的功能都是需要额外去实现的,并不是直接一保存就保存好了
- QFileDialog::getOpenFileName的返回值是QString,是文件路径
- 但如果是QFileDialog::getOpenFileNames打开一堆文件,那么它的返回值就是QStringList,会保存一堆文件
5.7 QInputDialog(输入对话框)

5.8 QFontDialog(字体对话框)

6. 案例(动手)
自己实现一个图片预览器,有时间的话可以自己再研究研究,其实在用qt画客户端界面就是调函数,调函数,基本无脑,选中控件+F1进行帮助界面中,一个一个的查就行了
预览如下图:

要求说明:
- 需要一个按钮能够打开一个图片,或一堆图片,并把图片名显示在左侧列表中
- 右侧也能预览这个图片
- 还需要实现上一张 下一张 放大 缩小 左旋 右旋 删除
- 还有记得对图片去重,就是不能打开已存在列表中的图片
6.1 关键点 :分离/隐藏文件路径 和 文件名
由于后面不仅是需要使用图片的文件名,还有图片路径的,所以在打开文件时,是需要记录和保存这个2个值的
// 隐藏文件路径,包含去重处理
void MainWindow::HideFilePath(QString filePath)
{QFileInfo fileInfo(filePath);//记录文件信息// 创建一个新的条目,并隐藏文件路径QListWidgetItem * fileMap = new QListWidgetItem();//创建一个条目fileMap->setText(fileInfo.fileName());// 文件名fileMap->setData(Qt::UserRole,filePath);//隐藏文件路径// 去重:查找是否已有相同文件名的条目// 第二个参数为查找完全匹配准确度,其中Qt::MatchExactly为完全匹配QList<QListWidgetItem*> existingItems = ui->list_picture->findItems(fileInfo.fileName(), \Qt::MatchExactly);if (existingItems.isEmpty()) {// 不存在相同的文件名,则添加ui->list_picture->addItem(fileMap);return;}
}





