PyQt5 QComboBox列表项更改位置 [英] PyQt5 QComboBox list items changing postion

查看:22
本文介绍了PyQt5 QComboBox列表项更改位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一些Qcombobox项目的显示样式问题。目前我硬编码的数据将显示在组合框中。

代码如下:

self.Dummy = QComboBox(self)
self.Dummy.setGeometry(200,600, 350, 50)

self.Dummy.setStyleSheet("QComboBox {background-color: white;border-style: outset;" border-width: 2px;border-radius: 5px;border-color: #448aff; font:  12px; min-width: 10em; padding: 3px;}")

self.Dummy.addItems(["-Select-", "2", "3","4","5","6","7","8","9","0","11",])

问题是,在每次选择后,下拉"列表"的位置都会不断变化。这是我面临的问题的图像。

下面是我的组合框

该列表包含项目<;-Select->,2,3,4,5,6,7,8,9,0,11,其中<;-选择->将是第一个显示的元素。

现在,当我单击该框时,框将列出元素,假设我选择了‘2’。然后,如果我尝试选择另一项,列表将以"向下"的方向放置。见下文

现在,假设从这些项中选择了最后一个元素‘11’。现在,如果我试图通过点击该框来选择一个新的项目,列表将被弹出"向上"而不是向下。见下文

应该做些什么来修复它?我认为这不是样式表的问题,如果没有它,这个问题就会发生。我需要解决这个问题的原因是,当列表弹出时,它覆盖了上面的标签

推荐答案

您看到的是取决于操作系统和样式的行为。

要避免它,最好的方法是将QComboBox子类化并覆盖showPopup(),然后调用基类实现(它负责显示弹出视图、调整大小和定位),并在必要时移动它。

class Combo(QtWidgets.QComboBox):
    def showPopup(self):
        super().showPopup()
        # find the widget that contains the list; note that this is *not* the view
        # that QComboBox.view() returns, but what is used to show it.
        popup = self.view().window()
        rect = popup.geometry()
        if not rect.contains(self.mapToGlobal(self.rect().center())):
            # the popup is not over the combo, there's no need to move it
            return
        # move the popup at the bottom left of the combo
        rect.moveTopLeft(self.mapToGlobal(self.rect().bottomLeft()))
        # ensure that the popup is always inside the edges of the screen
        # we use the center of the popup as a reference, since with multiple
        # screens the combo might be between two screens, but that position
        # could also be completely outside the screen, so the cursor position
        # is used as a fallback to decide on what screen we'll show it
        done = False
        for i, pos in enumerate((rect.center(), QtGui.QCursor.pos())):
            for screen in QtWidgets.QApplication.screens():
                if pos in screen.geometry():
                    screen = screen.geometry()
                    if rect.x() < screen.x():
                        rect.moveLeft(screen.x())
                    elif rect.right() > screen.right():
                        rect.moveRight(screen.right())
                    if rect.y() < screen.y():
                        rect.moveTop(screen.y())
                    elif rect.bottom() > screen.bottom():
                        # if the popup goes below the screen, move its bottom
                        # *over* the combo, so that the its current selected
                        # item will always be visible
                        rect.moveBottom(self.mapToGlobal(QtCore.QPoint()).y())
                    done = True
                    break
            if done:
                break
        popup.move(rect.topLeft())

这也可以在没有子类化的情况下完成(例如,如果您有许多组合,您从Designer创建了UI,并且不想使用提升的小部件),但您必须记住更改对组合的所有引用。

class MyWindow(QtWidgets.QWidget):
    def __init__(self):
        # ...
        self.combo = QtWidgets.QComboBox()
        self.combo.showPopup = self.showPopupAndCheck

    def showPopupAndCheck(self):
        QtWidgets.QComboBox.showPopup(self.combo)
        popup = self.view().window()
        rect = popup.geometry()
        if not rect.contains(self.combo.mapToGlobal(self.combo.rect().center())):
            # the popup is not over the combo, there's no need to move it
            return
        # change everything from self to self.combo

或者,如果您希望在所有程序中保持此行为的一致性,而不总是使用子类,您可以使用某种猴子修补黑客。
优点在于,您创建的任何QComboBox(即使在运行时加载UI文件或创建组合框)都将始终使用新行为。

重要信息:此必须位于程序的文件的最开始位置,可能就在导入部分之后。

from PyQt5 import QtCore, QtGui, QtWidgets

def customShowPopup(self):
    # we can't use super(), because we're not in the class definition, but
    # calling the class method with "self" as first argument is practically the 
    # same thing; note the underscore!
    QtWidgets.QComboBox._showPopup(self)
    popup = self.view().window()
    # ... go on, exactly as above

# create a new reference to the showPopup method, which is the one we've used
# in the function above
QtWidgets.QComboBox._showPopup = QtWidgets.QComboBox.showPopup
# overwrite the original reference with the new function
QtWidgets.QComboBox.showPopup = customShowPopup

这篇关于PyQt5 QComboBox列表项更改位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆