QWidget 我们可以获取/修改小部件的现有上下文菜单吗

Posted

技术标签:

【中文标题】QWidget 我们可以获取/修改小部件的现有上下文菜单吗【英文标题】:QWidget can we get/modify existing context menu of a widget 【发布时间】:2014-10-29 08:43:09 【问题描述】:

我有第三方小部件,它为我提供了一些上下文菜单。可以说剪切,复制粘贴,全选。 现在我只想修改现有上下文菜单的粘贴功能。我知道我可以在contextMenuEvent 中从头开始实现整个上下文菜单。但我不想这样做,因为我对其他上下文菜单操作很满意,只想修改粘贴功能。

我在 Mac OSX 上使用 QT 4.8。

如果目前无法做到这一点,有人可以给我链接/参考吗?这样我就可以满足我的利益相关者。

编辑:为了更清楚地了解我想要做的是,出于某种原因禁用粘贴上下文菜单,并希望稍后根据情况/事件启用它。

【问题讨论】:

看看装饰器模式:en.wikipedia.org/wiki/Decorator_pattern 只是为了确保:您的第 3 方小部件是 QWidget,即写在Qt 上吗? @Ezee:是的,我已经看过头文件了。***类继承自 QWidget。 @Merlin069:我已经继承了第三方类。问题是在 contextMenuEvent 中,我可以从头开始创建整个上下文菜单,但我不知道如何获取/修改现有的上下文菜单。 【参考方案1】:

我不确定它是否可以以通用方式完成。 这是一个棘手的解决方案:

contextMenuEvent 中创建对某个插槽的排队调用:

QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);

在插槽中获取可见窗口并找到QMenu。从中获取操作并启用/禁用它们:

Q_SLOT patchMenu()

  QWidgetList widgets = QApplication::topLevelWidgets();
  foreach (QWidget* widget, widgets)
  
    if (QMenu* menu = qobject_cast<QMenu*>(widget))
    
        QList<QAction*> actions = menu->actions();
        // here you can either get an action by index actions[5]
        // or search the action by text
        actions;
    
   

编辑: 这是一个演示此方法的工作示例: 窗口.h

#pragma once
#include <QtGui>

class Window: public QMainWindow

    Q_OBJECT
public:
    Window(QWidget *parent = 0);
;

class A : public QWidget

public:
    virtual void contextMenuEvent(QContextMenuEvent* e);
;

class B : public A

    Q_OBJECT;
public:
    virtual void contextMenuEvent(QContextMenuEvent*);

    Q_SLOT void patchMenu();
;

window.cpp

#include "window.h"

Window::Window(QWidget *parent) : QMainWindow(parent)

    setCentralWidget(new B());


void B::patchMenu()

    QWidgetList widgets = QApplication::topLevelWidgets();
    foreach (QWidget* widget, widgets)
    
        if (QMenu* menu = qobject_cast<QMenu*>(widget))
        
            QList<QAction*> actions = menu->actions();
            // here you can either get an action by index actions[5]
            // or search the action by text
            actions;
        
       


void B::contextMenuEvent(QContextMenuEvent* e)

    QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);
    A::contextMenuEvent(e);


void A::contextMenuEvent(QContextMenuEvent* e)

    QMenu menu;
    QAction* action = new QAction(QIcon(), "text", &menu);
    menu.addAction(action);
    menu.exec(e->globalPos());

【讨论】:

我已应用上述代码并打印出操作文本和快捷方式。此解决方法向我展示了每个小部件的每个操作,但不幸的是上下文菜单操作不存在。尽管如此,解决方法是 +1。 添加了一个您可以运行并确保其正常工作的示例。您无法获取每个小部件的操作,因为它会过滤掉除 QMenu 之外的所有内容。 是的,每个小部件的每个操作我的意思是 QMenu 操作。我已经将您的代码与我的代码进行了比较。唯一的逻辑区别是基类 contextMenuEvent 调用的顺序。我先调用 A::contextMenuEvent(e),然后调用 QMetaObject::invokeMethod(...)。现在我以你的方式应用它,我可以看到上下文菜单操作列表。谢谢哥们:)。但是一个更奇怪的问题是这样做的正确方法吗?我的意思是禁用一项操作,您必须通过所有小部件及其操作。 “遍历”不是问题,但是假设基本小部件每次显示菜单时都不会重新创建操作,您可以在找到时存储指向您需要的操作的指针它是第一次,然后使用这个指针来启用/禁用操作。但如果它确实每次都重新创建操作,那么使用指针会导致崩溃。 说得好,我明白了。不幸的是,我没有***基类的源代码。所以我必须先尝试一下,然后应用最适合我的解决方案。再次感谢您帮助我,接受您的解决方案。竖起大拇指。

以上是关于QWidget 我们可以获取/修改小部件的现有上下文菜单吗的主要内容,如果未能解决你的问题,请参考以下文章

重新映射 qwidget 上的上下文菜单调用

获取 QWidget 初始大小的可靠方法

QWidget::mousePressEvent() 同时在两个小部件上

QWidget 框架

在 JOGL 中跨多个 QWidget 共享 VBO

QWidget 中的 QML 小部件