Qt入门系列开发教程基础控件篇小部件(所有控件的基类QWidget)

Posted 鱼酱2333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt入门系列开发教程基础控件篇小部件(所有控件的基类QWidget)相关的知识,希望对你有一定的参考价值。

文章目录

widget 详细描述

widget 是用户操作的原子接口,它从窗口从系统接收鼠标、键盘和其他事件,并在屏幕上绘制自己的表示。每个widget都是矩形的,它们按 Z-order排序。widget 被其父级和它前面的widget裁剪。

一个未嵌入父窗口的widget 称为窗口。通常,窗口有一个边框和一个标题栏,尽管也可以创建没有边框和标题栏的窗口。在 Qt 中,QMainWindow 和 QDialog 的各种子类是最常见的窗口类型。

每个widget的构造函数都接受一个或两个标准参数

​ 1.构造函数中QWidget *parent = nullptr 是新widget的父级。 如果它是 nullptr(默认值),则新widget将是一个窗口。 如果不是,它将是父级的子级,并受父级几何形状的约束(除非您将 Qt::Window 指定为窗口标志)。
​ 2.这是配置窗口表的属性,Qt::WindowFlags f = (如果可用)设置窗口标志; 默认值适用于几乎所有widget,但要获得例如没有窗口系统框架的窗口,您必须使用特殊标志。

QWidget 有很多成员函数,但其中一些没有直接的功能; 例如,QWidget 有一个字体属性,但从不使用它本身。 有许多提供实际功能的子类,例如 QLabel、QPushButton、QListWidget 和 QTabWidget。

上层和子widget

一个widget没有父widget,通常是一个独立的窗口(顶级窗口widget)。 对于这些widget, setWindowTitle() 和 setWindowIcon() 分别设置标题栏和图标。

非窗口widget是子widget件,显示在其父widget中。 Qt 中的大多数widget主要用作子widget。 例如,可以将按钮显示为顶级窗口,但大多数人更喜欢将按钮放在其他widget中,例如 QDialog。

上图显示了一个 QGroupBox widget,用于在 QGridLayout 提供的布局中保存各种子widget。 QLabel 子widget已被概述以指示其完整大小。
如果您想使用 QWidget 来保存子widget,您通常需要向父 QWidget 添加布局。 有关详细信息,请参阅布局管理器

组件Widget

当一个widget被用作一个容器来组合多个子widget时,它被称为复合widget。 这些可以通过构建具有所需视觉属性的widget(例如 QFrame)并向其添加通常由布局管理的子widget来创建。 上图显示了使用 Qt Designer 创建的这样一个复合widget。
复合widget也可以通过子类化标准widget(例如 QWidget 或 QFrame)并在子类的构造函数中添加必要的布局和子widget来创建。 Qt 提供的许多示例都使用这种方法,Qt 教程中也有介绍。

自定义Widget和绘制

由于 QWidget 是 QPaintDevice 的子类,因此子类可用于显示使用 QPainter 类实例的一系列绘画操作组成的自定义内容。 这种方法与图形视图框架使用的画布样式方法形成对比,其中项目由应用程序添加到场景并由框架本身呈现。
每个widget都在其paintEvent() 函数中执行所有绘画操作。 每当需要重绘widget时调用此方法,无论是由于某些外部更改还是应用程序请求时。

大小提示 and 大小规则

在实现新的widget时,重新实现 sizeHint() 为widget提供合理的默认大小并使用 setSizePolicy() 设置正确的大小策略几乎总是有用的。
默认情况下,不提供大小提示的复合widget将根据其子widget的空间要求调整大小。
大小策略允许您为布局管理系统提供良好的默认行为,以便其他widget可以轻松包含和管理您的widget。 默认大小策略指示大小提示表示widget的首选大小,这通常对于许多widget来说已经足够了。
注意:顶级widget的大小限制为桌面高度和宽度的 2/3。 如果这些界限不够,您可以手动调整widget的大小。

事件

widget响应通常由用户操作引起的事件。 Qt 通过使用包含每个事件信息的 QEvent 子类实例调用特定的事件处理函数来将事件传递给widget。

如果您的widget仅包含子widget,您可能不需要实现任何事件处理程序。 如果您想检测子widget中的鼠标点击,请在widget的 mousePressEvent() 中调用子部件的 underMouse() 函数。
Scribble 示例实现了一组更广泛的事件来处理鼠标移动、按钮按下和窗口大小调整。
您需要为自己的widget提供行为和内容,但这里是与 QWidget 相关的事件的简要概述,从最常见的开始:

  • paintEvent() 每当需要重新绘制widget时都会调用paintEvent()。 每个显示自定义内容的widget都必须实现它。 使用 QPainter 进行绘画只能在paintEvent() 或由paintEvent() 调用的函数中进行。
  • resizeEvent()在widget被调整大小时被调用。
  • mousePressEvent()当鼠标光标在窗口widget内时按下鼠标按钮,或者当窗口widget使用grabMouse() 抓取鼠标时,将调用mousePressEvent()。 按下鼠标而不释放它实际上与调用grabMouse() 相同。
  • mouseReleaseEvent()释放鼠标按钮时调用。 widget在收到相应的鼠标按下事件时会收到鼠标释放事件。 这意味着如果用户在您的widget内按下鼠标,然后在释放鼠标按钮之前将鼠标拖动到其他位置,您的widget将收到释放事件。 有一个例外:如果在按住鼠标按钮时出现弹出菜单,该弹出菜单会立即窃取鼠标事件
  • mouseDoubleClickEvent()在用户双击widget时调用。 如果用户双击,widget接收鼠标按下事件、鼠标释放事件、(鼠标单击事件)第二次鼠标按下、该事件以及最后的第二次鼠标释放事件。 (如果在此操作过程中鼠标没有保持稳定,也可能会收到一些鼠标移动事件。)直到第二次单击到达之前,无法区分单击和双击。 (这就是为什么大多数 GUI 书籍建议双击是单击的扩展,而不是触发不同的操作的原因之一。)

接受键盘输入的widget需要重新实现更多的事件处理程序:

  • keyPressEvent()每当按下一个键时都会调用 ,并且当一个键被按住足够长的时间以使其自动重复时再次调用。 Tab 和 Shift+Tab 键仅在焦点更改机制不使用时才传递给widget。 要强制您的widget处理这些键,您必须重新实现 QWidget::event()。
    -focusInEvent() 当widget获得键盘焦点时调用 (假设您调用了 setFocusPolicy())。 表现良好的widget以清晰但谨慎的方式表明它们拥有键盘焦点。
  • focusOutEvent()当widget失去键盘焦点时调用。

您可能还需要重新实现一些不太常见的事件处理程序:

  • mouseMoveEvent()只要在按住鼠标按钮时鼠标移动,就会调用。这在拖放操作期间很有用。如果您调用 setMouseTracking(true),即使没有按下任何按钮,您也会收到鼠标移动事件。 (另请参阅拖放指南。)
  • keyReleaseEvent() 每当一个键被释放和被按住时被调用(如果键是自动重复的)。在这种情况下,widget将在每次重复时收到一对按键释放和按键事件。 Tab 和 Shift+Tab 键仅在焦点更改机制不使用时才传递给widget。要强制您的widget处理这些键,您必须重新实现 QWidget::event()。
  • wheelEvent()每当用户在widget获得焦点时转动鼠标滚轮时都会调用 。
  • enterEvent()当鼠标进入widget的屏幕空间时,将调用 。 (这不包括widget的任何子级拥有的屏幕空间。)
    -leaveEvent() 当鼠标离开widget的屏幕空间时调用 。如果鼠标进入一个子部件,它不会引发 leaveEvent()。
  • moveEvent()。当widget相对于其父级移动时,将调用
  • closeEvent() 当用户关闭窗口widget(或调用 close() 时)调用 closeEvent()。

QEvent::Type 的文档中还描述了一些相当晦涩的事件。 要处理这些事件,您需要直接重新实现 event()。
event() 的默认实现处理 Tab 和 Shift+Tab(移动键盘焦点),并将大多数其他事件传递给上面更专业的处理程序之一。
事件和用于传递它们的机制包含在事件系统中。

函数分类

widget样式

除了每个平台的标准小部件样式外,小部件还可以根据样式表中指定的规则进行样式设置。 此功能使您能够自定义特定小部件的外观,以便为用户提供有关其用途的视觉提示。 例如,可以以特定方式设置按钮的样式,以表明它执行破坏性操作。
小部件样式表的使用在 Qt 样式表文档中有更详细的描述。

透明度和双缓冲

从 Qt 4.0 开始,QWidget 会自动对其绘制进行双缓冲,因此无需在paintEvent() 中编写双缓冲代码来避免闪烁。
从 Qt 4.1 开始,只要没有设置 Qt::WA_PaintOnScreen,父控件的内容就会默认传播到它们的每个子控件。 可以编写自定义小部件以通过更新不规则区域(以创建非矩形子小部件)或使用具有小于完整 alpha 分量的颜色绘制来利用此功能。 下图显示了如何微调自定义小部件的属性和属性以实现不同的效果

在上图中,构造了一个去除了一个区域的半透明矩形子控件,并将其添加到父控件(显示像素图的 QLabel)。然后,设置不同的属性和widget属性来实现不同的效果:

  • 左侧widget没有设置其他属性或widget属性。此默认状态适合大多数使用透明度、不规则形状或不使用不透明画笔在其整个区域上绘制的自定义小部件。
  • 中心widget设置了 autoFillBackground 属性。此属性与依赖小部件提供默认背景的自定义小部件一起使用,并且不使用不透明画笔在其整个区域上绘制。
  • 右侧widget具有 Qt::WA_OpaquePaintEvent 小部件属性集。这表明小部件将在其整个区域上涂上不透明的颜色。小部件的区域最初是未初始化的,在图中用红色对角网格图案表示,该网格图案穿过重绘区域。 Qt::WA_OpaquePaintArea 属性对于需要快速绘制自己的专用内容并且不需要默认填充背景的小部件很有用。

要快速更新具有简单背景颜色的自定义widget,例如实时绘图或图形widget,最好定义合适的背景颜色(使用带有 QPalette::Window 角色的 setBackgroundRole()),设置 autoFillBackground 属性,并且仅在小部件的paintEvent() 中实现必要的绘图功能。
要快速更新使用不透明内容在其整个区域上不断绘制的自定义小部件,例如视频流小部件,最好设置小部件的 Qt::WA_OpaquePaintEvent,避免与重新绘制小部件背景相关的任何不必要的开销。
如果一个小部件同时具有 Qt::WA_OpaquePaintEvent 小部件属性和 autoFillBackground 属性集,则 Qt::WA_OpaquePaintEvent 属性优先。根据您的要求,您应该选择其中之一。
从 Qt 4.1 开始,父窗口widget的内容也传播到标准 Qt 窗口widget。如果父widget以非标准方式装饰,这可能会导致一些意想不到的结果,如下图所示。

自定义标准 Qt widget的绘画行为的范围,而不求助于子类化,比自定义小部件的范围略小。 通常,可以通过设置其 autoFillBackground 属性来实现标准小部件的所需外观。

创建透明窗体

从 Qt 4.5 开始,可以在支持合成的窗口系统上创建具有半透明区域的窗口。
要在顶级小部件中启用此功能,请使用 setAttribute() 设置其 Qt::WA_TranslucentBackground 属性,并确保在您希望部分透明的区域中使用非透明颜色绘制其背景。
平台说明:

  • X11:此功能依赖于使用支持 ARGB 视觉效果的 X 服务器和合成窗口管理器。
  • Windows:小部件需要设置 Qt::FramelessWindowHint 窗口标志才能使半透明工作。
  • macOS:小部件需要设置 Qt::FramelessWindowHint 窗口标志才能使半透明工作。

原生widget与外来widget

在 Qt 4.4 中引入的外星widget是窗口系统未知的widget。 它们没有与之关联的原生窗口句柄。 此功能显着加快了小部件的绘制、调整大小和消除闪烁。
如果您需要原生窗口的旧行为,您可以选择以下选项之一:

  • 1.在您的环境中使用 QT_USE_NATIVE_WINDOWS=1。
  • 2.在您的应用程序上设置 Qt::AA_NativeWindows 属性。 所有widget都将是原生widget。
  • 3.在widget上设置 Qt::WA_NativeWindow 属性:widget本身及其所有祖先都将变为原生(除非设置了 Qt::WA_DontCreateNativeAncestors)。
  • 4.调用 QWidget::winId 来强制一个原生窗口(这意味着 3)。
  • 5.设置 Qt::WA_PaintOnScreen 属性以强制使用本机窗口(这意味着 3)。

API

API太多了,懒得翻译了

    // GUI风格
    QStyle *style() const;
    void setStyle(QStyle *);
    // Widget types and states

    //是否为窗口
    bool isWindow() const;

    //模态相关判断和设置
    bool isModal() const;
    Qt::WindowModality windowModality() const;
    void setWindowModality(Qt::WindowModality windowModality);

    //启用禁用相关
    bool isEnabled() const;
    bool isEnabledTo(const QWidget *) const;

    void setEnabled(bool);
    void setDisabled(bool);

    //窗口标题是否被修改[*]
    void setWindowModified(bool);

    // Widget 坐标
    QRect frameGeometry() const;
    const QRect &geometry() const;
    QRect normalGeometry() const;

    int x() const;
    int y() const;
    QPoint pos() const;
    QSize frameSize() const;
    QSize size() const;
    inline int width() const;
    inline int height() const;
    inline QRect rect() const;
    //儿子矩形大小
    QRect childrenRect() const;
    QRegion childrenRegion() const;

    //大小相关
    QSize minimumSize() const;
    QSize maximumSize() const;
    int minimumWidth() const;
    int minimumHeight() const;
    int maximumWidth() const;
    int maximumHeight() const;
    void setMinimumSize(const QSize &);
    void setMinimumSize(int minw, int minh);
    void setMaximumSize(const QSize &);
    void setMaximumSize(int maxw, int maxh);
    void setMinimumWidth(int minw);
    void setMinimumHeight(int minh);
    void setMaximumWidth(int maxw);
    void setMaximumHeight(int maxh);



    QSize sizeIncrement() const;
    //设置增量,窗口resize调用
    void setSizeIncrement(const QSize &);
    void setSizeIncrement(int w, int h);
    QSize baseSize() const;
    void setBaseSize(const QSize &);
    void setBaseSize(int basew, int baseh);

    void setFixedSize(const QSize &);
    void setFixedSize(int w, int h);
    void setFixedWidth(int w);
    void setFixedHeight(int h);

    // Widget 坐标 mapping
    QPointF mapToGlobal(const QPointF &) const;
    QPoint mapToGlobal(const QPoint &) const;
    QPointF mapFromGlobal(const QPointF &) const;
    QPoint mapFromGlobal(const QPoint &) const;
    QPointF mapToParent(const QPointF &) const;
    QPoint mapToParent(const QPoint &) const;
    QPointF mapFromParent(const QPointF &) const;
    QPoint mapFromParent(const QPoint &) const;
    QPointF mapTo(const QWidget *, const QPointF &) const;
    QPoint mapTo(const QWidget *, const QPoint &) const;
    QPointF mapFrom(const QWidget *, const QPointF &) const;
    QPoint mapFrom(const QWidget *, const QPoint &) const;

    QWidget *window() const;
    QWidget *nativeParentWidget() const;
    inline QWidget *topLevelWidget() const  return window(); 

    // Widget appearance functions
    const QPalette &palette() const;
    void setPalette(const QPalette &);//背景
    void setBackgroundRole(QPalette::ColorRole);
    QPalette::ColorRole backgroundRole() const;

    void setForegroundRole(QPalette::ColorRole);
    QPalette::ColorRole foregroundRole() const;

    //字体相关
    const QFont &font() const;
    void setFont(const QFont &);
    QFontMetrics fontMetrics() const;
    QFontInfo fontInfo() const;


	//鼠标追踪
    void setMouseTracking(bool enable);
    bool hasMouseTracking() const;
    bool underMouse() const;

    void setTabletTracking(bool enable);
    bool hasTabletTracking() const;

    void setMask(const QBitmap &);
    void setMask(const QRegion &);
    QRegion mask() const;
    void clearMask();

    void render(QPaintDevice *target, const QPoint &targetOffset = QPoint(),
                const QRegion &sourceRegion = QRegion(),
                RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));

    void render(QPainter *painter, const QPoint &targetOffset = QPoint(),
                const QRegion &sourceRegion = QRegion(),
                RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));

    Q_INVOKABLE QPixmap grab(const QRect &rectangle = QRect(QPoint(0, 0), QSize(-1, -1)));

#if QT_CONFIG(graphicseffect)
    QGraphicsEffect *graphicsEffect() const;
    void setGraphicsEffect(QGraphicsEffect *effect);
#endif // QT_CONFIG(graphicseffect)

#ifndef QT_NO_GESTURES
    void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
    void ungrabGesture(Qt::GestureType type);
#endif

public Q_SLOTS:
    void setWindowTitle(const QString &);
#ifndef QT_NO_STYLE_STYLESHEET
    void setStyleSheet(const QString& styleSheet);
#endif
public:
#ifndef QT_NO_STYLE_STYLESHEET
    QString styleSheet() const;
#endif
    //标题栏相关
    QString windowTitle() const;
    void setWindowIcon(const QIcon &icon);
    QIcon windowIcon() const;
    void setWindowIconText(const QString &);
    QString windowIconText() const;
    void setWindowRole(const QString &);
    QString windowRole() const;
    void setWindowFilePath(const QString &filePath);
    QString windowFilePath() const;

    void setWindowOpacity(qreal level);
    qreal windowOpacity() const;

    bool isWindowModified() const;
#if QT_CONFIG(tooltip)
    void setToolTip(const QString &);
    QString toolTip() const;
    void setToolTipDuration(int msec);
    int toolTipDuration() const;
#endif
#if QT_CONFIG(statustip)
    void setStatusTip(const QString &);
    QString statusTip() const;
#endif
#if QT_CONFIG(whatsthis)
    void setWhatsThis(const QString &);
    QString whatsThis() const;
#endif
#ifndef QT_NO_ACCESSIBILITY
    QString accessibleName() const;
    void setAccessibleName(const QString &name);
    QString accessibleDescription() const;
    void setAccessibleDescription(const QString &description);
#endif

    void setLayoutDirection(Qt::LayoutDirection direction);
    Qt::LayoutDirection layoutDirection() const;
    void unsetLayoutDirection();

    void setLocale(const QLocale &locale);
    QLocale locale() const;
    void unsetLocale();

    inline bool isRightToLeft() const  return layoutDirection() == Qt::RightToLeft; 
    inline bool isLeftToRight() const  return layoutDirection() == Qt::LeftToRight; 

public Q_SLOTS:
    inline void setFocus()  setFocus(Qt::OtherFocusReason); 

public:
    bool isActiveWindow() const;
    void activateWindow();
    void clearFocus();

    void setFocus(Qt::FocusReason reason);
    Qt::FocusPolicy focusPolicy() const;
    void setFocusPolicy(Qt::FocusPolicy policy);
    bool hasFocus() const;
    static void setTabOrder(QWidget *, QWidget *);
    void setFocusProxy(QWidget *);
    QWidget *focusProxy() const;
    Qt::ContextMenuPolicy contextMenuPolicy() const;
    void setContextMenuPolicy(Qt::ContextMenuPolicy policy);

    // Grab functions
    void grabMouse();
#ifndef QT_NO_CURSOR
    void grabMouse(const QCursor &);
#endif
    void releaseMouse();
    void grabKeyboard();
    void releaseKeyboard();
#ifndef QT_NO_SHORTCUT
    int grabShortcut(const QKeySequence &key, Qt::ShortcutContext context = Qt::WindowShortcut);
    void releaseShortcut(int id);
    void setShortcutEnabled(int id, bool enable = true);
    void setShortcutAutoRepeat(int id, bool enable = true);
以上是关于Qt入门系列开发教程基础控件篇小部件(所有控件的基类QWidget)的主要内容,如果未能解决你的问题,请参考以下文章

Qt入门系列开发教程基础控件篇框架QFrame

Qt入门系列开发教程基础控件篇QCalendarWidget日历控件

Qt入门系列开发教程基础控件篇QLabel文本标签

Qt入门系列开发教程高级控件篇QTableWidget表格小部件

Qt入门系列开发教程高级控件篇QListWidget列表小部件

Qt入门系列开发教程高级控件篇QTreeWidget树形小部件