单击启动按钮后保持菜单打开

时间:2016-01-11 21:52:29

标签: python qt pyqt

我有一个带菜单的QToolButton。单击QToolButton时,将显示菜单。默认行为是,当从菜单中单击操作时,菜单将消失。我怎样才能使菜单保持打开状态直到用户点击其他地方?

以下是显示行为的最小代码:

from PyQt4 import QtGui, QtCore
import sys, os

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    toolButton = QtGui.QToolButton()
    toolButton.setText('Select')
    toolMenu = QtGui.QMenu()
    for i in range(3):
        action = toolMenu.addAction(str(i))
        action.setCheckable(True)
    toolButton.setMenu(toolMenu)
    toolButton.setPopupMode(QtGui.QToolButton.InstantPopup)
    toolButton.show()
    sys.exit(app.exec_())

4 个答案:

答案 0 :(得分:1)

this c ++回答:

无耻地移植此代码
from PyQt4 import QtGui, QtCore
import sys, os

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    toolButton = QtGui.QToolButton()
    toolButton.setText('Select')
    toolMenu = QtGui.QMenu()
    for i in range(3):    
        checkBox = QtGui.QCheckBox(str(i), toolMenu)
        checkableAction = QtGui.QWidgetAction(toolMenu)
        checkableAction.setDefaultWidget(checkBox)
        toolMenu.addAction(checkableAction)
    toolButton.setMenu(toolMenu)
    toolButton.setPopupMode(QtGui.QToolButton.InstantPopup)
    toolButton.show()
    sys.exit(app.exec_())

答案 1 :(得分:0)

我设法找到的最简单的解决方案是添加Thread

static

答案 2 :(得分:0)

我正在寻找完全相同的东西,并使用了three_pineapples的代码,但我无法按照我想要的方式连接它。我以为我会分享我的解决方案以防其他人发现它有用。 按钮功能非常相似,但我的代码包含我将复选框连接到函数的解决方案。此外,由于它们存储在列表中,因此可以单独或循环连接它们,如果这样更容易的话。

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os

##### main window class #####
class main_window(QMainWindow):
    def __init__(self):
        super(main_window, self).__init__()
        self.resize(300, 200)

        wdgMain = QWidget()
        self.setCentralWidget(wdgMain)
        layMain = QGridLayout(wdgMain)
        wdgMain.setLayout(layMain)

        ## checkable tool button ##
        tlbToolButton1 = QToolButtonChx("Check Me Out!")
        layMain.addWidget(tlbToolButton1, 0, 0)
        tlbToolButton1.addItems(["Item" + str(n) for n in range(8)])

        ## connect tool button checkboxes ##
        for i in range(tlbToolButton1.length()):
            tlbToolButton1.index(i).stateChanged.connect(self.checkbox_tester)

    def checkbox_tester(self, choice):
        objSender = self.sender()
        strObjectName = objSender.objectName()
        print "Action Checker::", strObjectName, ":", choice
##### end of main window class #####



##### checkable tool button class #####
class QToolButtonChx(QToolButton):
    def __init__(self, strText=""):
        super(QToolButtonChx, self).__init__()

        self.setText(strText)
        tlbMenu = QMenu(self)
        self.setMenu(tlbMenu)
        self.setPopupMode(QToolButton.MenuButtonPopup)
        self.lstchxItems = []

    def addItem(self, strItem):
        self.lstchxItems.append(QCheckBox(strItem, self.menu()))
        actCheckItem = QWidgetAction(self.menu())
        actCheckItem.setDefaultWidget(self.lstchxItems[-1])
        self.lstchxItems[-1].setObjectName('chx' + strItem)
        self.menu().addAction(actCheckItem)

    def addItems(self, lstItems):
        for strItem in lstItems:
            self.lstchxItems.append(QCheckBox(strItem, self.menu()))
            actCheckItem = QWidgetAction(self.menu())
            actCheckItem.setDefaultWidget(self.lstchxItems[-1])
            self.lstchxItems[-1].setObjectName('chx' + strItem)
            self.menu().addAction(actCheckItem)

    def index(self, intIndex):
        return self.lstchxItems[intIndex]

    def length(self):
        return len(self.lstchxItems)
##### end of checkable tool button class #####


if __name__ == '__main__':
    app = QApplication(sys.argv)
    winMain = QMainWindow()
    gui = main_window()
    gui.show()
    sys.exit(app.exec_())

答案 3 :(得分:0)

我根据@three_pineapples的回答制作了一个PyQt5版本,并解决了@Space Hornet试图解决的问题-获取复选框的状态。

根据doc of QWidgetAction

  

请注意,取决于小部件来激活操作,例如   通过重新实现鼠标事件处理程序并调用QAction :: trigger()。

因此,我认为有人需要将复选框的stateChanged信号连接到操作的trigger方法。

我还向操作添加了一个文本,因此action.text()的文本标签与复选框相同。也许不是必需的。

完整的代码如下:

import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSlot

@pyqtSlot(QtWidgets.QAction)
def menuTriggered(action):
    print('state change=',action.text())
    return

@pyqtSlot(QtWidgets.QMenu)
def buttonTriggered(menu):
    actions=menu.findChildren(QtWidgets.QWidgetAction)
    for actii in actions:
        wii=actii.defaultWidget()
        stateii=wii.isChecked()
        print('action', actii.text(), 'is checked:',stateii)
    return

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    toolButton = QtWidgets.QToolButton()
    toolButton.setText('Select')
    toolMenu = QtWidgets.QMenu()

    for i in range(3):
        checkBox = QtWidgets.QCheckBox(str(i), toolMenu)
        checkableAction = QtWidgets.QWidgetAction(toolMenu)
        checkableAction.setDefaultWidget(checkBox)

        # Add a text to action, for easier handling in slot
        checkableAction.setText(str(i))

        # Connect the checkbox's stateChanged to QAction.trigger
        checkBox.stateChanged.connect(checkableAction.trigger)
        toolMenu.addAction(checkableAction)

    toolMenu.triggered.connect(menuTriggered)
    toolButton.setMenu(toolMenu)
    toolButton.setPopupMode(QtWidgets.QToolButton.MenuButtonPopup)

    # NOTE that toolButton.clicked work, toolButton.triggered not
    toolButton.clicked.connect(lambda: buttonTriggered(toolMenu))
    toolButton.show()
    sys.exit(app.exec_())