Qt学习笔记

元对象

  1. 要在 Qt Creator 中启动元对象系统,包含 Q_OBJECT 宏的类的定义必须位于头文件中,否则 moc 工具不能生成元对象代码

  2. 若定义了 QObject 类的派生类,并进行了构建,在这之后再添加 Q_OBJECT 宏,则此时必须执行一次 qmake 命令(“构建”>“执行 qmake”),否则 moc 不能生成代码

  3. 要使用元对象系统的功能,需要满足以下三个条件:

  • 该类必须继承自 QObject 类。
  • 必须在类声明的私有区域添加 Q_OBJECT 宏,该宏用于启动元对象特性,然后便可使用动态特性、信号和槽等功能了。
  • *元对象编译器(moc)为每个 QObject 的子类,提供实现了元对象特性所必须的代码
  1. 多重继承时 QObject 必须位于基类列表中的第一位
  2. QMetaObject 类描述了 QObject 及其派生类对象的所有元信息,QMetaObject 类的对象是 Qt 中的元对象。
  3. 成员进行描述
  • 函数成员使用类QMetaMethod 进行描述
  • 属性使用 QMetaProperty 类进行描述等,
  • 使用QMetaObject 类对整个类对象进行描述

使用 Qt 反射机制的条件

  1. 需要继承自 QObject 类,并需要在类之中加入 Q_OBJECT 宏。
  2. 注册成员函数:若希望普通成员函数能够被反射,需要在函数声明之前加入QObject::Q_INVOKABLE 宏。
  3. 注册成员变量:若希望成员变量能被反射,需要使用 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. 形式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
  1. 形式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));
  1. 形式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 );
  1. 形式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 关键字原型

  1. 在以上关键字上右击然后按下 F2,在 qobjectdefs.h 文件中可以看到这些关键字的原型
  2. signals 关键字:最终被#define 置换为一个访问控制符,其简化后的语法为#define signals public
  3. slots 关键字:最终被#define 置换为一个空宏,即简化后的语法为:#define slots
  4. emit 关键字:同样被#define 置换为一个空宏,即简化后为:#define emit
  5. 由以上各关键字原型可见,使用 emit 发射信号,其实就是一个简单的函数调用

事件

继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6OPOzmIU-1632751916577)(./pic/application.png)]

  1. QCoreApplication:主要提供无 GUI 程序的事件循环。
  2. QGuiApplication:用于管理 GUI 程序的控制流和主要设置。
  3. QApplication 专门为 QGuiApplication 提供基于 QWidget 的程序所需的一些功能
    1. 初始化应用程序
    2. 执行事件处理
    3. 解析常用命令行参数
    4. 定义了应用程序的界面外观,可使用 QApplication::setStyle()进行更改
    5. 使用 QCoreApplication::translate()函数对字符串进行转换。
    6. 通过 QApplication::desktop()函数处理桌面,通过 QCoreApplication::clipboard()函数处理剪贴板。
    7. 管理应用程序的鼠标光标

Qt 事件event

  • 继承关系
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KH1wsSvL-1632751916580)(./pic/event.png)]

事件和信号的区别

  1. 他们两个是不同的概念,不要弄混淆。信号是由对象产生的,而事件则不一定是由对象产生的(比如由鼠标产生的事件),事件通常来自底层的窗口系统,但也可以手动发送自定义的事件,可见信号和事件的来源是不同的。
  2. 事件既可以同步使用,也可以异步使用 (取决于调用 sendEvent()还是 postEvents()),而使用信号和槽总是同步的。事件的另一个好处是可以被过滤。
  • QEvent::accept()函数表示接受一个事件,使用 QEvent::ignore()函数表示忽略一个事件。
  • QCloseEvent(关闭事件)有一些不同,QCloseEvent::ignore()表示取消关闭操作,而QCloseEvent::accept()则表示让 Qt 继续关闭操作。

Qt 实现事件过滤器的步骤如下:

  1. 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::NoButton0x0000 0000按钮状态不指向任何按钮。
Qt::LeftButton0x0000 0001按下左键
Qt::RightButton0x0000 0002按下右键
Qt::MidButton 或 Qt::MiddleButton0x0000 0004 按下中键

鼠标和键盘事件共同使用的类及函数

  1. 通过调用从 QInputEvent::modifiers()函数可以查询键盘修饰键的状态。
  2. 使用 QWidget::etEnable()函数可以启用或禁用部件的鼠标和键盘事件。
  3. 键盘修饰键(即 Ctrl、Alt、Shift 等键)使用枚举类型 Qt::KeyboardModifier 来描述,其取值如下表
枚举值说明
Qt::NoModifier0x0000 0000无修饰键被按下
Qt::ShiftModifier0x0200 0000按下 Shift 键
Qt::ControlModifier0x0400 0000按下 Ctrl 键
Qt::AltModifier0x0800 0000按下 Alt 键
Qt::MetaModifier0x1000 0000按下 Meta 键(windows 系统为 windows 键)
Qt::KeypadModifier0x2000 0000按下小键盘上的键
Qt::GroupSwitchModifier0x4000 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 类

  1. QEvent(Type type) //构造函数,用于创建自定义事件

  2. virtual ~QEvent() //析构函数

  3. void accept() //接受事件

  4. void ignore() //忽略事件

  5. void setAccepted(bool a) //设置是否接受事件

  6. Type type() const //返回事件的类型

  7. static int registerEventType(int hint=-1):
    注册并返回自定义事件类型,使用该函数的返回值可保证自定义的事件不会有重复的 Type 枚举值。

  8. enum Type{None, ActionAdded, … Keypress,…} //定义事件的类型,详见帮助文档

QObject 类

  1. virtual bool event() //接收并处理事件,先于默认的事件处理函数
  2. void installEventFilter(QObject *finterObj); //安装(或注册)事件过滤器
  3. vitrual bool eventFilter(QObject* w , QEvent *e ) //用于接收并处理事件过滤器对象接收的事件。
  4. void removeEventFilter(QObject* obj); //移除事件过滤器。

QCoreApplication 类

  1. virtual bool notify(QObject* r, QEvent* e) //该函数用于分发事件
  2. int exec(); //使用该函数进入事件主循环。
  3. void postEvent(QObject* r, QEvent* e, int priority=Qt::NormalEventPriority); //用于发布自定义事件
  4. bool sendEvent(QObject* r, QEvent *e); //用于发送自定义事件

QWidget 类

  1. void grabKeyboard() //捕获键盘输入
  2. void grabMouse() //捕获鼠标输入
  3. void grabMouse(const QCursor& c); //捕获鼠标输入
  4. QWidget* keyboardGrabber(); //返回捕获键盘输入的部件
  5. QWidget* mouseGrabber(); //返回捕获鼠标输入的部件
  6. void releaseMouse() //释放捕获的鼠标输入
  7. void releaseKeyboard() //释放捕获的键盘输入。
  8. bool hasMouseTracking() const; //是否启用鼠标跟踪
  9. void setMouseTracking(bool enable) //设置鼠标跟踪状态
  10. bool underMouse() const; //部件是否位于鼠标光标之下
  11. void setAttribute ( Qt::WidgetAttribute attribute, bool on=true); //设置是否启用键压缩。
  12. 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 是用于描述由布局管理的项目的抽象类
  1. 由 QHBoxLayout 类实现的水平布局,效果如下图
  2. 由 QVBoxLayout 类实现的垂直布局,效果如下图
  3. 由 QGridLayout 类实现的二维网格布局,效果如下图
  4. 由 QFormLayou 实现的两列表格布局,效果如下图
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fip3dBs1-1632751916585)(./pic/layout_class.png)]

Qt 使用布局管理器的步骤为,

  1. 首先创建一个布局管理器类的对象
  2. 然后使用该布局管理器类中的 addWidget()函数,把需要由布局管理器管理的部件添加进来。还可使用 addLayout()函数把其他布局管理器添加进来。
  3. 最后使用 QWidget::setLayout()函数为窗口设置布局管理器。

说明:

**

  1. 若为布局指定了父部件,则可以不使用 QWidget::setLayout()函数反之,调用QWidget::setLayout()函数安装布局,则可以不为该布局指定父部件。
  2. 不需要为添加到布局中的部件指定父部件,布局中的部件会自动成为安装布局的部件的子部件(使用 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::SetDefaultConstraint0把主窗口的最小大小设置为 QLayout::minimumSize(),除非主窗口已经具有最小大小,也就是说若主窗口已显示设置了最小大小,则此约束不会再使用 QLayout::minimumSize()设置主窗口的最小大小。这是默认值
QLayout::SetFixedSize3主窗口的大小设置为 sizeHint();此时主窗口大小无法被调整,通常使用此约束使主窗口自动适应所布置的部件的大小。
QLayout::SetMinimumSize2把主窗口的最小大小设置为 QLayout::minimumSize(),主窗口不能调整为比该大小更小。
QLayout::SetMaximumSize4把主窗口的最大大小设置为 QLayout::maximumSize(),主窗口不能调整为比该大小更大。
QLayout::SetMinAndMaxSize5把主窗口的大小设置为QLayout::minimumSize()~QLayout::maximumSize()
QLayout::SetNoConstraint1不对主窗口的大小进行设置(即没有约束),也就是说,保持主窗口之前的最大和最小大小,不对其进行更改。

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

  1. 把大小为 size 的不可拉伸间距(QSpacerItem)添加到布局的末尾。
void QBoxLayout::addSpacing(int size);
  1. 在索引 index 处,插入大小为 size 的不可拉伸间距(QSpacerItem)。若索引为负,则在最后添加空格。
void QBoxLayout::insertSpacing(int index, int size);
  1. 把具有零最小大小和拉伸因子为 strecth 的可拉伸间距(QSpacerItem)添加到布局的末尾。

void QBoxLayout::addStretch(int strecth = 0);
  1. 在索引 index 处,插入最小大小为 0,拉伸因子为 stretch 的可拉伸间距(QSpacerItem)。若索引为负,则在最后添加空格。
void QBoxLayout::insertStretch(int index, int stretch =0);
  1. 在索引 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::LeftToRight0水平从左到右
QBoxLayout::RightToLeft1水平从右到左
QBoxLayout::TopToBottom2垂直从上到下
QBoxLayout::BottomToTop3垂直从下到上

函数介绍

  1. QBoxLayout(Direction dir, QWidget* parent = Q_NULLPTR); //构造一个方向为 dir 的盒式布局
  2. 把布局layout添加到末尾或在指定索引index处插入布局,并设置其拉伸因子为stretch, 若 index 为负,则添加到末尾。
   void addLayout(QLayout* layout, int stretch = 0);
   void insertLayout(int index, QLayout* layout, int stretch = 0);
  1. 把部件 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());
  1. 在末尾添加或在索引 index 处插入大小为 size 的不可拉伸间距(QSpacerItem)。若索引
    为负,则添加到末尾。
void addSpaceing(int size); 
void insertSpacing(int index, int size);
  1. 在末尾添加或在索引 index 处,插入最小大小为 0,拉伸因子为 stretch 的可拉伸间距
    (QSpacerItem)。若索引为负,则添加到末尾。
void addStretch(int stretch = 0);
void insertStretch(int index, int stretch = 0);
  1. 在末尾添加或在索引 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);
  1. //返回索引为 index 的拉伸因子
int stretch(int index) const; 
  1. //返回布局的方向。
Direction direction() const; 
  1. //设置布局的方向为 dir
void setDirection(Direction dir); 
  1. 返回布局中的项目数。
virtual int count() const; 
  1. 把盒式布局的正交尺寸限制在最小值 size 大小。其中正交尺寸是指,对于垂直布局则是指水平方向的尺寸,对于水平布局则是指垂直方向的尺寸。
void addStruct(int size);
  1. 把 item 插入到指定索引 index 处,若 index 为负,则插入到末尾。
void insertItem(int index, QLayoutItem* item); 
  1. 从布局中删除指定索引 index 处的项目,并返回该项目,若没有这样的项目,则返回 0,删除项目后,布局中的其他项目会重新编号索引。
virtual QLayoutItem* takeAt(int index) 
  1. 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::LabelRole0标签部件
QFormLayout::FieldRole1字段部件
QFormLayout::SpanningRole2跨越标签和字段的部件(标签和字段间的间距?)
  • 设置或获取表单布局字段部分的增长方式(注意:标签部分是不会增长的,即使标签部分部件的大小策略被设置为 Expanding,该部件也不会增长
FieldGrowthPolicy fieldGrowthPolicy() const; 
void setFieldGrowthPolicy(FieldGrowthPolicy);
成员说明
QFormLayout::FieldsStayAtSizeHint0字段不超出他们的大小提示,QMacStyle 默认值
QFormLayout::ExpandingFieldsGrow1只有水平方向的大小策略为 Expanding 或MinimumExpanding 的字段可以增长以填充可用的空间,其他字段不会超出他们的大小提示(原理见图示)。这是 QCommonStyle(比如 windows)的默认值
QFormLayout::AllNonFixedFieldsGrow2所有具有允许增长的大小策略的字会都会增长以填充可用空间,这是大多数样式的默认值(比如 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::DontWrapRows0字段始终位于标签旁边,这是除 Qt Extended 样式外的所有样式的默认策略。
QFormLayout::WrapLongRows1标签获得足够宽的水平空间,以适应最宽的标签,其余空间分配给字段。若“标签,字段”对的最小大小比可用空间大,则字段被换到下一行,这是 QtExtended 样式的默认策略。
QFormLayout::WrapAllRows2字段始终位于标签下方
  • 设置和获取部件之间的水平和垂直间距
//属性: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 类(分组布局或栈布局)

实现多页面切换的基本步骤

  1. 使用 QComboBox(组框)或 QListWidget(列表)之类的部件,提供给用户一个选择需要显示的页面的选项。
  2. 创建一个容器(比如 QWidget 实例),然后在该容器中添加需要显示给用户的内容。
  3. 把容器添加到 QStackedLayout 布局中。
  4. 把 QComboBox 的 activated 信号(或类似信号)与 QStackedLayout 的 setCurrentIndex 槽相关联,以实现当用户选择 QComboBox 中的选项时,显示 QStackedLayout 布局中的子部件。setCurrentIndex 槽的作用就是使 QStackedLayout 布局中的某一个子部件可见。

QStackedLayout 类的核心

  1. setCurrentIndex(int)和 setCurrentWidget(QWidget*)槽函数
  2. 要删除布局中的部件,可使用 QLayout::removeWidget()函数,
  3. 要获取布局中子部件的索引需使用 QLayout::indexOf()函数

QStackedLayout 类中的属性

  1. count:const int
//QLayout::count()的重新实现,返回布局中的项目数
virtual int count() const;
  1. currentIndex:int
//槽信号:currentChanged(int index);获取和设置当前部件(即可见部件),若没有当前部件,则索引为−1 
int currentIndex() const; 
void setCurrentIndex(int index) 
  1. 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 的步骤

  1. 创建一个 QTabWidget。
  2. 为每个选项卡创建一个页面(容器),通常为 QWidget(不要指定父部件)。
  3. 把子部件插入到页面部件(即容器)中。
  4. 使用 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 类,也就是说该类是一个带有边框的可视部件

分界线

  1. 分界线的创建:分界线是由 QSplitterHandle 类实现的,QSplitter 类本身不实现分界线。因此 QSplitterHandle 是一个部件,而 QSplitter 是另一个部件,这是两个部件,只不过这两个部件通过 Qt 的内部设计,让他们关联在一起,产生了一定的联系。
  2. 背景色:QSplitter 的分界线默认有可能是看不见的(因为颜色与 QSplitter 背景色相同,所以看不见),因此要使分界线可见,需设置分界线的背背色。
  3. 分界线的索引:其索引从 0 开始编号,分界线的数量与子部件的数量一样多。但索引为 0 的分界线始终是隐藏的。对于垂直分离器,索引为 0 的子部件上方的分界线索引为 0,对于水平水界面(对于从左到右的语言),则索引为 0 的子部件左侧的分界线的索引为 0,对于从右到左的语言,则索引为 0 的子部件右侧的分界线的索引为 0。
  • 动态调整:是指移动分界线时部件大小随之动态的改变,若不是动态调整的,则在移动分界线时部件大小不会改变,当完成分界线的移动时(即松开鼠标时),部件的大小才改变

  • 分离器的特点:分离器中的子部件分随着分离器大小的改变而改变,当分离器大小改变时,分离器会重新分配空间,以使其所有子部件的相对大小保持相同的比例不变。

  • 子部件的大小策略对分离器不起作用,分离器会把子部件填充满整个空间,即使子部件的大小策略设置为 Fixed,仍会被拉伸。

使用 QSplitter 的步骤如下:

  1. 创建一个 QSplitter。
  2. 使用 addWidget()函数把子部件添加到 QSplitter 中。

QSplitter 类的属性

  1. 折叠属性
    childrenCollapsible:bool
    访问函数:
bool childrenCollapsible() const; 
void setChildrenCollapsible(bool);
- 子部件是否可以被折叠(即调整到 0 的大小),默认为可折叠。
- 若部件可折叠,即使该部件的最小大小(minimumSize())不为零,用户也可将其大小调整为 0。  
- 设置该属性会作用于所有子部件上,使用函数 setCollapsible()可设置单个子部件是否可折叠。
  1. 分界线宽度
//handleWidth:int 访问函数:
 int handleWidth() const; 
 void setHandleWidth(int);
  1. 部件是否动态调整,分界线是否是不透明的
opaqueResize:bool 
//访问函数:
bool opaqueResize() const; 
void setOpaqueResize(bool opaque = true);
  1. 设置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::TabFocus0x1通过 tab 键接受焦点
Qt::ClickFocus0x2通过鼠标点击接受焦点
Qt::StrongFocusTabFocus | ClickFocus | 0x8通过 tab 和鼠标点击接受焦点。
Qt::WheelFocusStrongFocus | 0x4Qt::StrongFocus + 可使用鼠标滚轮接受焦点
Qt::NoFocus0 不接受焦点

设置焦点

// 若此部件或其父部件之一是活动窗口,则为此部件(或其焦点代理)设置焦点。若窗口不是活动的,则当窗口 变为活动时,部件将获得焦点。
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 语句。

  1. 类继承结构
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n7ZspnXr-1632751916587)(./pic/class_widght.png)]

  2. 主窗口包含内容
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cy78jFDq-1632751916588)(./pic/mainwindow.png)]

  3. 说明

    • 中心部件:主窗口必须有且只能有一个中心部件。中心部件可以是任意类型的部件(比 如 QTextEdit、QLineEDit 等)。中心部件使用 **setCentralWidget()**函数设置
    • 状态栏:状态栏主要用于向向户显示一些程序的状态信息,状态栏位于主窗口底部,一个主窗口只能有一个状态栏。使用** setStatursBar()**函数可设置状态栏。
    • 工具栏:工具栏通常是由一系列的类似按钮的部件组成的。使用 addToolBar()可以把工具栏添加到主窗口。工具栏是由 QToolBar 类实现的。一个主窗口可以有多个工具栏,工具栏可以位于主窗口的上、下、左、右四个方向上。
    • Dock 部件(悬浮窗口、可停靠窗口):一个主窗口可以有多个可停靠窗口。使用**addDockWidget()**可以把可停靠窗口添加到主窗口
    • 菜单与菜单栏:菜单位于菜单栏之中,一个主窗口只能有一个菜单栏,一个菜单栏中可以包含多个菜单。QMainWindow 有一个默认的菜单栏,该菜单栏使用 menuBar()
      函数返回。

菜单

  • QMenu 和 MenuBar 类都继承自 QWidget,可见,他们其实就是一个 QWidget 部件,只不过他们有些特殊的限制

  • QMenu 类可用于创建菜单,该类可创建单独的一个菜单项,并可使用 QMenu::addMenu()函数把一个菜单项添加到另一个菜单项中,从而创一个子菜单。

  • QMenuBar 是菜单栏,使用 QMenu 创建的菜单通常会添加到菜单栏中。使用QMenuBar::addMenu()函数可把菜单添加到菜单栏之中。

函数

  1. 添加菜单 menu 到菜单栏或菜单中,并返回与此菜单关联的 Action(动作)。此函数不会使菜单或菜单栏拥有 menu 的所有权(关于所有权,见后文)。
QAction* addMenu(QMenu *menu);
  1. 使用 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 需要完成以下关键步骤:

  1. 把 QAction 对象使用 QWidget::addAction()函数添加到部件。必须把 QAtion 添加到部件才能使用
  2. 把 QAction 的 triggered()信号连接到需要执行的槽函数。
  3. 激活 QAction。
    • 若已把 QAction 添加到菜单中,则直接点击该菜单项即可;
    • 若 QAction 含有快捷键,则直接使用快捷键便可激活 QAction;
    • 若 QAction 是添加到某个 QWidget 部件的(比如 QPushButton),则可以把该部件的某个信号连接到 QAction::trigger()槽或 QAction::triggered()信号,来激活QAction。

QShortcut 类(快捷键)

快捷键的实现原理:

首先使用指定的 QKeySequence(键序列)创建一个快捷键 QShortcut,然后把 QShortcut::activated()信号(激活快捷键时会发送此信号)关联到需要执行的槽函数即可

QShortcut 类中的属性

  1. 描述快捷键是否可自动重复
autoRepeat:bool
bool autoRepeat() const; 
void setAutoRepeat(bool);
  1. 快捷键的激活方式
context:Qt::ShortcutContext
Qt::ShortcutContext context() const; 
void setContext(Qt::ShortcutContext)

Qt::ShortcutContext 枚举

成员说明
Qt::WidgetShortcut0当父部件拥有焦点时,快捷键被激活。
Qt::WidgetWithChildrenShortcut3当父部件或其子部件拥有焦点时,快捷键可被激活。
Qt::WindowShortcut1当父部件是活动顶层窗口的逻辑子部件时,快捷键是活动的。
Qt::ApplicationShortcut2当其中一个应用程序窗口处于活动状态时,快捷键是活动的。
  1. 描述是否启用快捷键 enabled:bool
bool isEnabled() const; 
void setEnabled(bool);
  1. 获取和设置键序列 key:QKeySequence
QKeySequence key() const; 
void setKey(const QKeySequence&);
  1. 描述快捷键的 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 绘制图形的步骤

  1. 创建一个 QPainter 对象
  2. 调用QPainter::begin(QPaintDevice *);指定绘图设备并开始绘制,此步骤也可在 QPainter的构造函数中完成。注意:每次调用begin()函数都会把QPainter 的设置重置为默认值。
  3. 调用 QPainter 的成员函数绘制图形,调用 QPainter::end()结束绘制
  4. 若绘制设备是一个 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::NoIntersection0两线不相交(即平行)。
QLineF::UnboundedIntersection2两线相交,但交点不位于两条线之上
QLineF::BoundedIntersection1两线相交,交点位于两条线之上。
  • 偏移
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; //返回该线的占点

步骤

  1. 创建一个 QPainter 对象
  2. 调用QPainter::begin(QPaintDevice *);指定绘图设备并开始绘制,此步骤也可在 QPainter的构造函数中完成。注意:每次调用begin()函数都会把QPainter 的设置重置为默认值。
  3. 调用 QPainter 的成员函数绘制图形,调用 QPainter::end()结束绘制
  4. 若绘制设备是一个 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::NoIntersection0两线不相交(即平行)。
QLineF::UnboundedIntersection2两线相交,但交点不位于两条线之上
QLineF::BoundedIntersection1两线相交,交点位于两条线之上。
  • 偏移
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; //返回该线的占点
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Car12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值