【问题标题】:Overriding QCompleter popup position覆盖 QCompleter 弹出位置
【发布时间】:2021-01-26 13:45:00
【问题描述】:

关于覆盖 QCompleter 弹出位置的问题也有类似的问题,但我仍然找不到有效的解决方案。我只是想将弹出窗口向下移动 5px 左右(我有一些特定的样式要求)

我尝试将 QListView 子类化并使用 setPopup() 将其用作我的弹出窗口。然后我覆盖 showEvent 并将弹出窗口向下移动 Y。我也在 resizeEvent 上执行此操作,因为我相信这是在过滤项目并且弹出窗口调整大小时触发的。但是这不起作用..然后我使用单次计时器在 1 毫秒后触发移动。这确实有效,但似乎很不一致 - 第一次显示与随后的时间或调整大小不同。

以下是我最近的尝试(试图通过计算弹出窗口的数量来破解它..),希望有人能告诉我我做错了什么或更好的解决方案

import sys
import os
from PySide2 import QtCore, QtWidgets, QtGui

class QPopup(QtWidgets.QListView):
    def __init__(self, parent=None):
        super(QPopup, self).__init__(parent)

        self.popups = 0

    def offset(self):
        y = 3 if self.popups < 2 else 7
        print('y: {}'.format(y))
        self.move(self.pos().x(), self.pos().y() + y)

        self.popups += 1

    def showEvent(self, event):
        print('show')
        # self.offset()
        QtCore.QTimer.singleShot(1, self.offset)

    def resizeEvent(self, event):
        print('resize')
        # self.offset()
        QtCore.QTimer.singleShot(1, self.offset)

class MyDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(MyDialog, self).__init__(parent)

        self.create_widgets()
        self.create_layout()
        self.create_connections()

    def create_widgets(self):
        self.le = QtWidgets.QLineEdit('')

        self.completer = QtWidgets.QCompleter(self)
        self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
        self.completer.setMaxVisibleItems(10)
        self.completer.setFilterMode(QtCore.Qt.MatchContains)
        self.completer.setPopup(QPopup())

        popup = QPopup(self)
        self.completer.setPopup(popup)

        self.model = QtCore.QStringListModel()
        self.completer.setModel(self.model)

        self.le.setCompleter(self.completer)

        self.completer.model().setStringList(['one','two','three'])

    def create_layout(self):
        main_layout = QtWidgets.QVBoxLayout(self)

        main_layout.addWidget(self.le)

    def create_connections(self):
        pass

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    my_dialog = MyDialog()

    my_dialog.show()  # Show the UI
    sys.exit(app.exec_())

【问题讨论】:

    标签: python pyside2 qcompleter


    【解决方案1】:

    一种解决方案可能是创建 QLineEdit 的子类并覆盖 keyPressEvent 以显示带有偏移量的弹出窗口:

    PySide2.QtWidgets.QCompleter.complete([rect=QRect()])

    对于 PopupCompletion 和 QCompletion::UnfilteredPopupCompletion 模式,调用此函数会显示显示当前完成的弹出窗口。默认情况下,如果未指定 rect,则弹出窗口显示在 widget() 的底部。如果指定了 rect,则弹出窗口显示在矩形的左边缘。

    doc.qt.io -> QCompleter.complete

    完整、独立的示例

    矩形是根据光标矩形的 y 位置计算的。弹出窗口的高度没有改变。宽度调整为 ZLineEdit 小部件的宽度。

    rect = QtCore.QRect(0,
                        self.cursorRect().y() + 4,
                        self.width(),
                        self.completer().widget().height())
    

    您的代码使用上述要点稍作修改,可能如下所示:

    import sys
    from PySide2 import QtCore, QtWidgets
    from PySide2.QtWidgets import QLineEdit, QDialog, QCompleter
    
    
    class ZLineEdit(QLineEdit):
        def __init__(self, string, parent=None):
            super().__init__(string, parent)
    
        def keyPressEvent(self, event):
            super().keyPressEvent(event)
            if len(self.text()) > 0:
                rect = QtCore.QRect(0,
                                    self.cursorRect().y() + 4,
                                    self.width(),
                                    self.completer().widget().height())
                self.completer().complete(rect)
    
    
    class MyDialog(QDialog):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.le = ZLineEdit('')
            autoList = ['one', 'two', 'three']
            self.completer = QCompleter(autoList, self)
    
            self.setup_widgets()
            self.create_layout()
            self.create_connections()
    
        def setup_widgets(self):
            self.completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
            self.completer.setCompletionMode(QtWidgets.QCompleter.PopupCompletion)
            self.completer.setMaxVisibleItems(10)
            self.completer.setFilterMode(QtCore.Qt.MatchContains)
            self.le.setCompleter(self.completer)
    
        def create_layout(self):
            main_layout = QtWidgets.QVBoxLayout(self)
            main_layout.addWidget(self.le)
    
        def create_connections(self):
            pass
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        my_dialog = MyDialog()
        my_dialog.show()
        sys.exit(app.exec_())
    

    测试

    在左侧,您会看到默认行为。在右侧弹出窗口向下移动了 4px:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 2016-11-21
      • 2020-09-23
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多