【问题标题】:PyQt5 QScrollArea does not scroll, resizes items insteadPyQt5 QScrollArea 不滚动,而是调整项目大小
【发布时间】:2019-04-26 09:10:42
【问题描述】:

我遇到的问题完全让我发疯。

我正在使用 PyQt5 在 Python 上编写 GUI 应用程序。我的应用程序由多个 QGroupBoxes 组成,当用户在它们之间切换时它们变得可见和不可见。

其中一个 QGroupBoxes 包含 QScrollArea,其中放置了另一个 QGroupBoxes。当用户向应用程序添加信息时,可能会添加新的 QGroupBoxes,因此当添加的元素过多时,QScrollArea 应该允许查看所有这些。

所以元素的结构是:

QGroupBox
=>QScrollArea
=>=>QScrollAreaWidgetContents
=>=>=>QVBoxLayout
=>=>=>=>QGroupBox
=>=>=>=>=>QFormLayout
=>=>=>=>QGroupBox
=>=>=>=>=>QFormLayout

但是,即使我将内部 QGroupBoxes 放置在垂直布局中,然后放置在单个 QScrollAreaWidgetContents 中,QScrollArea 也不会显示任何滚动条,而是调整内部元素的大小,因此看起来像这样。

我的问题可以用这个例子来概括:

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(415, 213)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(0, 0, 801, 601))
        self.groupBox.setObjectName("groupBox")
        self.scrollArea = QtWidgets.QScrollArea(self.groupBox)
        self.scrollArea.move(10, 30)
        self.scrollArea.setFixedWidth(380)
        self.scrollArea.setMinimumHeight(160)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.move(0, 0)
        self.scrollAreaWidgetContents.setFixedWidth(378)
        self.scrollAreaWidgetContents.setMinimumHeight(158)
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        MainWindow.setCentralWidget(self.centralwidget)

       QtCore.QMetaObject.connectSlotsByName(MainWindow)

class competencyBox(QWidget):
    def __init__(self, parent):
        super(competencyBox, self).__init__(parent)
        self.compCodeLineEdit = QLineEdit()
        self.compDescrpTextEdit = QTextEdit()
        self.box = QGroupBox(self)
        self.form_lay = QFormLayout(self)
        self.form_lay.addRow(QLabel("Код: "), self.compCodeLineEdit)
        self.form_lay.addRow(QLabel("Описание: "), self.compDescrpTextEdit)
        self.box.setLayout(self.form_lay)
        self.box.setFixedSize(510, 240)

class test_window(QMainWindow):
    def __init__(self):
        super(test_window, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.addBox(self.ui.scrollAreaWidgetContents, competencyBox, 4)

    def addBox(self, parent, element, number):
        vert_lay = QVBoxLayout(parent)
        for i in range(number):
            e = element(parent)
            vert_lay.addWidget(e)
        vert_lay.setSpacing(5)

如你所见,我尝试了不同的方法,例如为内部 QGroupBoxes 设置固定大小、在垂直布局中添加间距等,但 QScrollArea 仍然忽略它们并缩小内部元素。我被卡住了,不知道如何解决我的问题。请帮我。

【问题讨论】:

  • 这个人的问题与我几乎相同,但他的解决方案不适用于我:stackoverflow.com/questions/12781407/… 因为我已经将setWidgetResizeable(True) 应用于我的 QScrollArea。
  • mmmm,这跟我的要求有什么关系?
  • 这个问题通常不是由 QScrollArea 引起的,而是由 OP 代码的另一部分引起的,所以这就是我向你要 MCVE 的原因
  • 我建议您在以后的场合提供minimal reproducible example,代码片段可以很好地说明或解释问题,但不能解决问题:我想要 X,我做 Y,但它没有工作,因为错误可能在你代码的隐藏部分,我们永远不会知道,这就是为什么 SO 引入 MCVE 的概念

标签: python python-3.x pyqt pyqt5 qt-designer


【解决方案1】:

在您的情况下的主要问题是 scrollAreaWidgetContents 不应具有固定大小,因为它是小部件的容器,如果您使用 self.scrollAreaWidgetContents.setFixedWidth (378) 您正在设置它,则 scrollAreaWidgetContents 的大小应该是设定的大小。小部件通过 QVBoxLayout。

另一个问题是 CompetencyBox 必须使用布局来设置 QGroupBox。

from PyQt5 import QtCore, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(415, 213)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.groupBox = QtWidgets.QGroupBox(self.centralwidget)
        self.groupBox.setGeometry(QtCore.QRect(0, 0, 801, 601))
        self.groupBox.setObjectName("groupBox")
        self.scrollArea = QtWidgets.QScrollArea(self.groupBox)
        self.scrollArea.move(10, 30)
        self.scrollArea.setFixedWidth(380)
        self.scrollArea.setMinimumHeight(160)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        MainWindow.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

class CompetencyBox(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(CompetencyBox, self).__init__(parent)
        self.compCodeLineEdit = QtWidgets.QLineEdit()
        self.compDescrpTextEdit = QtWidgets.QTextEdit()
        lay = QtWidgets.QVBoxLayout(self)
        box = QtWidgets.QGroupBox()
        lay.addWidget(box)
        form_lay = QtWidgets.QFormLayout()
        form_lay.addRow(QtWidgets.QLabel("Код: "), self.compCodeLineEdit)
        form_lay.addRow(QtWidgets.QLabel("Описание: "), self.compDescrpTextEdit)
        box.setLayout(form_lay)
        box.setFixedSize(510, 240)

class Test_Window(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Test_Window, self).__init__(parent)
        self.setupUi(self)
        self.addBox(self.scrollAreaWidgetContents, CompetencyBox, 4)

    def addBox(self, parent, element, number):
        vert_lay = QtWidgets.QVBoxLayout(parent)
        for i in range(number):
            vert_lay.addWidget(element())
        vert_lay.setSpacing(5)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = Test_Window()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

【讨论】:

  • 但是,我想澄清一些事情。为什么我们要把 QGroupBox 放在另一个布局中?看来我已经在addBox() 方法中完成了这项工作。 PyQt 还不断通知我,QLayout: Attempting to add QLayout "" to competencyBox "", which already has a layout。除此之外,一切都很完美。
  • @Anton 你是在使用我的代码还是修改了它?,我没有生成那个警告。
  • @Anton 如果您修改了我的代码,我可能在我的解释中省略了一些您可能尚未实现的内容,另一方面,如果您使用我的代码而不修改任何内容,则可能是版本问题你用的是什么版本的 PyQt5?
  • 我没有修改你的代码。使用 PyQt5 5.11.3。我还发现,lay = QtWidgets.QVBoxLayout(self) 行会导致警告(以及任何其他布局的使用),但删除此行会导致 QGroupBoxes 再次缩小,所以无论如何我都会使用你的方法。
猜你喜欢
  • 2016-02-16
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多