`
tomhibolu
  • 浏览: 1430788 次
文章分类
社区版块
存档分类
最新评论

漫谈QWidget及其派生类(菜单、菜单栏)

 
阅读更多
  • QMenu和QMenuBar都是QWidget的派生类,按理说也没有什么特别的。只是真的想理清它,似乎还真的不是那么简单...

QMenuBar

漫谈QWidget及其派生类(三)中,我们已经知道:QMenuBar和QStatusBar都是QWidget的派生类,所以我们可以像添加一个QPushButton一样将它们任意放置到另一个QWidget中。

继续看个别的例子:

#include <QtGui>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QMenuBar menubar;
    menubar.addAction("Action1");
    menubar.addAction("Action1");
    menubar.show();

    return app.exec();
}

我们知道,QWidget本来就有一个成员函数:

void QWidget::addAction ( QAction * action )

而此处只不过是QMenuBar提供的重载版本:

QAction *QMenuBar::addAction(const QString &text)
{
    QAction *ret = new QAction(text, this);
    addAction(ret);
    return ret;
}

可是同样的东西,到了QMenuBar中,就显示出一种菜单栏的效果了呢?

不同的Widget,为什么不一样?我们都会自定义控件,所以都熟悉:

void QMenuBar::paintEvent(QPaintEvent *e)
{
...
    for (int i = 0; i < d->actions.count(); ++i) {
        QAction *action = d->actions.at(i);
        QRect adjustedActionRect = d->actionRect(action);
...

便利它自身的actions列表,然后依次将它们paint出来。

然后当触发快捷键,或者在某个区域点击鼠标时:

void QMenuBar::mousePressEvent(QMouseEvent *e)
{
...
    QAction *action = d->actionAt(e->pos());
....
    d->setCurrentAction(action, true);
...

addMenu()

在继续之前,我们需要简单了解一下addAction和addMenu

QMenu *QMenuBar::addMenu(const QString &title)
{
    QMenu *menu = new QMenu(title, this);
    addAction(menu->menuAction());
    return menu;
}

看,无非是创建一个QMenu,然后将该菜单对应的QAction添加进来了。而这个QMenu,稍候可以通过对应的QAction的成员函数

QMenu * QAction::menu () const

来获得

先看看QMenu,稍候再回来

QMenu

QMenu 也是一个QWidget的派生类

  • 一个规规矩矩的矩形窗口(窗口类别 Qt::Popup)
  • 通过setVisible(true)或show()使其显示出来

但是,为什么QMenu长成这个样子呢,一条一条的?

其实看了前面的QMenuBar,我们对QMenu为什么长这个样子,应该不会感到任何惊奇了。

先添加一些QAction,然后在paintEvent中遍历Action列表,并画出一个一个矩形条。

void QMenu::paintEvent(QPaintEvent *e)
{
    //draw the items that need updating..
    for (int i = 0; i < d->actions.count(); ++i) {
        QAction *action = d->actions.at(i);
...

当然,为了有点立体效果,或者说为了让QMenu和其他东西分开,还需要画边框。

上下文菜单

我们在一个Widget的某个位置上点击右键,或者通过键盘上某个键。会弹出上下文菜单。

这个菜单和我们在菜单栏看到的菜单其实没有区别,要说区别的话,就是需要我们自己:

  • 设置菜单的位置
  • 并让菜单显示出来

考虑:一般我们是如何使用上下文菜单的?

void Widget::contextMenuEvent(QContextMenuEvent *event)
{
  QMenu menu(this);
  menu.addAction("A1");
  menu.addAction("A2");
  
  filemenu->exec(this->mapToGlobal(event.pos())); 
  • 创建菜单
  • 添加action
  • 显示菜单

如何显示?

  • 记得刚接触这个东西时,在这个地方都是犯糊涂。这儿为什么不能直接用event中的位置,而是要map到全局坐标。

还是要从QMenu是QWidget的派生类说起。在前面我们提到了这样的内容:

  • QWidget分:窗口(Window)和部件(Widget)两类。前者的位置是全局的或者说相对屏幕的,后者坐标是相对父部件的

QMenu 是 Window,所以位置坐标是全局的。而event坐标是当前窗口部件的。

  • 显示一个QWidget,我们必须调用setVisible(true)/show()才行!!这儿用的确实exec(),我们类比QDialog的话,很容易才到答案。

其内部肯定调用了show(),而且还使用QEventLoop开启了局部的事件循环。

popup()

既然直接调用show()就可以让菜单显示出来,这个popup()又有何用?

void QMenu::popup(const QPoint &p, QAction *atAction)
{
...
}

它做的工作:

  • 确保样式和字体被正确设置
  • 调整几何尺寸(位置和大小)
  • 调用show() 显示

而我们刚提到的exec()就是在popup的基础上加了个事件循环

QAction *QMenu::exec(const QPoint &p, QAction *action)
{
    QEventLoop eventLoop;
    d->eventLoop = &eventLoop;
    popup(p, action);
...

回到菜单栏

了解了上下文菜单,我们可以回头看看菜单栏是如何控制菜单显示的。

一开始说了,

  • 菜单对应的action被加入到了菜单栏
  • 菜单栏在paintEvent绘制我们熟悉的那一栏东西
  • 当我们点击鼠标时,菜单栏mousePressEvent中判断位置对应哪个action
  • 这样就到了...

void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst)
{
    if(!action || !action->menu() || losePopupMode)
        return;

    activeMenu = action->menu();
    ....
    activeMenu->popup(pos);

源码中,最长的一段就是在计算和调整菜单的位置(以确保菜单不会跑到屏幕外),即那个pos


分享到:
评论

相关推荐

    QWidget样式表设置背景示例代码

    然而,在尝试通过样式表(QSS,Qt Style Sheets)来改变`QWidget`及其子类的外观时,有时会遇到一些问题,特别是当直接对`QWidget`派生的类应用样式表时,可能无法达到预期效果。本篇将深入探讨这个问题以及解决方案...

    setCentralWidget,Qt中心部件Demo

    中心部件通常是一个继承自 `QWidget` 的自定义部件,但也可以是其他 `QWidget` 派生类的实例。以下是如何在 `QMainWindow` 中使用中心部件的说明和一个简单的实例讲解。 + **中心部件的使用说明:** 1. **创建中心...

    qt包括菜单栏工具栏的小图标主窗口

    通过QMainWindow、QMenuBar、QToolBar和QAction等类,我们可以轻松地创建带菜单栏和工具栏的主窗口,并为菜单项和工具栏按钮设置事件响应。这样的设计使得Qt成为了开发桌面应用程序的强大工具,能够满足各种复杂的UI...

    QWidget 显示图片,支持缩放、拖动、右键菜单等功能

    本示例中,我们关注的是一个扩展了`QWidget` 的类,它增加了显示图片、支持缩放、拖动以及右键菜单的功能。这个自定义的组件名为 `MyImageWidget`。 首先,`MyImageWidget` 类会继承自`QWidget`,以便我们可以利用`...

    Qt导航栏Demo之侧边垂直菜单

    在本文中,我们将深入探讨如何使用Qt框架创建一个侧边垂直菜单导航栏。Qt是一个功能强大的C++库,广泛用于跨平台的图形用户界面(GUI)开发。在许多应用程序中,垂直导航栏作为主菜单布局,能有效地节省空间并提供更...

    定制QWidget标题栏的示例,并含有qss配置QTabWidget样式的示例

    在本文中,我们将深入探讨如何使用Qt框架进行高级界面定制,特别是关注于QWidget标题栏的自定义和QTabWidget样式的QSS配置。Qt是一个跨平台的C++图形用户界面应用程序开发框架,广泛用于创建美观且功能丰富的桌面和...

    QWidget实现界面收缩栏的效果

    QT插件实现了界面收缩栏效果 1、可以在收缩栏中添加界面 2、可以对添加的界面进行收起或展开 3、可以拖动界面变换界面的位置 用法链接:...

    Qt例程源代码QWidget.7z

    以下是一些关于QWidget及其相关知识点的详细说明: 1. **窗口和布局管理**:QWidget可以创建窗口,通过setWindowFlags()方法设置窗口属性,如是否为顶层窗口、是否可最小化等。同时,使用QLayout进行布局管理,如...

    QWidget实现左侧炫酷导航栏效果

    QT插件实现了界面左侧导航栏效果1、可以在导航栏中添加切换标签2、可以在导航栏中添加界面用法链接:https://menghui666.blog.csdn.net/article/details/134545765?spm=1001.2014.3001.5502微博主页:...

    Qt编程基础 - 第六章-窗体 - 6.4、QWidget 自定义右键菜单

    本节将深入探讨如何在QWidget类的基础上自定义右键菜单,这是提高用户交互性和应用程序功能的重要手段。在Qt库中,我们可以利用QMenu和QAction来创建并管理这种自定义的上下文菜单。 首先,了解QMenu和QAction的...

    026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法.7z

    在Qt库中,`QWidget`类是所有用户界面对象的基础,它是构建图形用户界面(GUI)的核心组件。这个压缩包文件“026 QWidget类分析显示和隐藏接口说明线程类QThread使用方法”显然是针对Qt开发者的,旨在详细解释`...

    QWidget嵌入到QML中

    1. 创建`QWidget`:首先,你需要有一个自定义的`QWidget`类。这个类可以继承自`QWidget`,并添加你需要的功能或组件。 ```cpp class CustomWidget : public QWidget { Q_OBJECT public: explicit CustomWidget...

    给QWidget加滚动条

    我们首先需要创建一个继承自`QWidget`的自定义类,这个类将会包含需要展示的内容。在这个类中,我们可以添加布局、按钮、文本等控件。 ```cpp class MyWidget : public QWidget { Q_OBJECT public: MyWidget...

    UI界面+Pyqt+菜单栏拓展+scroll滑动实现

    在本项目中,我们主要探讨如何使用Python的PyQt库来构建一个具有可滚动和拓展菜单栏的UI界面。PyQt是一个强大的图形用户界面(GUI)工具包,它基于Qt库,提供了丰富的功能来创建复杂的桌面应用程序。让我们深入研究...

    使用QWidget实现翻转

    1. 创建一个继承自`QWidget`的自定义类,并重写`paintEvent()`方法。在这里,你需要绘制翻转前后的两个图像或内容。通常,这会涉及设置`QPainter`的画刷和画笔,然后在指定区域内绘制。 2. 在`paintEvent()`中,...

    2个QWidget相互切换显示.zip

    `QWidget`是QT库中的核心类,它提供了图形用户界面的基础框架,包括窗口、控件和布局管理等。每个`QWidget`都可以有自己的子部件,并且可以通过布局来组织这些子部件,使其在窗口中按照预期的方式排列。 在描述中...

    QWidget,QMainWindow和QDialog的区别

    QWidget、QMainWindow 和 QDialog 是 Qt 中三个基础的 GUI 组件类,它们之间的区别是非常重要的,在创建 Qt Gui Application 时,总会让你选择在 QWidget、QMainWindow 和 QDialog 中选择一个 Base Class。这三个类...

    qwidget嵌入qml最完整代码

    QML是一种基于JSON的声明式语言,用于构建具有丰富图形界面的应用程序,而QWidget是C++中的一个类,它是Qt GUI编程的核心组件。在某些场景下,我们需要将两者结合使用,以利用QML的灵活性和QWidget的功能性。...

    QWidget控件在QML中使用 控件

    在Qt框架中,QML(Qt Quick)是一种强大的声明式用户界面设计语言,它允许开发者...这种方式不仅适用于QWidget,还可以应用于其他C++类,如自定义的QGraphicsView或复杂的逻辑处理类,让QML和C++的优点得到充分的结合。

    Python3.x+Pyqt5实现主窗体(QMainWindow类)里的分割器QSplitter动态载入子窗体(QWidget类),还实现了导航栏抽屉效果

    本教程主要聚焦于使用PyQt5的QMainWindow类构建主窗体,并结合QSplitter来动态加载子窗体(QWidget类),同时实现一种导航栏抽屉效果。下面我们将详细探讨这些知识点。 1. **QMainWindow类**: QMainWindow是PyQt5...

Global site tag (gtag.js) - Google Analytics