首页 > 解决方案 > PyQt5 将小部件大小设置为最小并修复

问题描述

def __init__(self):
    super().__init__()
    self.order_list = [str(i) * 2 * i for i in range(20)]
    self.space = 18
    self.init_ui()

def init_ui(self):
    self.setGeometry(300, 300, 300, 300)

    self.layout = Qw.QGridLayout(self)

    self.menu = Qw.QWidget()
    self.menu.setFixedHeight(self.space * len(self.order_list) + 5)
    self.menu.items = []
    for n, i in enumerate(self.order_list):
        btn = Qw.QCheckBox(i, self.menu)
        btn.move(5, self.space * n + 5)
        btn.setFixedHeight(15)
        self.menu.items.append(btn)
    self.menu_scroll = Qw.QScrollArea()
    self.menu_scroll.setWidgetResizable(True)
    self.menu_scroll.setWidget(self.menu)
    self.layout.addWidget(self.menu_scroll, 0, 0, 1, 1)
    self.layout.setColumnStretch(0, 10)

    self.rec = Qw.QWidget()
    self.rec_box = Qw.QVBoxLayout(self.rec)
    self.rec.setLayout(self.rec_box)
    self.rec_scroll = Qw.QScrollArea()
    self.rec_scroll.setWidget(self.rec)

    self.layout.addWidget(self.rec_scroll, 0, 1, 1, 1)
    self.layout.setColumnStretch(1, 9)

    self.order_btn = Qw.QPushButton('Order')
    self.order_btn.setFixedSize(80, 30)
    self.order_btn.clicked.connect(self.get_ordered)
    self.layout.addWidget(self.order_btn, 1, 0, 1, 2, alignment=Qc.Qt.AlignCenter)

所以我有这个代码。它由带有两个 QScrollAreas 和一个按钮的网格布局组成。我需要将 self.menu 的大小设置为固定,这样它就可以一直滚动到它不够大的时候。已经垂直这样做了,但是我如何才能将菜单调整为最大的小部件大小?将 WidgetResizeable 设置为 False 只会使 ScrollArea 为空。(不要看右边的区域,我会在左边的区域被照顾的时候改变它)

我还应该提到,需要在单击 order_btn 时添加一些小部件。这就是带有 Layouts 的代码的工作方式,但它破坏了间距和位置。

def __init__(self):
    super().__init__()
    self.order_list = [str(i) * 2 * i for i in range(20)]
    self.space = 10
    self.init_ui()

def init_ui(self):
    self.setGeometry(300, 300, 300, 300)

    self.layout = Qw.QGridLayout(self)

    self.menu = Qw.QWidget()
    lay = Qw.QVBoxLayout(self.menu)
    self.menu.items = []
    for n, i in enumerate(self.order_list):
        btn = Qw.QCheckBox(i)
        btn.setFixedHeight(15)
        lay.addWidget(btn)
        self.menu.items.append(btn)

    self.menu_scroll = Qw.QScrollArea(widgetResizable=True)
    self.menu_scroll.setWidget(self.menu)
    self.layout.addWidget(self.menu_scroll, 0, 0, 1, 1)
    self.layout.setColumnStretch(0, 10)

    self.rec = Qw.QWidget()
    self.rec.items = []
    self.lay2 = Qw.QVBoxLayout(self.rec)
    for n, i in enumerate(self.order_list):
        btn = Qw.QCheckBox(i)
        btn.setFixedHeight(15)
        self.lay2.addWidget(btn)
        self.rec.items.append(btn)

    self.rec_scroll = Qw.QScrollArea(widgetResizable=True)
    self.rec_scroll.setWidget(self.rec)
    self.layout.addWidget(self.rec_scroll, 0, 0, 1, 1)
    self.layout.setColumnStretch(0, 10)

    self.layout.addWidget(self.rec_scroll, 0, 1, 1, 1)
    self.layout.setColumnStretch(1, 9)

    self.order_btn = Qw.QPushButton('Order')
    self.order_btn.setFixedSize(80, 30)
    self.order_btn.clicked.connect(self.get_ordered)
    self.layout.addWidget(self.order_btn, 1, 0, 1, 2, alignment=Qc.Qt.AlignCenter)

@Qc.pyqtSlot()
def get_ordered(self):
    try:
        while self.rec.items:
            self.rec.items.pop(-1).deleteLater()
        n = 0
        for i in self.menu.items:
            if i.checkState():
                item = Qw.QLabel()
                item.setFixedHeight(15)
                item.setText(i.text())
                item.show()
                self.rec.items.append(item)
                self.lay2.addWidget(item)
                n += 1
    except Exception as error:
        print(error)

标签: pythonpyqtpyqt5qscrollarea

解决方案


你不需要计算任何东西,如果你添加一个项目,你会重新计算吗?你应该做的是使用 QVBoxLayout 来计算正确的大小:

from PyQt5 import QtCore as Qc
from PyQt5 import QtWidgets as Qw

class Widget(Qw.QWidget):
    def __init__(self):
        super().__init__()
        self.order_list = [str(i) * 2 * i for i in range(20)]
        self.init_ui()

    def init_ui(self):
        self.setGeometry(300, 300, 300, 300)

        layout = Qw.QGridLayout(self)

        self.menu = Qw.QWidget()
        lay = Qw.QVBoxLayout(self.menu)
        self.menu.items = []
        for n, i in enumerate(self.order_list):
            btn = Qw.QCheckBox(i)
            btn.setFixedHeight(15)
            lay.addWidget(btn)
            self.menu.items.append(btn)
        lay.addStretch()

        self.menu_scroll = Qw.QScrollArea(widgetResizable=True)
        self.menu_scroll.setWidget(self.menu)
        layout.addWidget(self.menu_scroll, 0, 0, 1, 1)
        layout.setColumnStretch(0, 10)

        self.rec = Qw.QWidget()
        self.rec_box = Qw.QVBoxLayout(self.rec)
        self.rec_scroll = Qw.QScrollArea()
        self.rec_scroll.setWidget(self.rec)

        layout.addWidget(self.rec_scroll, 0, 1, 1, 1)
        layout.setColumnStretch(1, 9)

        self.order_btn = Qw.QPushButton('Order')
        self.order_btn.setFixedSize(80, 30)
        self.order_btn.clicked.connect(self.get_ordered)
        layout.addWidget(self.order_btn, 1, 0, 1, 2, alignment=Qc.Qt.AlignCenter)

    @Qc.pyqtSlot()
    def get_ordered(self):
        pass

if __name__ == '__main__':
    import sys
    app = Qw.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

从布局中删除元素总是一个坏主意,最好在必要时隐藏或显示。

from PyQt5 import QtCore as Qc
from PyQt5 import QtWidgets as Qw

class Widget(Qw.QWidget):
    def __init__(self):
        super().__init__()
        self.order_list = [str(i) * 2 * i for i in range(20)]
        self.init_ui()

    def init_ui(self):
        self.setGeometry(300, 300, 300, 300)
        self.layout = Qw.QGridLayout(self)

        self.menu = Qw.QWidget()
        lay = Qw.QVBoxLayout(self.menu)
        self.menu.items = []
        for n, i in enumerate(self.order_list):
            btn = Qw.QCheckBox(i)
            btn.setFixedHeight(15)
            lay.addWidget(btn)
            self.menu.items.append(btn)
        lay.addStretch()

        self.menu_scroll = Qw.QScrollArea(widgetResizable=True)
        self.menu_scroll.setWidget(self.menu)
        self.layout.addWidget(self.menu_scroll, 0, 0, 1, 1)
        self.layout.setColumnStretch(0, 10)

        self.rec = Qw.QWidget()
        self.rec.items = []
        lay2 = Qw.QVBoxLayout(self.rec)
        for n, i in enumerate(self.order_list):
            btn = Qw.QLabel(i)
            btn.setFixedHeight(15)
            lay2.addWidget(btn)
            self.rec.items.append(btn)
        lay2.addStretch()

        self.rec_scroll = Qw.QScrollArea(widgetResizable=True)
        self.rec_scroll.setWidget(self.rec)
        self.layout.addWidget(self.rec_scroll, 0, 0, 1, 1)
        self.layout.setColumnStretch(0, 10)

        self.layout.addWidget(self.rec_scroll, 0, 1, 1, 1)
        self.layout.setColumnStretch(1, 9)

        self.order_btn = Qw.QPushButton('Order')
        self.order_btn.setFixedSize(80, 30)
        self.order_btn.clicked.connect(self.get_ordered)
        self.layout.addWidget(self.order_btn, 1, 0, 1, 2, alignment=Qc.Qt.AlignCenter)

    @Qc.pyqtSlot()
    def get_ordered(self):
        for checkbox, label in zip(self.menu.items, self.rec.items):
            label.setVisible(checkbox.isChecked())

if __name__ == '__main__':
    import sys
    app = Qw.QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

推荐阅读