如何对齐包含在几个HBoxLayouts上的小部件?

2024-06-02 12:57:38 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们来看看这个小片段:

import sys

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItem
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QTreeView
from PyQt5.QtWidgets import QWidget


class PropertiesWidget(QTreeView):

    def __init__(self, columns, *args, **kwargs):
        super(PropertiesWidget, self).__init__(*args, **kwargs)

        self.model = QStandardItemModel(self)
        self.setModel(self.model)
        self.model.setColumnCount(columns)
        self.model.setHeaderData(0, Qt.Horizontal, "Property")
        self.model.setHeaderData(1, Qt.Horizontal, "Value")
        self.setFocusPolicy(Qt.NoFocus)
        self.last_item = 0
        self.last_item = QStandardItem()
        self.parameters = {}

    def begin_group(self, name, key):
        root = QStandardItem(name)
        root.setEditable(False)
        if not key:
            root.setData(key)
        self.model.appendRow([root])
        self.last_item = root

    def end_group(self):
        if (self.last_item and self.last_item.parent()):
            self.last_item = self.last_item.parent()

    def append_row(self, text, widget):
        if not self.last_item:
            return

        if text in self.parameters:
            raise Exception("Not allowed duplicate keys {0}".format(text))

        item = self.last_item
        child = QStandardItem(text)
        child2 = QStandardItem()
        child.setEditable(False)
        item.appendRow([child, child2])
        if widget:
            self.setIndexWidget(child2.index(), widget)

        self.expand(child.index().parent())

    def add_vec2(self, key, value):
        x = QLineEdit(value, self)
        y = QLineEdit(value, self)

        lbl = QLabel('')
        lbl.setMinimumWidth(0)
        lbl2 = QLabel('')
        lbl2.setMinimumWidth(0)

        layout = QHBoxLayout(self)
        layout.addWidget(x, stretch=1)
        layout.addWidget(y, stretch=1)
        layout.addWidget(lbl, stretch=1)
        layout.addWidget(lbl2, stretch=1)
        layout.setContentsMargins(0, 0, 0, 0)

        widget = QWidget(self)
        widget.setLayout(layout)

        setattr(widget, "operator_key", key)
        self.append_row(key, widget)

    def add_vec3(self, key, value):
        x = QLineEdit(value, self)
        y = QLineEdit(value, self)
        z = QLineEdit(value, self)

        lbl = QLabel('')
        lbl.setMinimumWidth(0)

        layout = QHBoxLayout(self)
        layout.addWidget(x, stretch=1)
        layout.addWidget(y, stretch=1)
        layout.addWidget(z, stretch=1)
        layout.addWidget(lbl, stretch=1)
        layout.setContentsMargins(0, 0, 0, 0)

        widget = QWidget(self)
        widget.setLayout(layout)

        setattr(widget, "operator_key", key)
        self.append_row(key, widget)

    def add_vec4(self, key, value):
        x = QLineEdit(value, self)
        y = QLineEdit(value, self)
        z = QLineEdit(value, self)
        w = QLineEdit(value, self)

        layout = QHBoxLayout(self)
        layout.addWidget(x, stretch=1)
        layout.addWidget(y, stretch=1)
        layout.addWidget(z, stretch=1)
        layout.addWidget(w, stretch=1)
        layout.setContentsMargins(0, 0, 0, 0)

        widget = QWidget(self)
        widget.setLayout(layout)

        setattr(widget, "operator_key", key)
        self.append_row(key, widget)


def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = PropertiesWidget(2)
    ex.begin_group("foo", "foo")
    ex.add_vec2("vec2", "vec2_value")
    ex.add_vec3("vec3", "vec3_value")
    ex.add_vec4("vec4", "vec4_value")
    ex.end_group()

    ex.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

如果我运行它并扩展小部件,我们将看到每行的所有行编辑都正确对齐:

enter image description here

但是如果我缩小它,这些小部件将以不同的尺寸对齐,如下所示:

enter image description here

我如何保证无论你如何调整小部件的大小,所有行编辑都将具有相同的大小,并且它们将彼此对齐?我已经尝试过使用setMinimumWidth(100),但那不行。在


Tags: keyfromimportselfvaluedefwidgetitem
3条回答

就像Pyqli给了我一个免费的解决方案。下面是一个完整的工作示例:

import sys

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItem
from PyQt5.QtGui import QStandardItemModel
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QTreeView
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QSizePolicy


class VecParameter(QWidget):
    value_changed = pyqtSignal(object)

    def __init__(self, value, num_components, max_columns=4, parent=None, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.components = []
        if num_components > max_columns:
            num_components = max_columns

        layout = QHBoxLayout(self)
        for i in range(num_components):
            c = QLineEdit(str(value[i]), self)
            c.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding)
            self.components.append(c)
            layout.addWidget(c, stretch=1)
        for i in range(num_components, max_columns):
            lbl = QLabel('')
            lbl.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding)
            layout.addWidget(lbl, stretch=1)

        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)


class PropertiesWidget(QTreeView):

    def __init__(self, columns, *args, **kwargs):
        super(PropertiesWidget, self).__init__(*args, **kwargs)

        self.model = QStandardItemModel(self)
        self.setModel(self.model)
        self.model.setColumnCount(columns)
        self.model.setHeaderData(0, Qt.Horizontal, "Property")
        self.model.setHeaderData(1, Qt.Horizontal, "Value")
        self.setFocusPolicy(Qt.NoFocus)
        self.last_item = 0
        self.last_item = QStandardItem()
        self.parameters = {}

    def begin_group(self, name, key):
        root = QStandardItem(name)
        root.setEditable(False)
        if not key:
            root.setData(key)
        self.model.appendRow([root])
        self.last_item = root

    def end_group(self):
        if (self.last_item and self.last_item.parent()):
            self.last_item = self.last_item.parent()

    def append_row(self, text, widget):
        if not self.last_item:
            return

        if text in self.parameters:
            raise Exception("Not allowed duplicate keys {0}".format(text))

        item = self.last_item
        child = QStandardItem(text)
        child2 = QStandardItem()
        child.setEditable(False)
        item.appendRow([child, child2])
        if widget:
            self.setIndexWidget(child2.index(), widget)

        self.expand(child.index().parent())

    def add_vec1(self, key, value=[0]):
        widget = VecParameter(value, 1, parent=self)
        self.append_row(key, widget)

    def add_vec2(self, key, value=[0, 0]):
        widget = VecParameter(value, 2, parent=self)
        self.append_row(key, widget)

    def add_vec3(self, key, value=[0, 0, 0]):
        widget = VecParameter(value, 3, parent=self)
        self.append_row(key, widget)

    def add_vec4(self, key, value=[0, 0, 0, 0]):
        widget = VecParameter(value, 4, parent=self)
        self.append_row(key, widget)


def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = PropertiesWidget(2)
    ex.begin_group("foo", "foo")
    ex.add_vec1("vec1", [1])
    ex.add_vec2("vec2", [1, 2])
    ex.add_vec3("vec3", [1, 2, 3])
    ex.add_vec4("vec4", [1, 2, 3, 4])
    ex.end_group()

    ex.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

实际上,你的布局没有相同数量的项目。这就是为什么。你的每一个“行”必须有相同的长度,但不同的项目数量。所以当你把它变小的时候,空间就被里面的东西分开了。在

为了快速解决问题,您可以尝试在布局中添加“不可见”项,例如间隔符,因此每行中的项的总和可以相同

你可以用Tkinter来做这个。它更简单,并将保持一切与它的网格功能对齐!(请确保为每个框设置x偏移量!)在

Import tkinter

root = tk.Tk() # Some versions of python throw tantrums when you don't do this
root.geometry(...) #Like so: root.geometry("400x400")
#to make this easy I'll only do one box.
"""
The grid feature of tkinter allows you to grid-align boxes to a page.
By just simply asking if root.geometry is less than ... then realign to a new grid.
"""
Entry = tkinter.Entry(root, background = "...") #Use Entry.get() feature to gather what's been written as a value called ans if u want to do this.
#More entries down here.....
Entry.grid(row = 2, column = 2) #Edit row and column for where to grid it.
root.mainloop() # Required by tkinter in order to run.

相关问题 更多 >