QT6 源(109)篇三:阅读与注释菜单栏里的菜单对象 QMenu,给出其源代码

(8)本源代码来自于头文件 qmenu . h

#ifndef QMENU_H
#define QMENU_H

#include <QtWidgets/qtwidgetsglobal.h>
#include <QtWidgets/qwidget.h>
#include <QtCore/qstring.h>
#include <QtGui/qicon.h>
#include <QtGui/qaction.h>


QT_REQUIRE_CONFIG(menu);

QT_BEGIN_NAMESPACE

class QMenuPrivate;
class QStyleOptionMenuItem;
class QPlatformMenu;

/*
The QMenu class provides a menu widget for use in menu bars,
    context menus, and other popup menus.

菜单小部件是一个选择菜单。它可以是菜单栏中的下拉式选单,也可以是独立的上下文选单。
当用户单击相应的项或按下指定的快捷键时,菜单栏会显示下拉菜单。
使用QMenuBar:addMenu()将菜单插入菜单栏。
上下文菜单通常由某个特殊的键盘键或右键单击调用。它们可以用popup()异步执行,也可以用exec()同步执行。
菜单也可以响应按钮按压而被调用;除了调用方式外,这些菜单与上下文菜单类似。

Actions  :
菜单由操作项列表组成。使用addAction()、addActions()和插入Action()函数添加操作。
动作垂直表示并由 QStyle渲染。
此外,操作可以有一个文字标签,一个可选的图标画在最左侧,快捷键顺序,如“Ctrl+X”.
可以使用 actions()函数找到菜单中现有的操作 QAction。
    QList<QAction *>   QWidget::actions() const;

有四种类型的操作项:分隔符、显示子菜单的操作、小部件和执行操作的操作。
分隔符使用addSeparator()插入,子菜单使用addMenu()插入,所有其他项都被视为操作项。
在插入操作项时,通常需要指定接收者和槽位。每当项被触发()时,接收者都会收到通知。
此外,QMenu提供了两个信号,触发()和悬停()triggered() and hovered(),
这些信号表示从菜单触发的QAction。

You clear a menu with clear() and remove individual action items with removeAction().

QMenu还可以提供拆卸菜单。撕掉菜单是一个顶层窗口,包含菜单的副本。
这使得用户可以“撕掉”常用的菜单,并将其放置在屏幕的方便位置。
如果您希望特定菜单具有此功能,请插入带有setTearOffEnabled()的撕掉手柄。
当使用拖拽式菜单时,请记住,这个概念在微软Windows上并不常用,所以一些用户可能并不熟悉它。
可以考虑使用QToolBar。

可以使用 OWidgetAction 类将窗口小部件插入到菜单中。
此类的实例用于保存小部件,并通过采用QAction的 addAction()重载插入到菜单中。
如果QWidgetAction触发triggered ()信号,则菜单将关闭。

警告:要在屏幕上显示QMenu,应使用exec()或popup(),而不是show()或setVisible()。
要隐藏或禁用菜单栏中的菜单,或在其作为子菜单添加的另一个菜单中禁用它,请使用menuAction()的相应属性。

QMenu on macOS with Qt Build Against Cocoa :
QMenu can be inserted only once in a menu/menubar.
Subsequent insertions will have no effect or will result in a disabled menu item.
See the Menus example for an example of how to use QMenuBar
and QMenu in your application.


*/

class Q_WIDGETS_EXPORT QMenu : public QWidget
{
private:
    Q_OBJECT

    Q_DECLARE_PRIVATE(QMenu)

    //This property holds the title of the menu。
    //This is equivalent to the QAction::text property of the menuAction().
    //By default, this property contains an empty string.
    Q_PROPERTY(QString title READ title WRITE setTitle) //菜单栏里菜单的名字。

    Q_PROPERTY(QIcon   icon  READ icon  WRITE setIcon)  //菜单栏里菜单的图片。其会取代文本
    //This property holds the icon of the menu。
    //This is equivalent to the QAction::icon property of the menuAction().
    //By default, if no icon is explicitly set, this property contains a null icon.

    //这个属性表示菜单是否支持被撕下。  // 默认情况下,此属性为假。
    //当为真时,菜单包含一个特殊的撕下项(通常显示为菜单顶部的虚线),当触发时创建菜单的副本。
    //这个“撕下”的副本存在于一个单独的窗口中。它包含与原始菜单相同的菜单项,除了撕下的手柄。
    Q_PROPERTY(bool      tearOffEnabled        //此属性在 windows系统上没有用
                READ   isTearOffEnabled        WRITE   setTearOffEnabled)

    //此属性表示是否应折叠连续的分隔符。   默认情况下,此属性为真。
    //此属性指定菜单中的连续分隔符是否应视觉上折叠为一个。菜单开头或结尾的分隔符也会被隐藏。
    Q_PROPERTY(bool    separatorsCollapsible
                READ   separatorsCollapsible   WRITE   setSeparatorsCollapsible)
    //动态菜单优化:当菜单内容根据上下文动态变化时(如通过用户操作增减菜单项),
    //  连续分隔符可能因内容增减而产生冗余。启用此属性可自动合并多余分隔符,保持菜单整洁。
    //边缘分隔符隐藏:若分隔符位于菜单开头或结尾,默认情况下会被隐藏,避免视觉上的突兀感。


    Q_PROPERTY(bool    toolTipsVisible         //默认情况下,此属性为假。
                READ   toolTipsVisible         WRITE   setToolTipsVisible)
    //此属性表示是否应显示菜单操作的提示信息。此属性指定操作菜单项是否显示其提示信息。
    //菜单栏里的提示默认是关闭的,因为不必要重复。工具栏里的按钮提示,默认是打开的,因为必要。

private:
    Q_DISABLE_COPY(QMenu)

    Q_PRIVATE_SLOT(d_func(), void _q_actionTriggered())
    Q_PRIVATE_SLOT(d_func(), void _q_actionHovered())
    Q_PRIVATE_SLOT(d_func(), void _q_overrideMenuActionDestroyed())
    Q_PRIVATE_SLOT(d_func(), void _q_platformMenuAboutToShow())

    friend class QMenuBar;
    friend class QMenuBarPrivate;
    friend class QTornOffMenu;
    friend class QComboBox;
    friend class QtWidgetsActionPrivate;
    friend class QToolButtonPrivate;
    friend void  qt_mac_emit_menuSignals (QMenu * menu, bool      show);
    friend void  qt_mac_menu_emit_hovered(QMenu * menu, QAction * action);

protected:
    bool             event(QEvent       *) override;
    void       changeEvent(QEvent       *) override;
    void     keyPressEvent(QKeyEvent    *) override;
    void mouseReleaseEvent(QMouseEvent  *) override;
    void   mousePressEvent(QMouseEvent  *) override;
    void    mouseMoveEvent(QMouseEvent  *) override;
    void        wheelEvent(QWheelEvent  *) override;
    void        enterEvent(QEnterEvent  *) override;
    void        leaveEvent(QEvent       *) override;
    void         hideEvent(QHideEvent   *) override;
    void        paintEvent(QPaintEvent  *) override;
    void       actionEvent(QActionEvent *) override;
    void        timerEvent(QTimerEvent  *) override;

    //如果菜单无法在屏幕上显示,它会自动调整布局以使其适合屏幕。
    //布局的含义取决于样式(例如,在Windows上,它将使用多列)。
    int  columnCount() const; //此函数返回本菜单所需的列数。

    //Reimplements: QWidget::focusNextPrevChild(bool next).
    bool focusNextPrevChild(bool next) override;

    virtual void initStyleOption(QStyleOptionMenuItem * option,
                                 const QAction        * action) const;

    QMenu(QMenuPrivate & dd, QWidget * parent = nullptr);

private Q_SLOTS:
    void internalDelayedPopup(); //无注释

Q_SIGNALS:
    void aboutToShow();
    //This signal is emitted just before the menu is shown   to  the user.
    //This signal is emitted just before the menu is hidden from the user.
    void aboutToHide();

    //This signal is emitted when an action in this menu is triggered.
    //action is the action that caused the signal to be emitted.
    //Normally, you connect each menu action's triggered() signal to its own custom slot,
    //but sometimes you will want to connect several actions to a single slot,
    //for example, when you have a group of closely related actions,
    //such as "left justify", "center", "right justify".
    //Note: This signal is emitted for the main parent menu in a hierarchy.
    //Hence, only the parent menu needs to be connected to a slot;
    //sub-menus need not be connected. // QAction 具有这俩同名信号的。但信号函数的参数设计的不一样。
    void triggered(QAction * action);  //本菜单里的按钮被 triggerd,本菜单就会发送本信号。
    void hovered  (QAction * action);  //当本菜单被悬停就触发,形参是高亮的菜单项。
    //This signal is emitted when a menu action is highlighted;
    //action is the action that caused the signal to be emitted.
    //Often this is used to update status information.
    //补充:QAction { Q_SIGNALS: void triggered(bool checked = false); void hovered(); };

public:
    //Constructs a menu with parent parent.
    //Although a popup menu is always a top-level widget,
    //if a parent is passed,
    //the popup menu will be deleted when that parent is destroyed
    //(as with any other QObject).
    //举例:menu_F = new QMenu(menubar); 传递的实参可以是菜单栏对象
    explicit QMenu(QWidget * parent = nullptr);
    explicit QMenu(const QString & title, QWidget * parent = nullptr);
    //Constructs a menu with a title and a parent.

    ~QMenu();


// Q_PROPERTY(QString      title   READ   title   WRITE   setTitle) //菜单栏里菜单的名字。
              QString      title() const;
                 void   setTitle(const QString & title);


// Q_PROPERTY(QIcon        icon    READ   icon    WRITE    setIcon)  //该图片会取代文本
              QIcon        icon () const;
               void     setIcon (const QIcon   & icon);


// Q_PROPERTY(bool      tearOffEnabled          //此属性在 windows系统上没有用
//            READ    isTearOffEnabled          WRITE   setTearOffEnabled)
              bool    isTearOffEnabled    () const;
              void   setTearOffEnabled    (bool  );
              bool    isTearOffMenuVisible() const;
              void  showTearOffMenu();
              void  showTearOffMenu(const QPoint & pos);
              void  hideTearOffMenu();


// Q_PROPERTY(bool      separatorsCollapsible   //此属性默认为真
//            READ      separatorsCollapsible   WRITE   setSeparatorsCollapsible)
              bool      separatorsCollapsible() const;
              void   setSeparatorsCollapsible(bool collapse);


// Q_PROPERTY(bool      toolTipsVisible         //默认情况下,此属性为假。
//            READ      toolTipsVisible         WRITE   setToolTipsVisible)
              bool      toolTipsVisible() const;
              void   setToolTipsVisible(bool visible);


    QAction  *     defaultAction() const;  //Returns the current default action.
    void        setDefaultAction(QAction * act); //This sets the default action to act.
    //默认操作可能具有视觉提示,具体取决于当前 QStyle。默认操作通常指示当出现下拉菜单时默认会发生什么。
    //设置后,默认的菜单项将会加粗显示。

    //Returns the currently highlighted action,
    //or nullptr if no action is currently highlighted.
    QAction  *      activeAction() const;  //此函数会返回当前菜单里被高亮显示的菜单项
    void         setActiveAction(QAction * act);
    //Sets the currently highlighted action to act.

    QPlatformMenu  *      platformMenu();  //没有关于 QPlatformMenu的源代码
    void               setPlatformMenu(QPlatformMenu * platformMenu); //这俩函数无注释


    QSize sizeHint() const override;

    //class QRect  { int x1;  int y1;  int x2;  int y2; }; //返回菜单里菜单项的大小
    QRect     actionGeometry(QAction * act) const; //Returns the geometry of action act.

    //class QPoint { int xp;  int yp; };
    QAction * actionAt(const QPoint  & pt ) const; //返回菜单里在某个位置的菜单项
    //Returns the item at pt; returns nullptr if there is no item there.

    QAction * menuAction() const; //Returns the action associated with this menu.
    //举例:menu_E->addAction(menu_Format_BIU->menuAction()); //!!重要:为菜单添加子菜单
    //子菜单是菜单 QMenu类型,但同时也是父菜单里的一个菜单项 QAction,
    //本函数即是返回与子菜单关联的父菜单里的菜单项。

    //Returns true if there are no visible actions inserted into the menu,
    //  false otherwise.
    bool isEmpty() const;

    void clear(); //Removes all the menu's actions.  //清空菜单里的所有菜单项
    //Actions owned by the menu and not shown in any other widget are deleted。

    //Displays the menu so that the action atAction will be at the
    //  specified global position p.
    //要将小部件的局部坐标转换为全局坐标,请使用 QWidget::mapToGlobal()。
    //在使用exec()或popup()定位菜单时,请记住您不能依赖菜单的当前大小(currentsize)。
    //出于性能原因,菜单仅在必要时调整其大小,因此在许多情况下,显示前后的大小会有所不同。
    //相反,使用sizeHint(),它根据菜单的当前内容计算适当的大小。
    void       popup(const QPoint &  p,  QAction * atAction = nullptr);
    QAction *  exec (); //This is equivalent to exec(pos()).
    QAction *  exec (const QPoint &  p,  QAction *   action = nullptr); //同步执行此菜单。
    //弹出菜单,使动作action位于指定的全局位置p。
    //要将小部件的局部坐标转换为全局坐标,请使用QWidget::mapToGlobal()。
    //这将在弹出式菜单或其子菜单中返回触发的事件处理程序,This returns the
    //  triggered QAction in either the popup menu or one of its submenus,
    //如果没有触发任何项目(通常是因为用户按下了 Esc),则返回nullptr。
    //请注意,所有信号都会像往常一样发出。如果您将 QAction连接到槽并调用菜单的exec()方法,
    //  则可以通过信号-槽连接或在 exec()方法的返回值中获取结果。
    //通常的用法是将菜单定位在当前鼠标位置:  exec( QCursor::pos() ); 或用于对齐或关联到 event。

    static //静态函数,临时构建菜单,以包含形参1 里的菜单项,并使菜单项 at在位置 pos处显示。
    QAction *  exec (const QList<QAction *> & actions,  //同步执行菜单。
                     const QPoint & pos, QAction * at = nullptr,
                           QWidget       *     parent = nullptr);
    //The menu's actions are specified by the list of actions。
    //菜单将弹出,以便指定的操作 at出现在全局位置 pos处。如果未指定 at,则菜单将出现在位置 pos处。
    //parent是菜单的父容器;指定父容器将提供上下文,若 pos本身不足以确定菜单应位于何处
    //(例如,在多桌面或当父容器嵌入在OGraphicsView中时)。
    //该函数返回弹出式菜单或其子菜单中触发的事件处理程序,
    //  如果未触发任何项目(通常是因为用户按下了Esc),则返回 nullptr。

    void setNoReplayFor(QWidget * widget); //无官方注释

    using  QWidget::addAction; //对,此函数确实定义在父类 QWidget中。参数有很大不同
    //void QWidget::addAction(QAction      * action);

    //This convenience function creates a new action with text.
    //The function adds the newly created action to the menu's list of actions,
    //and returns it.  QMenu takes ownership of the returned QAction.
    QAction * addAction(const QString      & text); //创建并添加具有文本 text的菜单项并返回之。
    QAction * addAction(const QString      & text    ,
                        const QObject      * receiver,
                        const char         * member  ,
                        const QKeySequence & shortcut = {}
                       );
    //将新建的具有文本 text的按钮(菜单项)的 triggered()信号连接到 receiver的 member槽函数上。
    //This convenience function creates a new action with the
    //text text and an optional shortcut shortcut.
    //The action's triggered() signal is connected to the receiver's member slot.


    //This convenience function creates a new action with an icon and some text.
    QAction * addAction(const QIcon        & icon,
                        const QString      & text);
    QAction * addAction(const QIcon        & icon, //同理,注释略
                        const QString      & text,
                        const QObject      * receiver,
                        const char         * member,
                        const QKeySequence & shortcut = {}
                       );
    //将新建的具有文本 text,图片 icon的按钮的 triggered()信号连接到 receiver的 member槽函数上。

    // addAction(QString): 本函数要求形参 Obj类型是 QObject的子类型。
    //Connect to a QObject slot / functor or function pointer (with context)
    template<class Obj, typename Func1> // 形参3 slot是形参2 object的槽函数
    inline typename std::enable_if<
            ! std::is_same<const char *, Func1>::value
            && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value,
                                        QAction *>::type
    addAction(const QString & text, const Obj * object,
                    Func1     slot, const QKeySequence & shortcut = {}  )
    {
        QAction * result = addAction(text);

        result->setShortcut(shortcut);

        connect(result, & QAction::triggered, object, std::move(slot));
        return result;
    }

    // addAction(QString): 将新按钮的 triggered()信号绑定到槽函数 slot上。
    //Connect to a functor or function pointer (without context)
    template <typename Func1>    //slot 可能是全局函数,而非某个类的成员函数。
    inline QAction * addAction(const QString & text,
                              Func1 slot, const QKeySequence & shortcut = {}  )
    {
        QAction * result = addAction(text);

        result->setShortcut(shortcut);

        connect(result, & QAction::triggered, std::move(slot));
        return result;
    }

    // addAction(QIcon, QString):
    //Connect to a QObject slot / functor or function pointer (with context)
    template<class Obj, typename Func1>
    inline typename std::enable_if<
        !  std::is_same<const char *, Func1>::value
        && QtPrivate::IsPointerToTypeDerivedFromQObject<Obj*>::Value,
                                        QAction *>::type
    addAction(const QIcon & actionIcon, const QString & text, //带了一个图片
              const Obj   * object, Func1 slot, const QKeySequence &shortcut = {}  )
    {
        QAction * result = addAction(actionIcon, text);

        result->setShortcut(shortcut);

        connect(result, & QAction::triggered, object, std::move(slot));
        return result;
    }

    // addAction(QIcon, QString):
    //Connect to a functor or function pointer (without context)
    template <typename Func1>             //形参 slot 可能是全局函数
    inline QAction * addAction(const QIcon & actionIcon, const QString & text,
                              Func1 slot, const QKeySequence &shortcut = {}  )
    {
        QAction * result = addAction(actionIcon, text);

        result->setShortcut(shortcut);

        connect(result, &QAction::triggered, std::move(slot));
        return result;
    }

    //This convenience function creates a new separator action,
    //i.e. an action with QAction::isSeparator() returning true.
    //The function inserts the newly created action into this menu's list of
    //  actions before action before and returns it.
    //QMenu takes ownership of the returned QAction.
    QAction * insertSeparator(QAction  * before); //在按钮 before的前面插入分隔符
    QAction *    addSeparator();                  //在菜单的最后添加一个分隔符

    //This convenience function creates a new title action,
    //i.e. an action with QAction::isSeparator() returning true but also having text hint.
    //The function inserts the newly created action into this menu's list of
    //actions before action before and returns it.
    //提示的渲染取决于样式和平台。
    //Widget样式可以使用渲染中用于部分的文本信息,或者可以选择忽略它并像简单的分隔符一样渲染部分。
    //QMenu 获得了返回的 QAction 的所有权。
    //总结:看起来依然是在菜单里,在 before前面,创建分隔条,但分隔条具有提示文本 text。
    QAction *  insertSection(QAction * before,                     const QString & text);
    QAction *  insertSection(QAction * before, const QIcon & icon, const QString & text);
    QAction *     addSection(const QString & text); //追加具有文本 text的分隔条
    QAction *     addSection(const QIcon   & icon, const QString & text);

    //This convenience function inserts menu before action before and
    //returns the menus menuAction(). 在按钮 before前插入子菜单 menu。返回子菜单对应的菜单项。
    QAction * insertMenu(QAction * before, QMenu * menu);
    //This convenience function adds menu as a submenu to this menu.
    //It returns menu's menuAction(). This menu does not take ownership of menu.
    QAction *    addMenu(                  QMenu * menu );
    //Appends a new QMenu with title to the menu. The menu takes ownership of the menu.
    //Returns the new menu.
    QMenu   *    addMenu(                      const QString & title);
    QMenu   *    addMenu(const QIcon   & icon, const QString & title);
    //Appends a new QMenu with icon and title to the menu.


}; //完结 class QMenu : public QWidget

QT_END_NAMESPACE

#endif // QMENU_H

(9)

谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhangzhangkeji

谢谢支持

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

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

打赏作者

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

抵扣说明:

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

余额充值