Qt中带有子菜单的可点击菜单项

时间:2010-09-22 16:51:22

标签: c++ qt menu

我在Qt 4.6写作。我想知道是否有可能实现这样的菜单项,它可以被触发,但也有一个子菜单。单击它会触发相关操作,将鼠标悬停会显示子菜单。

3 个答案:

答案 0 :(得分:1)

首先我要说这不是一个好的攻击计划。这里有一些极端情况需要花费大量的时间和代码才能做到正确,并且可能需要按操作系统进行定制。

然而,据说,实际的实施并不太复杂。只需将您正在创建子菜单的QMenu子类化,并覆盖事件处理程序,在进行“选择”时强制关闭父菜单。像下面这样的东西基本上有效:

from PyQt4 import QtCore, QtGui
import sys

app = QtGui.QApplication(sys.argv)
widget = QtGui.QMainWindow()
widget.resize(250,150)
menu = widget.menuBar().addMenu("test")

class submenu(QtGui.QMenu):                   #Override the submenu class
    def __init__(self,name):
        QtGui.QMenu.__init__(self,name)
    def mouseReleaseEvent(self,event):    #catch mouseRelease Events
        global menu
        QtGui.QMenu.mouseReleaseEvent(self,event)
        if not self.rect().contains(event.pos()):
            print("Parent Selected")
            menu.hide()                  #If the parent was selected, hide it
        else:                            #Likely ignore these
            print("Parent NOT Selected")

def c():
    print("Sub-item selected")
cMenu = submenu("Sub-menu")
menu.addMenu(cMenu)
actionC = QtGui.QAction("sub-item",widget)
actionC.triggered.connect(c)
cMenu.addAction(actionC)

widget.show()

sys.exit(app.exec_())

答案 1 :(得分:0)

这种行为有点令人困惑,但我试图用尽可能少的点击来开发UI。虽然有点意外,但这种行为使你在习惯它时使用起来会快一些。

我在上一条消息中没有写过,但是我用c ++编写,我不知道python ...无论如何我设法将想法翻译成c ++,但是它很有效但是很难看......我通过查看qt源找到了一个更好的方法(当我问这个问题时,我希望有一些更好的,“预期的”方法)

class MyMenu : public QMenu
{
Q_OBJECT
public:
    MyMenu(QWidget* parent);

    ~MyMenu();

    virtual void mouseReleaseEvent( QMouseEvent * event );

};

MyMenu::MyMenu(QWidget* parent):QMenu(parent)
{
}

MyMenu::~MyMenu()
{
}

void MyMenu::mouseReleaseEvent( QMouseEvent * event ){
  QAction* act = menuAction();
  if (act){
    QMenu* men = act->menu();
    act->setMenu(0);

    QMenu::mouseReleaseEvent(event);
    act->setMenu(men);
  }else{
    QMenu::mouseReleaseEvent(event);
  }
}

唯一的缺点是这样的菜单会对单击子菜单的所有选项做出反应,而不仅仅是所需的选项。也许最好检查是否有任何东西与动作的信号有关?

在我的ubuntu上它有效。但是,我想它不适用于Windows,系统专门管理菜单(除非qt使用一些菜单的外观和感觉,而不是系统菜单),但我懒得安装窗口只是为了检查它;)

答案 2 :(得分:0)

void CustomMenu::mouseReleaseEvent( QMouseEvent* event )
{
  QAction* action = menuAction();

  // Filter out submenus. TODO: Is there a better way to do this?
  if ( action && !rect().contains( event->pos() ) ) {
    QMenu* menu = action->menu();

    action->setMenu( 0 );

    QMenu::mouseReleaseEvent( event );
    emit customTriggeredSignal();

    action->setMenu( menu );
  }
  else {
    QMenu::mouseReleaseEvent( event );
  }
}

j_kubikjkerian的两个有用答案结合在一起,顶层菜单子类QMenu中的mouseReleaseEvent()会忽略子菜单的不必要调用。

我将报告该方法是否适用于Windows。