如何为QTreeWidgetItem的每个*类型*创建不同的弹出(上下文)菜单

sam*_*bha 2 c++ qt

我能够为我的QTreeWidget创建一个上下文菜单,如下所示

QMenu* pContextMenu = new QMenu(this)
QTreeWidget* pTreeWidget = new QTreeWidget();
QAction* pOpenFile = new QAction(tr("Open A File"), pContextMenu);
pTreeWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
pTreeWidget->addAction(pOpenFile);
Run Code Online (Sandbox Code Playgroud)

但我想要一个分支的不同弹出窗口而不是叶子.如何根据单击的widgetitem类型分配不同的弹出窗口?

我的树:

  • Branch1 < - Popup1
    • Leaf1
    • Leaf2 < - Popup2
  • 店2
    • 店3
      • Leaf1

QWidget :: actions()未列为虚拟.否则我会从QTreeWidget和reimplemented actions()派生我自己的类.

jmk*_*jmk 6

方法1:覆盖QTreeWidget

QTreeWidget如您所发现的,分配给自身的上下文菜单将不允许您为不同的项目设置不同的上下文菜单.

由于Qt项目视图没有上下文菜单的特殊API,您必须自己实现.幸运的是,这并不是很困难; 你只需要:

  1. 创建一个子类QTreeWidget.
  2. customContextMenuRequested(const QPoint&)信号连接到自定义插槽.
  3. 显示所需的上下文菜单.

我发布了一个完整的工作示例.需要注意的一些细节包括:

  • QTreeWidgetItem提供了一个方便的type属性,让您轻松识别项目,无需强制转换,字符串解析或其他笨拙/脆弱的方法.

  • 自定义QTreeWidgetItem类型值应大于或等于QTreeWidgetItem::UserType.

  • 显示上下文菜单时,必须将全局位置传递给exec().要从插槽中窗口小部件空间中的位置正确映射,必须使用项目的视口窗口小部件.


方法2:覆盖QItemDelegate(和QTreeWidget ...)

另一种方法是实现自己的QAbstractItemDelegate子类,并将其分配给树小部件.在您的项目委托中,您可以覆盖editorEvent()以相同的方式处理鼠标按下.

虽然这种方法实际上更符合Qt的项目视图API设计,但这种方法有一些关键的缺点:

  • Item委托使用QModelIndex对象来表示项目.要转换为a QTreeWidgetItem,您必须使用该QTreeWidget::itemFromIndex()方法.不幸的是,这是受保护的,因此它实际上会要求您继承子类QTreeWidget为您的委托提供此API.这为您的代码增加了一些样板复杂性.

  • editorEvent()项目视图处理该事件之前,钩子被调用.这意味着您无法轻松显示上下文菜单并同时允许默认行为(例如选择右键单击的项).

  • 由于editorEvent()处理程序会看到各种不同的事件,因此您必须更加小心地正确处理它们.如果您的行为很复杂,您还必须小心不要让这个单片处理程序失去控制.

核心代码非常相似,但同样,还有更多的样板.我也发布了这种方法的一个例子.