复杂上下文菜单子菜单

时间:2019-05-18 18:56:44

标签: python pyqt pyqt5 contextmenu

我有一个主要由上下文菜单驱动的Qt5应用程序。

现在,我具有菜单,子菜单和操作的标准结构。

我想代替子菜单添加一个带有一些输入小部件的小对话框,如下所示:

Context-menu mockup

有没有(可能很简单)的方法来获得这个?

我知道我可以从弹出窗口中打开一个普通对话框,但这不是我的意思。 我希望子菜单正常运行,如果可能的话,可以返回上级菜单。

注意:我实际上是在使用PyQt5,但是我认为这是一个更一般的Qt问题。

1 个答案:

答案 0 :(得分:0)

@ G.M。之后建议可以部分解决我的问题。

我的代码当前代码如下:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class ActionFont(QWidgetAction):
    def __init__(self, parent: QWidget, target: QPlainTextEdit):
        super(ActionFont, self).__init__(parent)
        self.setIcon(QIcon("font-face.svg"))
        self.setText("Face")
        w = QFontComboBox()
        w.currentFontChanged.connect(self.doit)
        self.setDefaultWidget(w)
        self.cursor = target.textCursor()
        self.char_format = self.cursor.charFormat()
        font = self.char_format.font()
        w.setCurrentFont(font)
        # self.triggered.connect(self.doit)

    def doit(self, font):
        self.char_format.setFont(font)
        self.cursor.setCharFormat(self.char_format)


class ActionSize(QWidgetAction):
    def __init__(self, parent: QWidget, target: QPlainTextEdit):
        super(ActionSize, self).__init__(parent)
        self.setIcon(QIcon("font-size.svg"))
        self.setText("Size")
        self.has_changed = False
        w = QSpinBox()
        self.setDefaultWidget(w)
        self.cursor = target.textCursor()
        self.char_format = self.cursor.charFormat()
        font = self.char_format.font()
        size = font.pointSize()
        w.setRange(6, 100)
        w.setValue(size)
        w.valueChanged.connect(self.doit)
        w.editingFinished.connect(self.quit)

    def doit(self, size):
        print(f'ActionSize.doit({size})')
        self.char_format.setFontPointSize(size)
        self.cursor.setCharFormat(self.char_format)
        self.has_changed = True

    def quit(self):
        print(f'ActionSize.quit()')
        if self.has_changed:
            print(f'ActionSize.quit(quitting)')


class Window(QMainWindow):
    def __init__(self, parent=None):
        from lorem import text
        super().__init__(parent)
        self.text = QPlainTextEdit(self)
        self.setCentralWidget(self.text)

        self.text.setContextMenuPolicy(Qt.CustomContextMenu)
        self.text.customContextMenuRequested.connect(self.context)

        self.text.appendPlainText(text())

        self.setGeometry(100, 100, 1030, 800)
        self.setWindowTitle("Writer")

    def context(self, pos):
        m = QMenu(self)
        w = QComboBox()
        w.addItems(list('ABCDE'))
        wa = QWidgetAction(self)
        wa.setDefaultWidget(w)
        m.addAction('Some action')
        m.addAction(wa)
        m.addAction('Some other action')
        sub = QMenu(m)
        sub.setTitle('Font')
        sub.addAction(ActionFont(self, self.text))
        sub.addAction(ActionSize(self, self.text))
        m.addMenu(sub)

        pos = self.mapToGlobal(pos)
        m.move(pos)
        m.show()


app = QApplication([])

w = Window()
w.show()

app.exec()

这有一些限制:

  • 如果我尝试使用setDefaultWidget(),我只能添加一个小部件 添加填充QWidget或容器(例如:QFrame)在菜单中什么也没有出现。
  • 因此,我无法在小部件前添加图标(或QLabel)。
  • 窗口小部件的行为不像菜单项(激活时不会关闭);我试图克服在ActionSize中实现的问题,但看上去相当笨拙,我不确定这是否是正确的方法。

因此,我接受我自己的答案,希望有人可以对其进行足够的改进以使其普遍有用。