元对象
-
要在 Qt Creator 中启动元对象系统,包含 Q_OBJECT 宏的类的定义必须位于头文件中,否则 moc 工具不能生成元对象代码
-
若定义了 QObject 类的派生类,并进行了构建,在这之后再添加 Q_OBJECT 宏,则此时必须执行一次 qmake 命令(“构建”>“执行 qmake”),否则 moc 不能生成代码
-
要使用元对象系统的功能,需要满足以下三个条件:
- 该类必须继承自 QObject 类。
- 必须在类声明的私有区域添加 Q_OBJECT 宏,该宏用于启动元对象特性,然后便可使用动态特性、信号和槽等功能了。
- *元对象编译器(moc)为每个 QObject 的子类,提供实现了元对象特性所必须的代码
- 多重继承时 QObject 必须位于基类列表中的第一位
- QMetaObject 类描述了 QObject 及其派生类对象的所有元信息,QMetaObject 类的对象是 Qt 中的元对象。
- 成员进行描述
- 函数成员使用类QMetaMethod 进行描述
- 属性使用 QMetaProperty 类进行描述等,
- 使用QMetaObject 类对整个类对象进行描述
使用 Qt 反射机制的条件
- 需要继承自 QObject 类,并需要在类之中加入 Q_OBJECT 宏。
- 注册成员函数:若希望普通成员函数能够被反射,需要在函数声明之前加入QObject::Q_INVOKABLE 宏。
- 注册成员变量:若希望成员变量能被反射,需要使用 Q_PROPERTY 宏
要在类之中声明属性,该类必须继承自 QObject 类,还应使用 Q_OBJECT 宏,然后使用QObject::Q_PROPERTY 宏声明属性
Q_PROPERTY(type name
(READ getFunction [WRITE setFunction] |
MEMBER memberName [(READ getFunction | WRITE setFunction)])
[RESET resetFunction]
[NOTIFY notifySignal]
[REVISION int]
[DESIGNABLE bool]
[SCRIPTABLE bool]
[STORED bool]
[USER bool]
[CONSTANT]
[FINAL])
- type:指定属性的类型,可以是 QVariant 支持的类型或用户自定义类型,若是枚举类型,还需使用 Q_ENUMS 宏对枚举进行注册,若是自定义类型,需要使用Q_DECLARE_METATYPE( Type )宏进行注册(详见后文)。
- name:指定属性的名称。
- READ getFunction: 用于指定读取函数(读取属性的值),其中 READ 表示读取,不可更改,getFunction用于指定函数名称。
若没有指定 MEMBER 变量,则必须指定 READ 函数。通常,READ 函数是 const 的,READ 函数必须返回属性的类型或对该类型的引
用。 - WRITE setFunction: 用于指定设置函数(设置属性的值),其中 WRITE 表示写入,不可更改,setFunction
用于指定函数名称。此函数必须只有一个参数,且返回值类型必须为 void。 若为只读属性,则不需要指定 WRITE 函数。 - MEMBER memberName 用于把指定的成员变量 memberName 设置为具有可读和可写性质,而无需创建
READ 和 WRITE 函数。其中 MEMBER 表示成员,不可更改,memberName 表示类中的成员变量。若没有指定 READ 函数,则必须指定 MEMBER 变量。 - RESET resetFunction:用于把属性重置为默认值,该函数不能有参数,且返回值必须为 void。其中 RESET 表示重置,不可更改resetFunction 用于指定函数名称。
- NOTIFY notifySignal:表示给属性关联一个信号。如果设置该项,则应指定该类中
已经存在的信号,每当属性值发生变化时就会发出该信号。若使用 MEMBER 变量, 则 NOTIFY 信号必须为零或一个参数,且参数必须与属性的类型相同,该参数将接受该属性的新值。 - REVISION:设置版本号,默认为 0。
- DESIGNABLE:用于设置属性在 GUI 设计工具的属性编辑器(例如 Qt 设计师)中是否可见,多数属性是可见的,默认值为 ture,即可见。该变量也可以指定一个返回布尔值的成员函数替代 true 或 false。
- SCRIPTABLE:设置属性是否可被脚本引擎访问,默认为 true
- STORED:设置在保存对象的状态时是否必须保存属性的值。大多数属性此值为 true
- USER:设置属性是否为可编辑的属性,每一个类只有一个 USER 属性(默认值为
false)。比如 QAbstractButton::checked 是用户可编辑的属性 - CONSTANT:表明属性的值是常量,常量属性不能有WRITE函数和NOTIFY信号。对于同一个对象实例,每一次使用常量属性的 READ 函数都必须得到相同的值,但对于类的不同实例,这个值可以不同。
- FINAL:表示属性不能被派生类重写。
Q_DECLARE_METATYPE( Type ) 注册一个类型使得QVariantk可以识别
信号和槽
只有 QObject 及其派生类才能使用信号和槽机制,且在类之中还需要使用 Q_OBJECT 宏
信号的定义规则
- 信号使用 signals 关键字声明,在其后面有一个冒号“:”,在其前面不能有 public、private、protected 访问控制符,信号默认是 public 的。
- 信号只需像函数那样声明即可,其中可以有参数,参数的主要作用是用于和槽的通信,这就像普通函数的参数传递规则一样。信号虽然像函数,但是对他的调用方式不一样,信号需要使用 emit关键字发射。
- 信号只需声明,不能对其进行定义,信号是由 moc 自动生成的。
- 信号的返回值只能是 void 类型的。
槽需符合以下规则
- 声明槽需要使用 slots 关键字,在其后面有一个冒号“:”,且槽需使用 public、private、protected 访问控制符之一。
- 槽就是一个普通的函数,可以像使用普通函数一样进行使用,槽与普通函数的主要区别是,槽可以与信号关联
信号和槽的关系
- 槽的参数的类型需要与信号参数的类型相对应,
- 槽的参数不能多余信号的参数,因为若槽的参数更多,则多余的参数不能接收到信号传递过来的值,若在槽中使用了这些多余的无值的参数,就会产生错误。
- 若信号的参数多余槽的参数,则多余的参数将被忽略。
- 一个信号可以与多个槽关联,多个信号也可以与同一个槽关联,信号也可以关联到另一个信号上。
- 若一个信号关联到多个槽时,则发射信号时,槽函数按照关联的顺序依次执行。
- 若信号连接到另一个信号,则当第一个信号发射时,会立即发射第二个信号
信号和槽的关联(连接) Connect
- 形式1:
static QMetaObject::Connection connect(
const QObject *sender, //发射信号的对象指针
const char *signal, //发送的信号 必须使用 SIGNAL()宏
const QObject *receiver, //接收信号的对象指针
const char *method, // 接收信号的槽函数,SLOT()宏,若是信号需使用 SIGNAL 宏
Qt::ConnectionType type = Qt::AutoConnection)
实例
class A:public QObject {Q_OBJECT singals: void s(int i);};
class B:public QObject{Q_OBJECT public slots: void x(int i){}};
A ma; B mb;
QObject::connect (&ma, SIGNAL( s(int) ), &mb, SLOT(x(int) );
Qt::ConnectionType
Qt::ConnectionType 的取值(type 参数的取值)枚举值 | 说明 |
---|---|
Qt::AutoConnection 0 | (自动关联,默认值)。若接收者驻留在发射信号的线程中(即信号和槽在同一线程中),则使用 Qt :: DirectConnection,不在同一个线程内,使用 Qt :: QueuedConnection。当信号发射时确定使用哪种关联类型。 |
Qt::DirectConnection 1 | 直接关联。当信号发射后,立即调用槽。在槽行完之后,才会执行发射信号之后的代码(即 emit 关键字之后的代码)。该槽在信号线程中执行。 |
Qt::QueuedConnection 2 | 队列关联。当控制权返回到接收者线程的事件循环后,槽才会被调用,也就是说 emit 关键字后面的代码将立即执行,槽将在稍后执行,该槽在接收者的线程中执行。 |
Qt::BlockingQueuedConnection 3 | 阻塞队列关联。和 Qt :: QueuedConnection 一样,只是信号线程会一直阻塞,直到槽返回。如果接收者驻留在信号线程中,则不能使用此连接,否则应用程序将会死锁。 |
Qt::UniqueConnection 0x80 | 唯一关联。这是一个标志,可使用按位或与上述任何连接类型组合。当设置 Qt :: UniqueConnection 时,则只有在不重复的情况下才会进行连接,如果已经存在重复连接(即,相同的信号指向同一对象上的完全相同的槽),则连接将失败,此时将返回无效的 QMetaObject::Connection |
- 形式2:
QMetaObject::Connection connect(
const QObject *sender,
const char *signal,
const char *method,
Qt::ConnectionType type = Qt::AutoConnection) const
例子
A ma;
B mb;
mb.connect(&ma, SIGNAL(s(int)), SLOT(x(int));
- 形式3
static QMetaObject::Connection connect(
const QObject *sender,
PointerToMemberFunction signal,
const QObject *receiver,
PointerToMemberFunction method,
Qt::ConnectionType type = Qt::AutoConnection)
例子
A ma;
B mb;
QObject::connect(&ma, &A::s, &mb, &B::x );
- 形式4
static QMetaObject::Connection connect(
const QObject *sender,
PointerToMemberFunction signal,
Functor functor)
示例:假设 void s(int i)是类 A 中定义的信号,void x(int i)是类 B 中定义的静态槽,
则
A ma;
QObject::connect(&ma, &A::s, &B::x );
signals、slots、emit 关键字原型
- 在以上关键字上右击然后按下 F2,在 qobjectdefs.h 文件中可以看到这些关键字的原型
- signals 关键字:最终被#define 置换为一个访问控制符,其简化后的语法为#define signals public
- slots 关键字:最终被#define 置换为一个空宏,即简化后的语法为:#define slots
- emit 关键字:同样被#define 置换为一个空宏,即简化后为:#define emit
- 由以上各关键字原型可见,使用 emit 发射信号,其实就是一个简单的函数调用
事件
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6OPOzmIU-1632751916577)(./pic/application.png)]
- QCoreApplication:主要提供无 GUI 程序的事件循环。
- QGuiApplication:用于管理 GUI 程序的控制流和主要设置。
- QApplication 专门为 QGuiApplication 提供基于 QWidget 的程序所需的一些功能
- 初始化应用程序
- 执行事件处理
- 解析常用命令行参数
- 定义了应用程序的界面外观,可使用 QApplication::setStyle()进行更改
- 使用 QCoreApplication::translate()函数对字符串进行转换。
- 通过 QApplication::desktop()函数处理桌面,通过 QCoreApplication::clipboard()函数处理剪贴板。
- 管理应用程序的鼠标光标
Qt 事件event
- 继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KH1wsSvL-1632751916580)(./pic/event.png)]
事件和信号的区别
- 他们两个是不同的概念,不要弄混淆。信号是由对象产生的,而事件则不一定是由对象产生的(比如由鼠标产生的事件),事件通常来自底层的窗口系统,但也可以手动发送自定义的事件,可见信号和事件的来源是不同的。
- 事件既可以同步使用,也可以异步使用 (取决于调用 sendEvent()还是 postEvents()),而使用信号和槽总是同步的。事件的另一个好处是可以被过滤。
- QEvent::accept()函数表示接受一个事件,使用 QEvent::ignore()函数表示忽略一个事件。
- QCloseEvent(关闭事件)有一些不同,QCloseEvent::ignore()表示取消关闭操作,而QCloseEvent::accept()则表示让 Qt 继续关闭操作。
Qt 实现事件过滤器的步骤如下:
- Qt 调用
void QObject::installEventFilter (QObject* filterObj)
把 filterObj 对象设置安装(或注册)为事件过滤器,filterObj 也称为过滤器对象。事件过滤器通常在构造函数中进行注册。
2. 在上一步注册的 filterObj 对象,通过调用
bool QObject::eventFilter(QObject* obj, QEvent* e);
来接收拦截到的事件。也就是说拦截到的事件在 filterObj 对象中的 eventFilter 函数中处理。eventFilter 的第一个参数 obj 指向的是事件本应传递到的目标对象。
3. 使用
QObject::removeEventFilter(QObject *obj)
函数可以删除事件过滤器。
过滤器事件过滤器处理事件的规则
eventFilter()函数可以接受或拒绝拦截到的事件,
- 若该函数返回 false,则表示事件需要作进一步处理,此时事件会被发送到目标对象本身进行处理(注意:这里并未向父对象进行传递),
- 若 evetnFilter()返回 true,则表示停止处理该事件,此时目标对象和后面安装的事件过滤器就无法获得该事件
自定义事件发送
// 直接发送给接收事件的目标对象
static void QCoreApplication::postEvent (
QObject* receiver, //指向接收事件的对象
QEvent* event, //需要发送的事件
int priority=Qt::NormalEventPriority);//事件的优先级
static bool QCoreApplication::sendEvent(
QObject* receiver,
QEvent* event)
- QWidget :: setMouseTracking()函数启用鼠标跟踪后,就即使不按下鼠标按钮也会产生鼠标移动事件
枚举值 | 值 | 说明 |
---|---|---|
Qt::NoButton | 0x0000 0000 | 按钮状态不指向任何按钮。 |
Qt::LeftButton | 0x0000 0001 | 按下左键 |
Qt::RightButton | 0x0000 0002 | 按下右键 |
Qt::MidButton 或 Qt::MiddleButton | 0x0000 0004 按下中键 |
鼠标和键盘事件共同使用的类及函数
- 通过调用从 QInputEvent::modifiers()函数可以查询键盘修饰键的状态。
- 使用 QWidget::etEnable()函数可以启用或禁用部件的鼠标和键盘事件。
- 键盘修饰键(即 Ctrl、Alt、Shift 等键)使用枚举类型 Qt::KeyboardModifier 来描述,其取值如下表
枚举值 | 值 | 说明 |
---|---|---|
Qt::NoModifier | 0x0000 0000 | 无修饰键被按下 |
Qt::ShiftModifier | 0x0200 0000 | 按下 Shift 键 |
Qt::ControlModifier | 0x0400 0000 | 按下 Ctrl 键 |
Qt::AltModifier | 0x0800 0000 | 按下 Alt 键 |
Qt::MetaModifier | 0x1000 0000 | 按下 Meta 键(windows 系统为 windows 键) |
Qt::KeypadModifier | 0x2000 0000 | 按下小键盘上的键 |
Qt::GroupSwitchModifier | 0x4000 0000 | 按下 Mode_switch 键(仅限 X11) |
鼠标事件 QMouseEvent
QMouseEvent(
Type type, //鼠标事件的类型
const QPointF &localPos, //鼠标光标的位置
Qt::MouseButton button,//产生鼠标事件的按钮,若事件类型是 MouseEvent,则此值是Qt::NoButton
Qt::MouseButtons buttons, //哪些鼠标按钮处于按下状态
Qt::KeyboardModifiers modifiers);//键盘修饰键
键盘事件 QKeyEvent
- 按键与自动重复:自动重复是指按下键盘上的键(修饰键除外)不放时,会不断重复的发送键按下事件,Qt 默认是启用自动重复的,若要实现类似按键 A+D 之类的快捷键,就需要关闭自动重复。可使用如下方法来关闭自动重复if( QKeyEvent::isAutoRepeat() ) return; // 若自动重复则什么也不做
- 压缩按键事件
QKeyEvent (
Type type, //type:表示键盘事件的类型,必须是 QEvent::KeyPress、QEvent::KeyRelease QEvent::ShortcutOverride 之一
int key, //描述键代码的 Qt::Key 枚举值
Qt::KeyboardModifiers modifiers, //键盘的修饰键
const QString &text = QString(), //按键生成的 Unicode 字符
bool autorep = false, //是否启用自动重复
ushort count = 1)//产生该事件时的按键数量
小结
QEvent 类
-
QEvent(Type type) //构造函数,用于创建自定义事件
-
virtual ~QEvent() //析构函数
-
void accept() //接受事件
-
void ignore() //忽略事件
-
void setAccepted(bool a) //设置是否接受事件
-
Type type() const //返回事件的类型
-
static int registerEventType(int hint=-1):
注册并返回自定义事件类型,使用该函数的返回值可保证自定义的事件不会有重复的 Type 枚举值。 -
enum Type{None, ActionAdded, … Keypress,…} //定义事件的类型,详见帮助文档
QObject 类
- virtual bool event() //接收并处理事件,先于默认的事件处理函数
- void installEventFilter(QObject *finterObj); //安装(或注册)事件过滤器
- vitrual bool eventFilter(QObject* w , QEvent *e ) //用于接收并处理事件过滤器对象接收的事件。
- void removeEventFilter(QObject* obj); //移除事件过滤器。
QCoreApplication 类
- virtual bool notify(QObject* r, QEvent* e) //该函数用于分发事件
- int exec(); //使用该函数进入事件主循环。
- void postEvent(QObject* r, QEvent* e, int priority=Qt::NormalEventPriority); //用于发布自定义事件
- bool sendEvent(QObject* r, QEvent *e); //用于发送自定义事件
QWidget 类
- void grabKeyboard() //捕获键盘输入
- void grabMouse() //捕获鼠标输入
- void grabMouse(const QCursor& c); //捕获鼠标输入
- QWidget* keyboardGrabber(); //返回捕获键盘输入的部件
- QWidget* mouseGrabber(); //返回捕获鼠标输入的部件
- void releaseMouse() //释放捕获的鼠标输入
- void releaseKeyboard() //释放捕获的键盘输入。
- bool hasMouseTracking() const; //是否启用鼠标跟踪
- void setMouseTracking(bool enable) //设置鼠标跟踪状态
- bool underMouse() const; //部件是否位于鼠标光标之下
- void setAttribute ( Qt::WidgetAttribute attribute, bool on=true); //设置是否启用键压缩。
- bool testAttribute(Qt::WidgetAttribute attribute) const //返回是否启用了键压缩。
QWidght
事件
moveEvent()
resizeEvent()
当位置改变时,若部件可见,则会产生 moveEvent()事件,若部件调整大小时可见,则会产生 resizeEvent()事件,当更改部件的几何形状,若部件可见时,会产生 moveEvent()或 resizeEvent()事件,
Qt 对窗口位置和大小进行描述的属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDktVdMK-1632751916581)(./pic/sizexy.png)]
控件默认大小
virtual QSize sizeHint() const;
- 可以重新实现该函数以指定部件的默认大小
窗口状态
Qt::WindowStates windowState() const;
void setWindowState(Qt::WindowStates windowState);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YFpRfZfL-1632751916582)(./pic/WindowState.png)]
标题、透明度、启用/禁用
//标题
QString windowTitle() const;
void setWindowTitle(const QString &);
//保存与部件相关联的路径
QString windowFilePath() const;
void setWindowFilePath(const QString& filePath);
透明度
//标题
qreal windowOpacity() const;
void setWindowOpacity(qreal level);
// 1.0(不透明)到 0.0(透明),
光标有关的属性
QCursor cursor() const;
void setCursor(const QCursor&);
void unsetCursor();
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTnBxqTq-1632751916583)(./pic/CursorShape.png)]
布局管理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fTduoQqS-1632751916584)(./pic/layout.png)]
- 布局项目(重要概念):是指由布局管理的元素,包括 QWidget 部件、QLayout 布局,还有间距 QSpacerItem、QLayoutItem 等,其中 QLayoutItem 是用于描述由布局管理的项目的抽象类
- 由 QHBoxLayout 类实现的水平布局,效果如下图
- 由 QVBoxLayout 类实现的垂直布局,效果如下图
- 由 QGridLayout 类实现的二维网格布局,效果如下图
- 由 QFormLayou 实现的两列表格布局,效果如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fip3dBs1-1632751916585)(./pic/layout_class.png)]
Qt 使用布局管理器的步骤为,
- 首先创建一个布局管理器类的对象
- 然后使用该布局管理器类中的 addWidget()函数,把需要由布局管理器管理的部件添加进来。还可使用 addLayout()函数把其他布局管理器添加进来。
- 最后使用 QWidget::setLayout()函数为窗口设置布局管理器。
说明:
**
- 若为布局指定了父部件,则可以不使用 QWidget::setLayout()函数反之,调用QWidget::setLayout()函数安装布局,则可以不为该布局指定父部件。
- 不需要为添加到布局中的部件指定父部件,布局中的部件会自动成为安装布局的部件的子部件(使用 QWidget::setParent())。注意:子部件的父部件不是布局,而是安装布局的部件**
设置拉伸因子的函数
//为索引为 index(从 0 开始)的部件设置拉伸因子
bool QBoxLayout::setStretch(int index, int stretch);
//为部件 widget 设置拉伸因子。
bool QBoxLayout::setStretchFactor(QWidget* widget, int stretch);
//返回索引 index 处的拉伸因子。
int QBoxLayout::stretch(int index) const;
QWidget 类中对部件大小进行限制的属性
大小属性 | 说明 |
---|---|
1. sizeHint | 默认大小 |
2. minimumSizeHint | 部件的最小大小提示 |
3. minimumSize | 部件的最小大小 |
4. maximumSize | 部件的最大大小 |
QSizePolicy 类
QSizePolicy sizePolicy() const;
void setSizePolicy(QSizePolicy);
void setSizePolicy(
QSizePolicy::Policy horizontal,
QSizePolicy::Policy vert);
//表示设置水平方向的大小策略
QSizePolicy::setHorizontalPolicy(Policy)
//表示设置水平方向的拉伸因子
QSize::setHorizontalStretch(int)
- 该类用于描述布局的大小调整策略
QSizePolicy::Policy 枚举
QSizePolicy::Policy 枚举 | 说明 |
---|---|
QSizePolicy::Fixed | 部件不可拉伸或压缩,其大小始终为 sizeHint 的大小。 |
QSizePolicy::Minimum | 部件的大小提示是其最小大小,部件可以拉伸,但不能压缩得比大小提示更小。部件拉伸范围为 sizeHint~无限 |
QSizePolicy::Maximum | 部件的大小提示是其最大大小,部件可以压缩,但不能拉伸得比大小提示更大。部件拉伸范围为 minimumSizeHint~sizeHint |
QSizePolicy::Preferred | 部件可任意拉伸和压缩,但大小提示仍是合适的大小。部件拉伸范围是minimumSizeHint~无限 |
QSizePolicy::Expanding | 部件可任意拉伸和压缩,但更希望是拉伸,设置该策略的部件拥有优先扩展权。部件拉伸范围是 minimumSizeHint~无限。 |
QSizePolicy::MinmumExpanding |
部件的大小提示是其最小大小,部件可以拉伸,但不能压缩得比大小提示更小,设置该策略的部件拥有优先扩展权。部件拉伸范围为 sizeHint~无限。注:这种策略可能会被淘汰。
|QSizePolicy::Ignored |忽略大小提示,部件可任意拉伸和压缩。部件拉伸范围为minimumSizeHint~无限,注意:若 minimumSizeHint 的值为 0,则该策略可把部件压缩为 0 的大小(即部件不可见) ,除该策略外,其余策略是不能把部件压缩为 0 的大小的。
- 若一些部件拉伸因子大于 0,而一些部件拉伸因子为 0,则只有拉伸因子大于 0 的部件会被拉伸,而拉伸因子为 0 的部件不会被拉伸。若所有部件的拉伸因子都为 0,则按照大小策略的规则对部件进行拉伸。
- 拉伸因子优先级>大小策略优先级
大小约束
- 大小约束其实就是用来设置主窗口的最大和最小值的
sizeConstraint sizeConstraint() const;
void setSizeConstraint(SizeConstraint);
QLayout::SizeConstraint 枚举 | 值 | 说明 |
---|---|---|
QLayout::SetDefaultConstraint | 0 | 把主窗口的最小大小设置为 QLayout::minimumSize(),除非主窗口已经具有最小大小,也就是说若主窗口已显示设置了最小大小,则此约束不会再使用 QLayout::minimumSize()设置主窗口的最小大小。这是默认值 |
QLayout::SetFixedSize | 3 | 主窗口的大小设置为 sizeHint();此时主窗口大小无法被调整,通常使用此约束使主窗口自动适应所布置的部件的大小。 |
QLayout::SetMinimumSize | 2 | 把主窗口的最小大小设置为 QLayout::minimumSize(),主窗口不能调整为比该大小更小。 |
QLayout::SetMaximumSize | 4 | 把主窗口的最大大小设置为 QLayout::maximumSize(),主窗口不能调整为比该大小更大。 |
QLayout::SetMinAndMaxSize | 5 | 把主窗口的大小设置为QLayout::minimumSize()~QLayout::maximumSize() |
QLayout::SetNoConstraint | 1 | 不对主窗口的大小进行设置(即没有约束),也就是说,保持主窗口之前的最大和最小大小,不对其进行更改。 |
A. 内容边距
布局中子部件和子部件之间的间距margin
QMargins QLayout::contentsMargins() const;
void QLayout::getContentsMargins(
int *left,
int *top,
int *right,
int *bottom) const;
void QLayout::setContentsMargins(
int left,
int top,
int right,
int bottom);
void QLayout::setContentsMargins(
const QMargins& margin);
B. 间距 spacing:指的是各部件之间的距离,
C. QSpacerItem 类 弹簧
- 使用该类可以创建自定义的间距,使用该类创建的间距相当于是一个空白部件,它是布局中的一个项目,会在布局中占据一个位置,布局会为其分配一个索引号,
//宽度为 w,高度为 h,水平方向的大小策略为hPolicy,垂直方向大小策略为 vPolicy 的间距
QSpacerItem(
int w,
int h,
QSizePolicy::Policy hPolicy = QSizePolicy::Minimum,
QSizePolicy::Policy vPolicy = QSizePolicy::Minimum) //构造函数
void changeSize(
int w,
int h,
QSizePolicy::Policy hPolicy = QSizePolicy::Minimum,
QSizePolicy::Policy vPolicy = QSizePolicy::Minimum)
//获取大小策略
QSizePolicy sizePolicy() const;
插入QSpacerItem
- 把大小为 size 的不可拉伸间距(QSpacerItem)添加到布局的末尾。
void QBoxLayout::addSpacing(int size);
- 在索引 index 处,插入大小为 size 的不可拉伸间距(QSpacerItem)。若索引为负,则在最后添加空格。
void QBoxLayout::insertSpacing(int index, int size);
- 把具有零最小大小和拉伸因子为 strecth 的可拉伸间距(QSpacerItem)添加到布局的末尾。
void QBoxLayout::addStretch(int strecth = 0);
- 在索引 index 处,插入最小大小为 0,拉伸因子为 stretch 的可拉伸间距(QSpacerItem)。若索引为负,则在最后添加空格。
void QBoxLayout::insertStretch(int index, int stretch =0);
- 在索引 index 处,插入最小大小为 0,拉伸因子为 0 的 spacerItem。若索引为负,则在最后添加空格。
void QBoxLayout::insertSpacerItem(int index, QSpacerItem* spacerItem);
6. 把 spacerItem 添加到布局的末尾
```C++
void QBoxLayout::addSpacerItem(QSpacerItem* spacerItem);
嵌套布局
//在末尾添加布局。
void QBoxLayout::addLayout(
QLayout* layout,
int stretch = 0);
//在指定索引处插入布局,并设置其拉伸因子为 stretch,若 index 为负,则添加到末尾。
void QBoxLayout::insertLayout(
int index,
QLayout* layout,
int stretch = 0);
布局管理器类QBoxLayout、QBoxLayout、QFormLayout
QBoxLayout 子类 QHBoxLayout 和 QVBoxLayout
QBoxLayout::Direction 枚举(无标志)
作用:用于描述盒式布局的方向
QBoxLayout::Direction | 枚举 | 值 说明 |
---|---|---|
QBoxLayout::LeftToRight | 0 | 水平从左到右 |
QBoxLayout::RightToLeft | 1 | 水平从右到左 |
QBoxLayout::TopToBottom | 2 | 垂直从上到下 |
QBoxLayout::BottomToTop | 3 | 垂直从下到上 |
函数介绍
- QBoxLayout(Direction dir, QWidget* parent = Q_NULLPTR); //构造一个方向为 dir 的盒式布局
- 把布局layout添加到末尾或在指定索引index处插入布局,并设置其拉伸因子为stretch, 若 index 为负,则添加到末尾。
void addLayout(QLayout* layout, int stretch = 0);
void insertLayout(int index, QLayout* layout, int stretch = 0);
- 把部件 widget 添加到布局的末尾或添加到索引 index 处,并设置其拉伸因子为 stretch,
对齐方式为 m,默认对齐方式为 0,表示部件填充整个单元格。若 index 为负,则插入
到末尾。Qt::Alignment 属性见公共枚举章节。注意:对齐方式会对部件的拉伸效果产
生影响,非零对齐表示不应拉伸以填充其可用空间。
void addWidget(
QWidget* widget,
int stretch = 0,
Qt::Alignment m = Qt::Alignmnet());
void insertWidget(
int index,
QWidget* widget,
int stretch = 0,
Qt::Alignment m = Qt::Alignmnet());
- 在末尾添加或在索引 index 处插入大小为 size 的不可拉伸间距(QSpacerItem)。若索引
为负,则添加到末尾。
void addSpaceing(int size);
void insertSpacing(int index, int size);
- 在末尾添加或在索引 index 处,插入最小大小为 0,拉伸因子为 stretch 的可拉伸间距
(QSpacerItem)。若索引为负,则添加到末尾。
void addStretch(int stretch = 0);
void insertStretch(int index, int stretch = 0);
- 在末尾添加或在索引 index 处,插入最小大小为 0,拉伸因子为 0 的 spacerItem。若索
引为负,则添加到末尾。
void addSpacerItem(QSpacerItem* spacerItem);
void insertSpacerItem(int index, QSpacerItem* sp);
7. 设置 sapcing 属性
```C++
int spacing() const;
void setSpacing( int spacing);```
8. 分别表示,设置索引为 index 的部件或布局 layout 或部件 widget 的拉伸因子
为 stretch,若 layout 或 widget(不包括子布局)在布局中,则返回 true,否则返回 false。
```C++
void setStretch(int index, int stretch);
bool setStretchFactor(QWidget* widget , int stretch);
bool setStretchFactor(QLayout* layout, int stretch);
- //返回索引为 index 的拉伸因子
int stretch(int index) const;
- //返回布局的方向。
Direction direction() const;
- //设置布局的方向为 dir
void setDirection(Direction dir);
- 返回布局中的项目数。
virtual int count() const;
- 把盒式布局的正交尺寸限制在最小值 size 大小。其中正交尺寸是指,对于垂直布局则是指水平方向的尺寸,对于水平布局则是指垂直方向的尺寸。
void addStruct(int size);
- 把 item 插入到指定索引 index 处,若 index 为负,则插入到末尾。
void insertItem(int index, QLayoutItem* item);
- 从布局中删除指定索引 index 处的项目,并返回该项目,若没有这样的项目,则返回 0,删除项目后,布局中的其他项目会重新编号索引。
virtual QLayoutItem* takeAt(int index)
- QLayout::itemAt()的重新实现返回指定索引 index 处的项目,若没有这样的项目,则返回 0。
virtual QLayoutItem* itemAt(int index) const;
网格布局 QGridLayout
属性
- 以下属性用于获取或设置垂直和水平方向子部件之间的间距。
horizontalSpacing:int /*访问函数:*/int horizontalSpacing() const; void setHorizontalSpacing(int spacing);
verticalSpacing:int /*访问函数:*/int verticalSpacing()const; void setVerticalSpacing(int spacing);
函数
构造函数
QGridLayout();
QGridLayout(QWidget* parent); //构造函数
- 在 row 行,第 column 列单元格添加项目(layout、widget 或 item)
- 其对齐方式为 alignment。默认对齐方式为 0,表示部件会填充整个单元格,非零对齐方式不应增长以填充可用空间
- 若 rowSpan 或columnSpan 为−1,则将 item 分别扩展至底部或右侧边缘。
void addLayout(
QLayout* layout,
int row,
int column,
Qt::Alignment alignment = Qt::Alignment());
void addLayout(
QLayout* layout,
int row, int column,
int rowSpan, int columnSpan,
Qt::Alignment alignment = Qt::Alignment());
void addWidget(
QWidget* widget,
int row,
int column,
Qt::Alignment alignment = Qt::Alignment());
void addWidget(
QWidget* widget,
int row,
int column,
int rowSpan,
int columnSpan,
Qt::Alignment alignment = Qt::Alignment());
void addItem(
QLayoutItem* item,
int row,
int column,
int rowSpan = 1,
int columnSpan = 1,
Qt::Alignment alignment = Qt::Alignment());
单元格的最小高度和宽度
1. int columnCount() const; //返回列数
2. int rowCount() const; //返回行数
3. int columnMinimumWidth(int column) const; //返回 column 列最小宽度
4. void setColumnMinimumWidth(int column, int minSize); //把column 列的**最小宽度**设置为minSize像素。
5. int rowMinimumHeight(int row) const; //返回 row 行的最小高度。
6. void setRowMinimumHeight(int row, int minSize); //把 row 行的**最小高度**设置为 minSize 像素。
设置的是 spcing 属性
1. int columnStretch(int column) const; //返回 column 列的拉伸因子
2. void setColumnStretch(int column, int stretch); //把 column 列的拉伸因子设置为 stretch。
3. int rowStretch(int row) const; //返回 row 行的拉伸因子。
4. void setRowStretch(int row, int stretch); //把 row 行的拉伸因子设置为 stretch。
5. void setSpacing(int spacing);// 把垂直和水平间距都设置为 spacing
6. int spacing() const; //若垂直和水平间距相等,则返回该值,否则返回−1。
表单布局 QFormLayout 类
- 、QFormLayout 被分成两列,左列是标签(label)部分,通常由标签 QLabel 组成,右列是由字段(field)部分
枚举
- 描述表单布局中部件的类型
成员 | 值 | 说明 |
---|---|---|
QFormLayout::LabelRole | 0 | 标签部件 |
QFormLayout::FieldRole | 1 | 字段部件 |
QFormLayout::SpanningRole | 2 | 跨越标签和字段的部件(标签和字段间的间距?) |
- 设置或获取表单布局字段部分的增长方式(注意:标签部分是不会增长的,即使标签部分部件的大小策略被设置为 Expanding,该部件也不会增长
FieldGrowthPolicy fieldGrowthPolicy() const;
void setFieldGrowthPolicy(FieldGrowthPolicy);
成员 | 值 | 说明 |
---|---|---|
QFormLayout::FieldsStayAtSizeHint | 0 | 字段不超出他们的大小提示,QMacStyle 默认值 |
QFormLayout::ExpandingFieldsGrow | 1 | 只有水平方向的大小策略为 Expanding 或MinimumExpanding 的字段可以增长以填充可用的空间,其他字段不会超出他们的大小提示(原理见图示)。这是 QCommonStyle(比如 windows)的默认值 |
QFormLayout::AllNonFixedFieldsGrow | 2 | 所有具有允许增长的大小策略的字会都会增长以填充可用空间,这是大多数样式的默认值(比如 Qt Extended 样式) |
- 表单布局内容的对齐方式
Qt::Alignment formAlignment() const;
void setFormAlignment(Qt::Alignment);
- 标签部分的水平对齐方式
Qt::Alignment labelAlignment() const;
void setLabelAlignment(Qt::Alignment)
- 表单行的换行方式
RowWrapPolicy rowWrapPolicy() const;
void setRowWrapPolicy(RowWrapPolicy)
QFormLayout::RowWrapPolicy枚举 | 值 | 说明 |
---|---|---|
QFormLayout::DontWrapRows | 0 | 字段始终位于标签旁边,这是除 Qt Extended 样式外的所有样式的默认策略。 |
QFormLayout::WrapLongRows | 1 | 标签获得足够宽的水平空间,以适应最宽的标签,其余空间分配给字段。若“标签,字段”对的最小大小比可用空间大,则字段被换到下一行,这是 QtExtended 样式的默认策略。 |
QFormLayout::WrapAllRows | 2 | 字段始终位于标签下方 |
- 设置和获取部件之间的水平和垂直间距
//属性:horizontalSpacing:int 访问函数:
int horizontalSpacing() const; void setHorizontalSpacing(int);
//属性:verticalSpacing:int 访问函数:
int verticalSpacing() const; void setVerticalSpacing(int);
QFormLayout 类没有设置拉伸因子的函数
插入函数
//构造函数
1. QFormLayout(QWidget* parent = Q_NULLPTR);
//把 label 和 field 添加到末尾
2. void addRow(QWidget* label, QWidget* field);
void addRow(QWidget* labedl , QLayout* field);
//使用 labelText 作为文本创建一个 QLabel,并把其伙伴设置为 field
3. void addRow(const QString& labelText, QWidget* field);
//使用 labelText 作为文本创建一个 QLabel,并把该标签和 field 添加到末尾。
4. void addRow(const QString& labelText, QLayout* field);
//在末尾添加 widget,该部件占两列的宽度
5. void addRow(QWidget* widget);
//在末尾添加 layout,该部件占两列的宽度
void addRow(QLayout* layout);
6. void insertRow(int row, QWidget *label, QWidget* field);
void insertRow(int row, QWidget *label, QLayout* field);
void insertRow(int row, const QString &labelText, QWidget* field);
void insertRow(int row, const QString &labelText, QLayout* field);
void insertRow(int row, QWidget *widget);
void insertRow(int row, QLayout* layout);
QStackedLayout 类(分组布局或栈布局)
实现多页面切换的基本步骤
- 使用 QComboBox(组框)或 QListWidget(列表)之类的部件,提供给用户一个选择需要显示的页面的选项。
- 创建一个容器(比如 QWidget 实例),然后在该容器中添加需要显示给用户的内容。
- 把容器添加到 QStackedLayout 布局中。
- 把 QComboBox 的 activated 信号(或类似信号)与 QStackedLayout 的 setCurrentIndex 槽相关联,以实现当用户选择 QComboBox 中的选项时,显示 QStackedLayout 布局中的子部件。setCurrentIndex 槽的作用就是使 QStackedLayout 布局中的某一个子部件可见。
QStackedLayout 类的核心
- setCurrentIndex(int)和 setCurrentWidget(QWidget*)槽函数
- 要删除布局中的部件,可使用 QLayout::removeWidget()函数,
- 要获取布局中子部件的索引需使用 QLayout::indexOf()函数
QStackedLayout 类中的属性
- count:const int
//QLayout::count()的重新实现,返回布局中的项目数
virtual int count() const;
- currentIndex:int
//槽信号:currentChanged(int index);获取和设置当前部件(即可见部件),若没有当前部件,则索引为−1
int currentIndex() const;
void setCurrentIndex(int index)
- stackingMode:StackingMode
//获取和设置子部件的显示方式,默认为 StackOne。StackingMode 枚举取值如下:
StackingMode stackingMode() const;
void setStackingMode(StackingMode);
- //QStackedLayout::StackOne(值为 0):只有当前部件可见(默认值)
- //QStackedLayout::StackAll(值为 1):所有部件均可见,当前部件只是被提升(即当前部件被提升到其他部件的前面)
QStackedWidget 类
QStackedWidget 类是在 QStackedLayout 之上构造的个便利的部件,其使用方法与步骤和 QStackedLayout 是一样的。QStackedWidget 类的成员函数与 QStackedLayout 类也基本上是一致的,使用该类就和使用 QStackedLayout 一样
QTabBar 类
属性表格
属性名 | 说明 |
---|---|
expanding | 是否扩展选项卡 |
documentMode | 是否以适合主窗口的模式呈现 |
movable | 选项卡是否可移动 |
currentIndex | 获取和设置当前选项卡 |
shape | 描述选项卡的形状 |
elideMode | 选项卡中文本的省略方式 |
count | 获取选项卡的数量 |
autoHide | 选项卡仅 1 个时是否隐藏 |
drawBase | 是否绘制基线 |
usesScrollButtons | 是否使用滚动按钮 |
tabsClosable | 是否显示选项卡上的关闭按钮 |
selectionBehaviorOnRemove | 当删除当前选项卡时,使用哪个选项卡作为当前选项卡 |
iconSize | 选项卡栏中的图标大小 |
changeCurrentOnDrag | 拖动选项卡时,当前选项卡是否会自动更改。 |
QTabWidget 类(选项卡部件)
QTabWidget 的步骤
- 创建一个 QTabWidget。
- 为每个选项卡创建一个页面(容器),通常为 QWidget(不要指定父部件)。
- 把子部件插入到页面部件(即容器)中。
- 使用 addTab()或 insertTab()把页面部件放入选项卡部件。
属性
属性名 | 说明 |
---|
属性名 说明
|count |获取选项卡的数量|
documentMode |是否以适合文档页面的模式呈现
|movable |选项卡是否可移动
|currentIndex |获取和设置当前选项卡
|elideMode |选项卡中文本的省略方式
|tabsClosable| 是否显示选项卡上的关闭按钮
|iconSize |选项卡栏中的图标大小
|usesScrollButtons| 是否使用滚动按钮
函数
把页面部件 page 和具有文本 label 和(或)图标 icon 的选项卡添加到 QTabWidget 部件的末尾或插入到索引 index 处,并返回选项卡栏上该选项卡的
索引。
QTabWidget(QWidget* parent = Q_NULLPTR); //构造函数
int addTab(QWidget* page, const QString &label);
int addTab(QWidget* page, const QIcon &icon, const QString &label);
int insert(int index, QWidget* page, const QString &label);
int insert(int index, QWidget* page, const QIcon &icon, const QString &label);
//移除所有页面,但不删除它们。调用此函数相当于调用 removeTab()函数直到选项卡部件为空。
void clear();
//移除索引 index 处的选项卡,页面不会被删除。
void removeTab(int index);
//返回部件 w 的索引位置,若没有该部件则返回−1 ⑥、QWidget* widget(int index) const; //返回索引 index 处的页面部件。
int indexOf(QWidget* w) const;
//返回指向当前页面部件的指针。
QWidget* currentWidget() const;
//槽,把 widget 设置为当前页面(可见页面)。 ⑧、QTabBar* tabBar() const; //返回当前的
void setCurrentWidget(QWidget* widget);
//受保护的。
void setTabBar(QTabBar* tb);
角落部件
QWidget* cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const;
//返回角落 corner 处的小部件或 0。
void setCornerWidget(QWidget* widget, Qt::Corner corner = Qt::TopRightCorner);
- 右上角的button
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Ha3xox1-1632751916586)(./pic/conerWdight.png)]
QTabWidget 类
状态使能失能
void setTabEnabled(int index, bool enabled); //设置选项卡的启用/禁用状态,禁用状态呈现出灰色。
bool isTabEnabled(int index) const; //获取选项卡的启用/禁用状态
设置图标函数
void setTabIcon(int index, const QIcon& icon); //设置选项卡的图标
QIcon tabIcon(int index) const; //获取选项卡的图标。
选项卡文本
void setTabText(int index, const QString &text); //设置选项卡的文本
QString tabText(int index) const; //获取选项卡的文本。
选项卡提示文本
void setTabToolTip(int index, const QString &tip); //设置选项卡的提示文本
QString tabToolTip(int index) const; //获取选项卡的提示文本。
帮助文本
void setTabWhatsThis(int index, const QString &text); //设置选项卡的帮助文本
QString tabWhatsThis(int index) const; //获取选项卡的帮助文本。
QTabWidget 类中的信号
void currentChanged(int index); //信号当选项卡栏上的当前选项卡发生更改时发送此信号,index 为新选项卡的索引,若没有新的索引,则为−1(比如 QTabBar 中没有选项卡)。该信号比较重要。
void tabBarClicked(int index); //信号,qt5.2
void tabBarDoubleClicked(int index); //信号,qt5.2
以上信号表示,单击或双击 index 处的选项卡时发送此信号,index 是单击选项卡的索引,若光标下没有选项卡,则为−1。
void tabCloseRequested(int index); //信号当点击选项卡上的关闭按钮时发送此信号,index 为应删除的选项卡的索引。
QSplitter 类(分离器)
QSplitter 的原理(见上图)
- QSplitter 的实现原理与 QBoxLayout 布局的原理类似,即 QSplitter把子部件以水平或垂直的方式添加到 QSplitter 中,只不过在这些子部件之间多了一条分界线
-QSplitter 类继承自 QFrame 类,也就是说该类是一个带有边框的可视部件
分界线
- 分界线的创建:分界线是由 QSplitterHandle 类实现的,QSplitter 类本身不实现分界线。因此 QSplitterHandle 是一个部件,而 QSplitter 是另一个部件,这是两个部件,只不过这两个部件通过 Qt 的内部设计,让他们关联在一起,产生了一定的联系。
- 背景色:QSplitter 的分界线默认有可能是看不见的(因为颜色与 QSplitter 背景色相同,所以看不见),因此要使分界线可见,需设置分界线的背背色。
- 分界线的索引:其索引从 0 开始编号,分界线的数量与子部件的数量一样多。但索引为 0 的分界线始终是隐藏的。对于垂直分离器,索引为 0 的子部件上方的分界线索引为 0,对于水平水界面(对于从左到右的语言),则索引为 0 的子部件左侧的分界线的索引为 0,对于从右到左的语言,则索引为 0 的子部件右侧的分界线的索引为 0。
-
动态调整:是指移动分界线时部件大小随之动态的改变,若不是动态调整的,则在移动分界线时部件大小不会改变,当完成分界线的移动时(即松开鼠标时),部件的大小才改变
-
分离器的特点:分离器中的子部件分随着分离器大小的改变而改变,当分离器大小改变时,分离器会重新分配空间,以使其所有子部件的相对大小保持相同的比例不变。
-
子部件的大小策略对分离器不起作用,分离器会把子部件填充满整个空间,即使子部件的大小策略设置为 Fixed,仍会被拉伸。
使用 QSplitter 的步骤如下:
- 创建一个 QSplitter。
- 使用 addWidget()函数把子部件添加到 QSplitter 中。
QSplitter 类的属性
- 折叠属性
childrenCollapsible:bool
访问函数:
bool childrenCollapsible() const;
void setChildrenCollapsible(bool);
- 子部件是否可以被折叠(即调整到 0 的大小),默认为可折叠。
- 若部件可折叠,即使该部件的最小大小(minimumSize())不为零,用户也可将其大小调整为 0。
- 设置该属性会作用于所有子部件上,使用函数 setCollapsible()可设置单个子部件是否可折叠。
- 分界线宽度
//handleWidth:int 访问函数:
int handleWidth() const;
void setHandleWidth(int);
- 部件是否动态调整,分界线是否是不透明的
opaqueResize:bool
//访问函数:
bool opaqueResize() const;
void setOpaqueResize(bool opaque = true);
- 设置QSplitter的方向
orientation:Qt::Orientation
访问函数:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation);
//可取值为Qt::Horizontal 和Qt::Vertical。
设置分隔条为蓝色
ps->setStyleSheet("QSplitter::handle{background-color: blue}");
QSplitterHandle 类(分界线)
- 承自 QWidget,该类主要用于实现 QSplitter(分离器)的分界线,因此,通常与分离器一起使用。
函数
QSplitterHandle(Qt::Orientation orientation, QSplitter* parent); //构造函数
QSplitter* splitter() const; //获取与此分界线关联的分离器
void setOrientation(Qt::Orientation orientation); //设置分界线的方向
Qt::Orientation orientation() const; //返回分界线的方向
bool opaqueResize() const; //设置是否不透明(动态调整),该值由 QSplitter 控制。
焦点
焦点循环:在使用 tab 键移动焦点时,焦点会在各部件之间循环移动。因此可使用一个循 环链表的结构来管理焦点,该链表称为焦点链。
1. //返回此部件焦点链中的下一个部件
QWidget* QWidget::nextInFocusChain() const;
2. //返回此部件焦点链中的前一个部件
QWidget* QWidget::previousInFocusChain() const;
3. //将焦点顺序中的部件 second 放置在部件 first 之后,该函数把部件 second 从其焦点链中移除,并插入在部件 first 之后
static void QWidget::setTabOrder(QWidget* first, QWidget* second);
获取焦点
//返回该部件(比如作为窗口的部件,该窗口不一定要处于激活状态)中**最后一次获得焦点的子部件**,对于顶级窗口,这是在窗口激活时,将获得焦点的部件。
QWidget* QWidget::focusWidget() const;
//静态,返回当前活动窗口中具有焦点的部件。
2、static QWidget* QApplication::focusWidget();
//QWidget 类中的属性部件是否具有焦点,获取此属性的值,相当于检查 QApplication::focusWidget()是否指向该部件。默认为 false。
3、focus:const bool 访问函数:bool hasFocus() const;
//QWidget 类中的属性该部件的窗口是否是活动窗口,默认为 false。
4、isActiveWindow:const bool 访问函数:bool isActiveWindow() const;
//把包含此部件的顶级部件设置为活动窗口
5、void QWidget::activateWindow();
焦点代理
- 类似于标签和行编辑器之间的伙伴关系;如部件 2 是部件 1 的焦点代理,则当部件 1获得焦点时,实际获得并处理焦点的是部件 2。
有关的函数
//返回该部件的焦点代理,若没有代理则返回 0。
①、QWidget* QWidget::focusProxy() const;
// 此部件的焦点代理设置为部件 w;若 w 为 0,则重置该部件为没有焦点代理
②、void QWidget::setFocusProxy(QWidget* w);
设置焦点及焦点策略 focusPolicy
-焦点策略:焦点策略描述了部件接受焦点的方式(比如可通过 tab 接受焦点,可通点鼠标滚轮接受焦点等)。
函数
// 属性
focusPolicy:Qt::FocusPolicy //QWidget 类中的属性
//访问函数:
//获取和设置焦点策略,若该部件拥有焦点代理,则焦点策略会传递给焦点代理
Qt::FocusPolicy focusPolicy()const;
void setFocusPolicy(Qt::FocusPolicy);
Qt::FocusPolicy 枚举
成员 | 值 | 说明 |
---|---|---|
Qt::TabFocus | 0x1 | 通过 tab 键接受焦点 |
Qt::ClickFocus | 0x2 | 通过鼠标点击接受焦点 |
Qt::StrongFocus | TabFocus | ClickFocus | 0x8 | 通过 tab 和鼠标点击接受焦点。 |
Qt::WheelFocus | StrongFocus | 0x4 | Qt::StrongFocus + 可使用鼠标滚轮接受焦点 |
Qt::NoFocus | 0 不接受焦点 |
设置焦点
// 若此部件或其父部件之一是活动窗口,则为此部件(或其焦点代理)设置焦点。若窗口不是活动的,则当窗口 变为活动时,部件将获得焦点。
void QWidget::setFocus(); //槽
void QWidget::setFocus(Qt::FocusReason reason);
焦点事件 QFocusEvent
void QWidget::focusOutEvent(QFousEvent* event);
void QWidget::focusInEvent(QFocusEvent* event);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HdkpMYHR-1632751916587)(./pic/focusReason.png)]
自定义焦点循环
虚函数
bool QWidget::focusNextPrevChild(bool next) ; //虚拟的,受保护的查找为 Tab 和 Shift+Tab 键提供焦点的部件,若找到则返回 true,若未找到则返回 false。若参数 next 为 true,则向前搜索,若为 false 则向后搜索。重新实现该函数,可以控制所有子部件的焦点循环。
QFocusFrame 类
- QFocusFrame 类直接继承自 QWidget 类。
QFocusFrame 类中的函数
// ①、构造函数
QFocusFrame(QWidget* parent = Q_NULLPTR);
// ②、把部件 w 的焦点框设置为此焦点框
void setWidget(QWidget* w);
// ③、返回部件拥有的焦点框
QWidget* widget() const; 。
Qt主窗口
需要在pro文件添加 QT+=widgets 语句。
-
类继承结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7ZspnXr-1632751916587)(./pic/class_widght.png)] -
主窗口包含内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cy78jFDq-1632751916588)(./pic/mainwindow.png)] -
说明
- 中心部件:主窗口必须有且只能有一个中心部件。中心部件可以是任意类型的部件(比 如 QTextEdit、QLineEDit 等)。中心部件使用 **setCentralWidget()**函数设置
- 状态栏:状态栏主要用于向向户显示一些程序的状态信息,状态栏位于主窗口底部,一个主窗口只能有一个状态栏。使用** setStatursBar()**函数可设置状态栏。
- 工具栏:工具栏通常是由一系列的类似按钮的部件组成的。使用 addToolBar()可以把工具栏添加到主窗口。工具栏是由 QToolBar 类实现的。一个主窗口可以有多个工具栏,工具栏可以位于主窗口的上、下、左、右四个方向上。
- Dock 部件(悬浮窗口、可停靠窗口):一个主窗口可以有多个可停靠窗口。使用**addDockWidget()**可以把可停靠窗口添加到主窗口
- 菜单与菜单栏:菜单位于菜单栏之中,一个主窗口只能有一个菜单栏,一个菜单栏中可以包含多个菜单。QMainWindow 有一个默认的菜单栏,该菜单栏使用 menuBar()
函数返回。
菜单
-
QMenu 和 MenuBar 类都继承自 QWidget,可见,他们其实就是一个 QWidget 部件,只不过他们有些特殊的限制
-
QMenu 类可用于创建菜单,该类可创建单独的一个菜单项,并可使用 QMenu::addMenu()函数把一个菜单项添加到另一个菜单项中,从而创一个子菜单。
-
QMenuBar 是菜单栏,使用 QMenu 创建的菜单通常会添加到菜单栏中。使用QMenuBar::addMenu()函数可把菜单添加到菜单栏之中。
函数
- 添加菜单 menu 到菜单栏或菜单中,并返回与此菜单关联的 Action(动作)。此函数不会使菜单或菜单栏拥有 menu 的所有权(关于所有权,见后文)。
QAction* addMenu(QMenu *menu);
- 使用 title 和 icon 创建一个新菜单,并把其添加到菜单或菜单栏,并返回该新菜单,菜单栏或菜单拥有该新菜单的所有权
QMenu* addMenu(const QString &title);
QMenu* addMenu(const QIcon& icon, const QString &title);
- 部件的所有权
所有权的意义:比如部件 1 若拥有部件 2 的所有权,则当部件 1 被删除(销毁)时,会删除部件 2。
QAction动作类
QAction 还可以包含有图标、文本、快捷方式、状态文字、What this 文字和工具提示。其中 QAction 的文本通常用作菜单的文本
使用 QAction 需要完成以下关键步骤:
- 把 QAction 对象使用 QWidget::addAction()函数添加到部件。必须把 QAtion 添加到部件才能使用。
- 把 QAction 的 triggered()信号连接到需要执行的槽函数。
- 激活 QAction。
- 若已把 QAction 添加到菜单中,则直接点击该菜单项即可;
- 若 QAction 含有快捷键,则直接使用快捷键便可激活 QAction;
- 若 QAction 是添加到某个 QWidget 部件的(比如 QPushButton),则可以把该部件的某个信号连接到 QAction::trigger()槽或 QAction::triggered()信号,来激活QAction。
QShortcut 类(快捷键)
快捷键的实现原理:
首先使用指定的 QKeySequence(键序列)创建一个快捷键 QShortcut,然后把 QShortcut::activated()信号(激活快捷键时会发送此信号)关联到需要执行的槽函数即可
QShortcut 类中的属性
- 描述快捷键是否可自动重复
autoRepeat:bool
bool autoRepeat() const;
void setAutoRepeat(bool);
- 快捷键的激活方式
context:Qt::ShortcutContext
Qt::ShortcutContext context() const;
void setContext(Qt::ShortcutContext)
Qt::ShortcutContext 枚举
成员 | 值 | 说明 |
---|---|---|
Qt::WidgetShortcut | 0 | 当父部件拥有焦点时,快捷键被激活。 |
Qt::WidgetWithChildrenShortcut | 3 | 当父部件或其子部件拥有焦点时,快捷键可被激活。 |
Qt::WindowShortcut | 1 | 当父部件是活动顶层窗口的逻辑子部件时,快捷键是活动的。 |
Qt::ApplicationShortcut | 2 | 当其中一个应用程序窗口处于活动状态时,快捷键是活动的。 |
- 描述是否启用快捷键 enabled:bool
bool isEnabled() const;
void setEnabled(bool);
- 获取和设置键序列 key:QKeySequence
QKeySequence key() const;
void setKey(const QKeySequence&);
- 描述快捷键的 What’s This 帮助文本 whatsThis:QString
QString whatsThis() const;
void setWhatsThis( const QString&);
信号:
void actived()
QKeySequence 类(键序列)
QActionGroup 类(动作组)
在同一个动作组中的动作是互斥的,任何时候只有一个动作是活动的
QMenu 类中的函数
- 单中添加和插入菜单项、分隔符的函数
QAction* addAction(const QString &text);
QAction* addAction(const QIcon& icon, const QString &text);
QAction* addAction(const QString &text, const QObject* receiver, const char* member,
const QKeySequence& shortcut = 0);
QAction* addAction(const QIcon& icon, const QString &text, const QObject* receiver,
const char* member, const QKeySequence& shortcut = 0);
QAction* addAction(const QString &text, const QObject* receiver,PointerToMemberFunction method,
const QKeySequence& shortcut = 0); //qt5.6
QAction* addAction(const QIcon &icon, const QString &text, const QObject* receiver,
PointerToMemberFunction method,const QKeySequence& shortcut = 0); //qt5.6
QAction* addAction(const QString &text, Functor functor, const QKeySequence& shortcut = 0); //qt5.6
QAction* addAction(const QString &text, const QObject* context,Functor functor,
const QKeySequence& shortcut = 0); //qt5.6
QAction* addAction(const QIcon& icon, const QString &text, Functor functor,
const QKeySequence& shortcut = 0); //qt5.6
QAction* addAction(const QIcon& icon, const QString &text, const QObject* context,Functor functor,
const QKeySequence& shortcut = 0); //qt5.6
- text:动作的文本,菜单项会显示该文本。
- icon:动作的图标,图标会显示在菜单项的左侧。
- receiver、member、method:表示用于接收动作 triggered()信号的对象和槽函数。其中 member 需使用 SLOT 宏指定,method 可直接使用成员函数的地址指定,其用法与 QObject::connect()函数相同。
- shortcut:表示该动作的快捷键。
- functor:表示用于接收动作 triggered()信号函数,只是该参数支持全局函数、静态
函数等
工具栏属性
设置工具栏可以被放置在哪些区域
描述工具栏是否可以作为独立的窗口(浮动状态)。
工具栏中的图标大小,默认大小取决于样式
描述工具栏是否可在工具栏区域或工具栏区域之间移动,
描述工具栏的方向,
描述把 QAction 添加到工具栏上时工具按钮的样式(即工具栏的图标和文本应如何显示),
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUH8cO6F-1632751916589)(./pic/toolbartstyle.png)]
QToolBar 类中的信号
激活信号
void actionTriggered(QAction* action); //信号
位置变化信号 void allowedAreasChanged(Qt::ToolBarAreas allowedAreas); //信号
图标大小变化信号void iconSizeChanged(const QSize& iconSize); //信号
移动信号 void movableChanged(bool movable); //信号
方向变化信号 void orientationChanged(Qt::Orientation orientation); //信号
样式改变信号 void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle); //信号
浮动变化信号 void topLevelChanged(bool topLevel); //信号
可见/不可见信号 void visibilityChanged(bool visible); //信号
QStatusBar 类(状态栏)
QStatusBar 类继承自 QWidget
主窗口(QMainWindow)只能有一个状态栏。使用 QMainWindow::setStatursBar()函数可设置状态栏
- 临时信息 setStatusTip()函数设置的信息
- 正常信息 正常信息通过一个 QWidget 部件来进行显示(比如 QLabel、QProgressBar 等),可使用 **QStatusBar::addWiget()**函数向状态栏添加这些部件
- 永久信息:永久信息显示在状态栏的最右侧,息也通过一个 QWidget 部件来进行显示(比如 QLabel、QProgressBar 等),可使用** QStatusBar::addPermanentWidget()**函数向状态栏添加这些部件
状态栏属性
sizeGripEnabled:bool 访问函数:
bool isSizeGripEnabled() const;
void setSizeGripEnabled(bool);
描述是否启用右下角的大小夹点(QSizeGrip),默认为启用
浮动窗口 QDockWidget 类
- 可停靠窗口允许放置的区域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAawwy4T-1632751916590)(./pic/dockwidghtarea.png)] - 描述可停靠窗口的特征,即,是否可移动、关闭、悬浮等
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e5nqhb9k-1632751916591)(./pic/dockwidghtfeature.png)] - 可停靠窗口的浮动状态
- 可停靠窗口的标题
Qt QPainter绘图
QPainter 类中绘制图像的函数
表示在位置 point 或矩形 rectangle 内绘制图像 image。若图像和矩形大小不一致,图像将缩放以适应其大小
void drawImage(const QRectF &rectangle, const QImage &image)
void drawImage(const QRect &rectangle, const QImage &image)
void drawImage(const QPointF &point, const QImage &image)
void drawImage(const QPoint &point, const QImage &image)
把图像 image 的一部分图像(由 source 指定)绘制到绘制设备的位置 point 或矩形 target 内。
void drawImage(const QRectF &target, const QImage &image, const QRectF &source,
Qt::ImageConversionFlags flags = Qt::AutoColor)
void drawImage(const QRect &target, const QImage &image, const QRect &source,
Qt::ImageConversionFlags flags = Qt::AutoColor)
void drawImage(const QPointF &point, const QImage &image, const QRectF &source,
Qt::ImageConversionFlags flags = Qt::AutoColor)
void drawImage(const QPoint &point, const QImage &image, const QRect &source,
Qt::ImageConversionFlags flags = Qt::AutoColor)
void drawImage(int x, int y, const QImage &image, int sx = 0, int sy = 0, int sw = -1, int sh = -1,
Qt::ImageConversionFlags flags = Qt::AutoColor)
在位置 point 绘制图片 picture
void drawPicture(const QPointF &point, const QPicture &picture);
void drawPicture(const QPoint &point, const QPicture &picture);
void drawPicture(int x, int y, const QPicture &picture);
示在位置 point 或矩形 rectangle 内绘制像素图 pixmap
void drawPixmap(const QPointF &point, const QPixmap &pixmap);
void drawPixmap(const QPoint &point, const QPixmap &pixmap);
void drawPixmap(int x, int y, const QPixmap &pixmap);
void drawPixmap(const QRect &rectangle, const QPixmap &pixmap);
void drawPixmap(int x, int y, int width, int height, const QPixmap &pixmap);
把像素图 pixmap 的矩形部分(由 source 指定)绘制到位置 point 或目标矩形target 内。若图像和矩形大小不一致,图像将缩放以适应其大小
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source);
void drawPixmap(const QRect &target, const QPixmap &pixmap, const QRect &source);
void drawPixmap(int x, int y, int w, int h, const QPixmap &pixmap, int sx, int sy, int sw, int sh);
void drawPixmap(const QPointF &point, const QPixmap &pixmap, const QRectF &source);
void drawPixmap(const QPoint &point, const QPixmap &pixmap, const QRect &source);
void drawPixmap(int x, int y, const QPixmap &pixmap, int sx, int sy, int sw, int sh);
在矩形 rectangle 内绘制一个平铺像素图,其原点位于 position,原点是指 pixmap 左上角的位置
void drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap,
const QPointF &position = QPointF());
void drawTiledPixmap(const QRect &rectangle, const QPixmap &pixmap,
const QPoint &position = QPoint());
void drawTiledPixmap(int x, int y,int width, int height,const QPixmap &pixmap, int sx=0,int sy=0);
- 把像素图 pixmap 拆分为 fragmentCount 个像素图片段 fragments,并以不同比例、旋转和透明度等在多个位置绘制这些像素图片段。
- 该函数比多次调用 drawPixmap()更快
void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount,
const QPixmap &pixmap, PixmapFragmentHints hints = PixmapFragmentHints());
图像的抗锯齿
函数
//设置渲染提示。RenderHint 枚举见下表
void setRenderHint(RenderHint hint, bool on = true)
void setRenderHints(RenderHints hints, bool on = true)
//返回渲染提示
RenderHints renderHints() const
//若设置了 hint 则返回 t
bool testRenderHint(RenderHint hint) const
- QPainter::RenderHint 枚举
| 成员 | 值 | 说明 |
| ------------------------------- | ---- | -------------------------------------------------------------------------------------- |
| QPainter::Antialiasing | 0x01 | 若可能,则启用抗锯齿处理 |
| QPainter::TextAntialiasing | 0x02 | 若可能,则文本启用抗锯齿。 |
| QPainter::SmoothPixmapTransform | 0x04 | 表示使用平滑的像素图像变换算法(如双线性) QPainter::HighQualityAntialiasing 0x08 已过时 |
| QPainter::NonCosmeticDefaultPen | 0x10 | 已过时 |
| QPainter::Qt4CompatiblePainting | 0x20 | 用于与 Qt4 相兼容 |
绘图
- QPainter(绘制器)是用来执行绘图的操作,用于描述需要绘制的图形比如需要绘制线、矩形、圆形等。
- QPaintDevice(绘图设备)是抽象出来的需要绘制的绘图设备,即可以在什么上面绘制图形,比如可在 QWidget、QImage、QPrinter 等上面绘图
QPainter 绘制图形的步骤
- 创建一个 QPainter 对象
- 调用QPainter::begin(QPaintDevice *);指定绘图设备并开始绘制,此步骤也可在 QPainter的构造函数中完成。注意:每次调用begin()函数都会把QPainter 的设置重置为默认值。
- 调用 QPainter 的成员函数绘制图形,调用 QPainter::end()结束绘制。
- 若绘制设备是一个 QWidget 部件,则 QPainter**只能在 paintEvent()**处理函数中使用(即,需要子类化 QWidget 部件,并重新实现该函数)。
划线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KwlFEATh-1632751916591)(./pic/drawLine.png)]
QLineF 类
函数
角度和长度
qreal angle() const; //返回直线的角度,范围为 0~359 度
void setAngle(qreal angle)
qreal length() const;
void setLength(qreal length)
qreal angleTo(const QLineF &line) const; //该线需要旋转多少度才与线 line 的度数相同(注意,这不
是指的两线相交的角度
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1SvyubLR-1632751916592)(./pic/line_angle.png)]
- 相垂直的线
QPointF pointAt(qreal t) const; //返回位于直线上 t*length()处的点。
QLineF normalVector() const; //返回与此线有相同起点和长度并与该线垂直的线
QLineF unitVector() const; //返回与此线有相同起点和方向,长度为 1.0 的线,即单位向量。
- 相交
IntersectType intersect(const QLineF &line, QPointF *intersectionPoint) const
QLineF::IntersectType 枚举(无标志)
作用:两线相交的类型
成员 | 值 | 说明 |
---|---|---|
QLineF::NoIntersection | 0 | 两线不相交(即平行)。 |
QLineF::UnboundedIntersection | 2 | 两线相交,但交点不位于两条线之上 |
QLineF::BoundedIntersection | 1 | 两线相交,交点位于两条线之上。 |
- 偏移
void translate(const QPointF &offset);
void translate(qreal dx, qreal dy);
//translated()不会改变原直线,但会返回一个偏移后的副本
QLineF translated(const QPointF &offset) const
QLineF translated(qreal dx, qreal dy) const
- 中点
QPointF center() const; //返回该线的占点
步骤
- 创建一个 QPainter 对象
- 调用QPainter::begin(QPaintDevice *);指定绘图设备并开始绘制,此步骤也可在 QPainter的构造函数中完成。注意:每次调用begin()函数都会把QPainter 的设置重置为默认值。
- 调用 QPainter 的成员函数绘制图形,调用 QPainter::end()结束绘制。
- 若绘制设备是一个 QWidget 部件,则 QPainter**只能在 paintEvent()**处理函数中使用(即,需要子类化 QWidget 部件,并重新实现该函数)。
划线
[外链图片转存中…(img-KwlFEATh-1632751916591)]
QLineF 类
函数
角度和长度
qreal angle() const; //返回直线的角度,范围为 0~359 度
void setAngle(qreal angle)
qreal length() const;
void setLength(qreal length)
qreal angleTo(const QLineF &line) const; //该线需要旋转多少度才与线 line 的度数相同(注意,这不
是指的两线相交的角度
[外链图片转存中…(img-1SvyubLR-1632751916592)]
- 相垂直的线
QPointF pointAt(qreal t) const; //返回位于直线上 t*length()处的点。
QLineF normalVector() const; //返回与此线有相同起点和长度并与该线垂直的线
QLineF unitVector() const; //返回与此线有相同起点和方向,长度为 1.0 的线,即单位向量。
- 相交
IntersectType intersect(const QLineF &line, QPointF *intersectionPoint) const
QLineF::IntersectType 枚举(无标志)
作用:两线相交的类型
成员 | 值 | 说明 |
---|---|---|
QLineF::NoIntersection | 0 | 两线不相交(即平行)。 |
QLineF::UnboundedIntersection | 2 | 两线相交,但交点不位于两条线之上 |
QLineF::BoundedIntersection | 1 | 两线相交,交点位于两条线之上。 |
- 偏移
void translate(const QPointF &offset);
void translate(qreal dx, qreal dy);
//translated()不会改变原直线,但会返回一个偏移后的副本
QLineF translated(const QPointF &offset) const
QLineF translated(qreal dx, qreal dy) const
- 中点
QPointF center() const; //返回该线的占点