python - 如何使用 PyQT 对话框标题栏上的 "?"(这个小部件是什么)

标签 python pyqt pyqt5

在 PyQt QDialog 的标题栏右侧(见下文,“x”旁边)有一个“?”这应该帮助用户查询对话框窗口上任何其他小部件的帮助。 PyQt Dialog title bar

我应该做什么(以编程方式)才能让它工作。一旦 ”?” isClicked,应该能够捕获下一个单击的小部件并提供工具提示或类似的东西。在PyQt中,我不知道如何捕获“?”上的isClicked事件。

我看过一些帖子,其中的问题是如何制作“?”消失了,但是那里的讨论使用Qt,而不是PyQt,所以我不明白它,而且他们没有谈论我需要的东西。我需要让它按预期工作。请参阅How can I hide/delete the "?" help button on the "title bar" of a Qt Dialog?PyQt4 QInputDialog and QMessageBox window flags

最佳答案

您可以设置 whatsThis属性到您想要的任何小部件:

    self.someWidget.setWhatsThis('hello!')

从那时起,每当您单击“?”时按钮,然后单击该小部件,将显示带有该文本的工具提示。

由于“这是什么”模式是单独设置给小部件的,因此没有简单的方法可以全局捕获它(据我所知),因为如果小部件没有设置“whatsthis”属性,则该功能将无法使用.
另外,每当您进入“这是什么”模式时,光标可能会根据“whatsthis”属性的内容而变化:如果未设置,光标可能会显示“已禁用”图标。

我已经为这个问题创建了一个基本的解决方法,只要模式被激活,它就会自动启用任何子窗口小部件的whatsthis(如果尚未设置):只要EnterWhatsThisMode被触发,它就会自动安装一个充当事件过滤器的自定义对象,并在调用 Whatsthis 事件时发出信号;一旦模式退出,过滤器就会被删除。
我为事件过滤器使用了一个单独的对象,因为无法知道小部件中已经安装了哪些事件过滤器,并且如果您已经安装了父级的事件过滤器,那么自动删除它将会是一个问题。

class WhatsThisWatcher(QtCore.QObject):
    whatsThisRequest = QtCore.pyqtSignal(QtWidgets.QWidget)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.WhatsThis:
            self.whatsThisRequest.emit(source)
        return super(WhatsThisWatcher, self).eventFilter(source, event)


class W(QtWidgets.QWidget):
    def __init__(self):
        QtWidgets.QWidget.__init__(self)
        layout = QtWidgets.QVBoxLayout(self)

        hasWhatsThisButton = QtWidgets.QPushButton('Has whatsThis')
        layout.addWidget(hasWhatsThisButton)
        hasWhatsThisButton.setWhatsThis('I am a button!')

        noWhatsThisButton = QtWidgets.QPushButton('No whatsThis')
        layout.addWidget(noWhatsThisButton)

        self.whatsThisWatchedWidgets = []
        self.whatsThisWatcher = WhatsThisWatcher()
        self.whatsThisWatcher.whatsThisRequest.connect(self.showCustomWhatsThis)

        whatsThisButton = QtWidgets.QPushButton('Set "What\'s this" mode')
        layout.addWidget(whatsThisButton)
        whatsThisButton.clicked.connect(QtWidgets.QWhatsThis.enterWhatsThisMode)

    def event(self, event):
        if event.type() == QtCore.QEvent.EnterWhatsThisMode:
            for widget in self.findChildren(QtWidgets.QWidget):
                if not widget.whatsThis():
                    # install the custom filter
                    widget.installEventFilter(self.whatsThisWatcher)
                    # set an arbitrary string to ensure that the "whatsThis" is
                    # enabled and the cursor is correctly set
                    widget.setWhatsThis('whatever')
                    self.whatsThisWatchedWidgets.append(widget)
        elif event.type() == QtCore.QEvent.LeaveWhatsThisMode:
            while self.whatsThisWatchedWidgets:
                widget = self.whatsThisWatchedWidgets.pop()
                # reset the whatsThis string to none and uninstall the filter
                widget.setWhatsThis('')
                widget.removeEventFilter(self.whatsThisWatcher)
        return super(W, self).event(event)

    def showCustomWhatsThis(self, widget):
        widgetPos = widget.mapTo(self, QtCore.QPoint())
        QtWidgets.QWhatsThis.showText(
            QtGui.QCursor.pos(), 
            'There is no "what\'s this" for {} widget at coords {}, {}'.format(
                widget.__class__.__name__, widgetPos.x(), widgetPos.y()), 
            widget)

关于此的一些注释:

  1. 我使用了一个按钮来激活 Whatsthis 模式,因为在 Linux 上的窗口管理器上没有相应的窗口标题按钮;
  2. 某些小部件可能包含子小部件,您将获得这些子小部件而不是“主”小部件(最常见的情况是 QAbstractScrollArea 后代,例如 QTextEdit 或 QGraphicsView,它们可能返回视口(viewport)、内部“小部件”或滚动条);

关于python - 如何使用 PyQT 对话框标题栏上的 "?"(这个小部件是什么),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59078185/

相关文章:

python - 是否可以手动锁定/解锁队列?

python - 在 Tkinter 中集成 click-Terminal?

python - Docker:主管无法启动uwsgi

python - 如何自定义 QListWidget 背景颜色(而不是 QListWidgetItem)

python - PYQT 背景图像无法正确显示

python - “QString”对象没有属性 'strip' ?

python - PyQt视频帧更新信号(每个视频帧后触发函数)

python - raise_(​​) 函数被忽略

python - 如何在 Python 中计算和绘制 LOWESS 曲线?

pycharm - 如何在 Pycharm 中安装 PyQt5?