悬停时突出显示自定义 QWidgetAction

2024-04-10

我的应用程序有一个QMenuBar与一些QMenus,其中每个都有多个QActions 和子QMenus。 大部分的QAction- 项目是衍生品QWidgetAction并重新实施QWidgetAction::createWidget方法。

通常,两者QActions and QMenu鼠标悬停时突出显示。 甚至一个QWidgetAction直到这里才惹麻烦:

但一旦我重写QWidgetAction::createWidget返回自定义QWidget

QWidget* MyWidgetAction::createWidget(QWidget* parent) { return new MyWidget(parent); }

突出显示不再起作用。于是我自己实现了:

void MyWidget::set_highlighted(bool h)
{
  setBackgroundRole(h ? QPalette::Highlight : QPalette::Window);
  setAutoFillBackground(h);
}
void MyWidget::enterEvent(QEvent*) override { set_highlighted(true); }
void MyWidget::leaveEvent(QEvent*) override { set_highlighted(false); }

但是,它的行为并不如预期:

我已经知道了enterEvent直到所有子菜单关闭后才会调用该方法,这仅在鼠标离开子菜单或其操作后有一些延迟才会发生(顺便说一句,我如何更改延迟?)。与鼠标移动事件相同。

Question:如何正确重新实现悬停突出显示?用户不应注意到自定义小部件和标准小部件QAction表现不同。 默认是什么QWidgetAction::createWidget我该如何重现它?我已经看过了Qt的源码 https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qwidgetaction.cpp.html#_ZN13QWidgetAction12createWidgetEP7QWidget但这很令人困惑。

重现动画的代码 https://gist.github.com/pasbi/336a75248e1fee2ece7c77a24babfe99

实际生产代码 https://github.com/pasbi/ommpfritt


我认为原因是您没有在小部件上启用鼠标跟踪,因此无法通知父菜单鼠标光标更改其位置。

我建议添加到你的构造函数中MyWidget类这一行:

setMousetracking(true);

Edit #1:
我发现了一个丑陋的技巧,但它似乎有效:

// You WidgetAction class
class MyWidgetAction : public QWidgetAction
{
public:
    MyWidgetAction(QObject *parent = nullptr);
    QWidget* createWidget(QWidget* parent) override {
        w = new MyWidget(parent);
        return w;
    }
    void highlight(bool hl) { w->set_highlighted(hl); }

private:
    MyWidget *w;
};

// In your code
QMenu *menu = ui->menuBar->addMenu("The Menu");
menu->addAction("Standard QAction 1");
menu->addAction("Standard QAction 2");
menu->addMenu("submenu")->addAction("subaction1");
QWidgetAction *a = new MyWidgetAction();
a->setText("My action 1");
a->setParent(menu); // Needed for the trick
menu->addAction(a);
menu->addAction("Standard QAction 3");
menu->addAction("Standard QAction 4");

// The ugly trick
connect(menu, &QMenu::hovered, this, [menu](QAction *act){
    QList<MyWidgetAction*> lCustomActions = menu->findChildren<MyWidgetAction*>();
    for (MyWidgetAction *mwa : lCustomActions){
        mwa->highlight(mwa == act);
    }
});

我看到hovered信号始终正确发送,因此我将其连接到 lambda 以检查每个自定义WidgetAction如果它是当前悬停的项目并在这种情况下手动突出显示。


Edit #2:
为了避免在我的第一次编辑中 lambda 中出现 for 循环,您还可以创建一个事件过滤器来管理鼠标移动时的突出显示:

class WidgetActionFilterObject : public QObject
{
    Q_OBJECT
public:
    explicit WidgetActionFilterObject(QObject *parent = nullptr);

protected:
    bool eventFilter(QObject *obj, QEvent *evt) override {
        if (evt->type() == QEvent::Type::MouseMove){
            QMouseEvent *mouse_evt = static_cast<QMouseEvent*>(evt);
            QAction *a = static_cast<QMenu*>(obj)->actionAt(mouse_evt->pos());
            MyWidgetAction *mwa = dynamic_cast<MyWidgetAction*>(a);
            if (mwa){
                if (last_wa && mwa != last_wa){
                    last_wa->highlight(false);
                }
                mwa->highlight(true);
                last_wa = mwa;
            } else {
                if (last_wa){
                    last_wa->highlight(false);
                    last_wa = nullptr;
                }
            }
        }
        return QObject::eventFilter(obj, evt);
    }

private:
    MyWidgetAction *last_wa = nullptr;
};

然后你唯一要做的就是安装一个事件过滤器 https://doc.qt.io/qt-5/eventsandfilters.html#event-filters在包含您的自定义的每个菜单上WidgetAction:

menu->installEventFilter(new WidgetActionFilterObject(this));

并且您将获得相同的结果,而无需在每个上循环hovered signal.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

悬停时突出显示自定义 QWidgetAction 的相关文章

随机推荐

  • 从 R 中单列中的所有数据中删除前缀

    我会有一个列 其中的数据如下所示 M999 00001 M999 00002 有没有办法删除R中列中的所有 M 我们可以用sub df1 1 lt sub df1 1 Or use substring substring df1 1 2 d
  • 将多个字符列更改为日期

    我有多个字符列 大约 20 个 我想将它们全部更改为日期格式并使用 r 删除时间 我试过了loops mutate and apply 这是仅使用两列的一些示例数据 col1 c 2017 04 01 23 00 00 2017 03 03
  • 从字符串解方程得到 C 的结果

    我想知道是否有人有关于如何做一些听起来很简单但在尝试编程时看起来并不像的事情的信息或经验 这个想法是 给出一个包含方程的字符串 例如 2 x 10 这很简单 但它可能会变得非常复杂 例如 sqrt 54 35 x 2 等等on 程序将返回
  • Count() 和左连接问题

    我在查询时遇到问题 该查询显示商店列表以及与其关联的产品数量 我已经玩左连接等有一段时间了 但没有成功 这些表具有以下结构 商店表包含列 id name 产品表包含列 id name status shop 查询如下 select s na
  • 在 Angular 2 中使用普通 js 代码 (angular-cli)

    我正在努力实施Vanilla Tilt JS 插件 https micku7zu github io vanilla tilt js 在我的项目中 但我什至似乎找不到在我的项目中使用 vanilla js 导入的方法 到目前为止 我已经尝试
  • Windows 7 家庭高级版上的 Visual Studio 2008/2010 和 SQL Server 2008

    在 Windows 7 Home Premium 上使用 VS 2008 2010 和 SQL Server 2008 开发 ASP NET 和 WPF 应用程序是否有任何限制 我知道您可以在 Home Premium 上运行 IIS 7
  • 从程序集文件加载的类型不等于在 .NET Core 中引用时的同一类型

    我拿一个Type 查询其程序集位置 然后从同一地址加载该程序集 并从加载的程序集中查找相同类型的程序集 结果类型不等于原始类型 这是测试用例 TestMethod public void TestTypeLoadingWithFilePat
  • 如何将整数数组划分为偶数和奇数?

    我想对数组进行分区 例如 1 2 3 4 5 6 7 8 第一个分区应保留偶数值 第二个分区应保留奇数值 结果示例 2 4 6 8 1 3 5 7 我设法用内置解决了这个问题两次Array prototype方法 第一个解决方案使用map
  • 根据一列中的不同值获取行

    如何通过不同的值获取行COL2 例如 我有下面的数据框 COL1 COL2 a com 22 b com 45 c com 34 e com 45 f com 56 g com 22 h com 45 我想根据中的唯一值获取行COL2 CO
  • 我需要采取哪些步骤来向我的 blogger/blogspot 博客添加良好的 Java 代码格式? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一系列步骤来将 java 代码格式添加到我的 blogspot 博客 我真的在寻找一个傻瓜指
  • 使用 Firebase 和 S3

    我正在使用 firebase 和 ionic Angular JS 创建一个应用程序 我想知道是否可以使用 amazon s3 来托管照片 并将 url 来自 s3 存储在 firebase 中 并将其提供给用户 我想这样做 因为 fire
  • JavaScript 排序函数如何工作(作为一种算法)? [复制]

    这个问题在这里已经有答案了 JavaScript带参数的排序函数 http www javascriptkit com javatutors arraysort shtml允许传入一个函数 例如 var myarray 25 8 7 41
  • 如何在 Lucene 6 中对数字字段进行排序

    我想根据数字字段对搜索结果进行排序 在下面的示例代码中 我想根据 年龄 字段进行排序 我从使用以下答案开始 如何在 Lucene 6 中对 IntPont 或 LongPoint 字段进行排序 https stackoverflow com
  • 修改framework.jar中的java代码

    我手机上的库存 ROM 与 MVNO 移动虚拟网络运营商 存在问题 基本上这意味着我的数据连接仅在漫游时有效 这是一个已知问题 已在多个 ROM 上得到修复 但我的尚未修复 为了解决这个问题 我想修改framework jar文件的源 sy
  • 如何在 Xcode 5 中重命名项目?

    如何在 Xcode 5 中重命名项目 我需要采取什么步骤 在过去 这始终是一个非常棘手的手动过程 嗯 答案在 Xcode 5 中非常非常简单 在左侧的项目导航器中 缓慢单击 2 次 项目文件名将可编辑 输入新名称 将出现一个带有警告的表 并
  • maven zip uber-jar 和 shell 脚本

    我希望 Maven 能够将由 shade plugin 创建的 uber jar 和 all files 目录中的 shell 脚本结合起来 项目结构如下所示 all files mvn script sh projB shaded jar
  • 在MySql中加入DELETE?如何?

    我有这个 query DELETE FROM classified sql table WHERE classified ad id id AND classified classified id sql table classified
  • 如何在 SQLAlchemy 和 Firebird 中将 Python 列表绑定为自定义查询中的参数?

    环境 我使用 Firebird 数据库和 SQLAlchemy 作为 ORM 包装器 背景 我知道通过使用in 可以通过sales id列出在IN子句并得到结果 我有一个必须使用的用例文本sql Question 这是我的片段 conn e
  • 如何解决 macOS 中的 zsh: command not found: flutterfire 问题?

    我跟着document https firebase flutter dev docs overview using the flutterfire cli在我的 flutter 应用程序中添加 firebase 我收到 1 条警告和消息
  • 悬停时突出显示自定义 QWidgetAction

    我的应用程序有一个QMenuBar与一些QMenus 其中每个都有多个QActions 和子QMenus 大部分的QAction 项目是衍生品QWidgetAction并重新实施QWidgetAction createWidget方法 通常