Слот для новых предметов на указанных позициях в QMenu

Я пытаюсь добиться следующего дизайна QMenu:

|  Add New Item  |
------------------
|   New Item 1   |
|   New Item 2   |
|   New Item 3   |
------------------
| Default Item 1 |
| Default Item 2 |

Предположим, если это новый QMenu, дизайн по умолчанию выглядит как-то неправдоподобно:

|  Add New Item  |
------------------
| Default Item 1 |
| Default Item 2 |

В моем коде, хотя я могу создать новый элемент, у меня есть 2 проблемы.

  1. Для любого из новых предметов, которые я указал при использовании опции - Add new item3 параметра по умолчанию повторно добавляются в QMenu, что приводит к дублированию параметров... Если я добавлю в self.qmenu.clear()пока он разрешает дублированные элементы по умолчанию, новые элементы не будут заполнены...

  2. Можно ли разместить новые предметы в промежутке между add new item а также default items? Или объединить 2 qmenus в одно, что-то похожее на то, как вы добавляете виджеты в QVBoxLayout, где вы можете контролировать порядок?

Заранее признателен за любые идеи.

class Example(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Example, self).__init__(parent)
        self.initUI()


    def initUI(self):         
        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Context menu')    
        self.qmenu = QtGui.QMenu()

    def contextMenuEvent(self, event):
        # self.qmenu.clear()

        # For adding in new item(s)
        add_item_action = QtGui.QAction('Add new item', self)
        slot = functools.partial(self.add_new_item)
        add_item_action.triggered.connect(slot)
        self.qmenu.addAction(add_item_action)
        self.qmenu.addSeparator()

        # Default items
        def_item_01 = self.qmenu.addAction("Default Item A")
        def_item_02 = self.qmenu.addAction("Default Item B")
        action = self.qmenu.exec_(self.mapToGlobal(event.pos()))

    def add_new_item(self):
        new_item_name = raw_input('Name of new item : ')
        if new_item_name:
            self.qmenu.addSeparator()
            # The new items should be checked upon created
            new_action = QtGui.QAction(new_item_name, self.qmenu, checkable=True)
            new_action.setChecked(True)
            self.qmenu.addAction(new_action)

my_win = Example()
my_win.show()

1 ответ

Решение

Сколько раз ты звонишь contextMenuEvent? каждый раз, когда вы нажимаете вправо, чтобы постоянно добавлять элементы по умолчанию, вам не кажется, что лучше добавить его только один раз, чтобы не добавлять дубликаты?, что является правильным решением.

С другой стороны, если вы хотите вставить элемент в QMenu ты должен использовать insertAction(),

И, наконец, не использовать raw_input() (или же input() в python3), поскольку они блокируют и замораживают графический интерфейс, лучше всего использовать диалог, который запрашивает у вас данные.

class Example(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Example, self).__init__(parent)
        self.initUI()

    def initUI(self):         
        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Context menu')    

        self.qmenu = QtGui.QMenu()
        add_item_action = QtGui.QAction('Add new item', self,
            triggered=self.add_new_item)
        self.qmenu.addAction(add_item_action)
        self.qmenu.addSeparator()

        self.separator =  self.qmenu.addSeparator()
        # Default items
        def_item_01 = self.qmenu.addAction("Default Item A")
        def_item_02 = self.qmenu.addAction("Default Item B")

    def contextMenuEvent(self, event):
        action = self.qmenu.exec_(self.mapToGlobal(event.pos()))

    @QtCore.pyqtSlot()
    def add_new_item(self):
        new_item_name, ok = QtGui.QInputDialog.getText(self, "name of item", "Name of new item : ")
        if ok:
            new_action = QtGui.QAction(new_item_name, self.qmenu, checkable=True)
            self.qmenu.insertAction(self.separator, new_action)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    my_win = Example()
    my_win.show()
    sys.exit(app.exec_())
Другие вопросы по тегам