Python QTableWidget无法显示完整宽度

3
我是一名经验丰富(尽管有些生疏)的Windows程序员。我正在尝试创建一个计算机(Ferranti Argus 400)的部分逻辑模拟,这个计算机是我在1963年设计的(是的,我那么老了!)。然而,我对Python编程还很陌生,使用QTableWidget时遇到了格式问题。
我想在右侧显示它,并显示一组用于输入模拟函数测试数据的控件(并使用QTableWidget来显示模拟运行的步骤),例如逐位显示乘法器的操作过程。
我尝试将QHBoxLayout()作为我的外部容器,其中包含两个嵌入式框。左边的QVBox将包含用于模拟的数据输入,右边的框将包含一个QTablewidget对象,用于滚动显示计算机寄存器的状态(目标机器有32*24位寄存器需要显示,尽管我最初将使用8位进行测试)。
QTableWidget工作正常(下面这个是简化版),直到我在左边添加了一个包含控件的Vbox(此处包含一组)。表格会从其全宽缩小,并定位在剩余空间的右侧。我想把它放在其他控件旁边的左边,并在空间不足时滚动。
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 simple window'

        self.left = 10
        self.top = 50
        self.width = 800
        self.height = 480

        self.initUI()

        def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # Parent layout
        self.central_Widget = QWidget(self)
        self.setCentralWidget(self.central_Widget)
        self.central_Layout = QHBoxLayout()

        # Configure left panel as Vbox
        self.leftpanel_Layout = QVBoxLayout()
        #
        self.leftpanel_Layout.addWidget(DataSelectionGroup("Data entry mode"))
        #
        # Add stretch to bottom of panel
        self.leftpanel_Layout.addStretch(0)

        self.rightpanel_Layout = QVBoxLayout()
        self.myLogTable = LogTablex()
        self.rightpanel_Layout.addWidget(self.myLogTable)

        self.setLayout(self.rightpanel_Layout)


        # Add left panel layout to central layout
   # uncomment these lines to see the unwanted behaviour
        #self.central_Layout.addLayout(self.leftpanel_Layout)
        #self.central_Layout.addStretch(0)

        self.setLayout(self.central_Layout)

        self.central_Layout.addLayout(self.rightpanel_Layout)
        self.setLayout(self.central_Layout)

        self.central_Widget.setLayout(self.central_Layout)
        self.setWindowTitle("Demo")
        self.show()


class DataSelectionGroup(QGroupBox):
    """ Create a group of Radio Buttons to choose type of data entry """
    def __init__(self, title):
        super().__init__(title)

        self.buttonLayout = QVBoxLayout()

        # add radio buttons to choose which mode of data entry to use
        self.radio1 = QRadioButton("&Binary")
        self.buttonLayout.addWidget(self.radio1)
        self.radio1.setChecked(True)

        self.radio2 = QRadioButton("Decimal &Fraction")
        self.buttonLayout.addWidget(self.radio2)

        self.radio3 = QRadioButton("Decimal &Integer")
        self.buttonLayout.addWidget(self.radio3)

        self.setLayout(self.buttonLayout)

class LogTablex(QTableWidget):
    def __init__(self, WordLength:int = 24):
        super().__init__()

        self.WordLength = WordLength
        self.initTable(["Note", "X", "Q", "N", "C", "O"])

    def initTable(self, headerlist):
        font = QFont()
        font.setFamily = "Courier New"
        font.setPointSize(8)

        self.setFont(font)
        self.horizontalHeader().setStyleSheet("QHeaderView::section { background-color:lightgrey; }")

        self.setColumnCount(len(headerlist))
        self.setHorizontalHeaderLabels(headerlist)

        self.setRowCount(0)
        self.start_newrow()
        self.str = '0' * self.WordLength + ' '

        self.setCellWidget(0, 0, QLabel("note"))
        self.setCellWidget(0, 1, QLabel(self.str))
        self.setCellWidget(0, 2, QLabel(self.str))
        self.setCellWidget(0, 3, QLabel(self.str))
        self.setCellWidget(0, 4, QLabel("1"))
        self.setCellWidget(0, 5, QLabel("1"))

        self.verticalHeader().setDefaultSectionSize(22)
        self.horizontalHeader().setSectionResizeMode(3)

        self.resizeColumnsToContents()

    def start_newrow(self, note:str = "new note         "):
        self.insertRow(self.rowCount())
        self.setCellWidget(self.rowCount() - 1, 0, QLabel(note))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

这个版本生成了第一张图片。如果您取消注释所示的两行代码,它将生成第二个版本。我已经与此问题斗争了一段时间,但是我无法理解如何使右侧表格正确显示。我希望有人能为我提供帮助。

我正在使用PyQt5和最近1周下载的最新版本Python。我在Windows 10上运行。

这是我的第一篇帖子。我希望格式正确。

1个回答

3

首先,我建议你在CMD或终端中执行脚本,因为很多时候IDE会隐藏错误,比如如果我执行你的代码,我会得到以下消息:

QWidget::setLayout: Attempting to set QLayout "" on App "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on App "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on App "", which already has a layout

由于QMainWindow是一个具有预设布局的特殊小部件,如下图所示,因此会出现错误: enter image description here 在您的情况下,您正在尝试替换它,正确的方法是将布局设置为centralwidget。
针对问题,似乎您一直在重复添加布局,这会导致问题,因此我已经改进了您的代码以确定位置(我建议不要将布局属性设置为类的属性,因为它们通常不会被重用)。
from PyQt5 import QtCore, QtGui, QtWidgets


class App(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 simple window'
        self.left, self.top, self.width, self.height = 10, 50, 800, 480
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # Parent layout
        self.central_Widget = QtWidgets.QWidget()
        self.setCentralWidget(self.central_Widget)
        central_Layout = QtWidgets.QHBoxLayout(self.central_Widget)

        leftpanel_Layout = QtWidgets.QVBoxLayout()
        leftpanel_Layout.addWidget(DataSelectionGroup("Data entry mode"))
        leftpanel_Layout.addStretch()

        rightpanel_Layout = QtWidgets.QVBoxLayout()
        self.myLogTable = LogTablex()
        rightpanel_Layout.addWidget(self.myLogTable)

        central_Layout.addLayout(leftpanel_Layout)
        central_Layout.addLayout(rightpanel_Layout)
        self.setWindowTitle("Demo")
        self.show()


class DataSelectionGroup(QtWidgets.QGroupBox):
    """ Create a group of Radio Buttons to choose type of data entry """
    def __init__(self, title):
        super().__init__(title)
        buttonLayout = QtWidgets.QVBoxLayout(self)
        # add radio buttons to choose which mode of data entry to use
        self.radio1 = QtWidgets.QRadioButton("&Binary")
        buttonLayout.addWidget(self.radio1)
        self.radio1.setChecked(True)
        self.radio2 = QtWidgets.QRadioButton("Decimal &Fraction")
        buttonLayout.addWidget(self.radio2)
        self.radio3 = QtWidgets.QRadioButton("Decimal &Integer")
        buttonLayout.addWidget(self.radio3)


class LogTablex(QtWidgets.QTableWidget):
    def __init__(self, WordLength:int = 24):
        super().__init__()
        self.WordLength = WordLength
        self.initTable(["Note", "X", "Q", "N", "C", "O"])

    def initTable(self, headerlist):
        font = QtGui.QFont("Courier New", 8)
        self.setFont(font)
        self.horizontalHeader().setStyleSheet("QHeaderView::section { background-color:lightgrey; }")
        self.setColumnCount(len(headerlist))
        self.setHorizontalHeaderLabels(headerlist)
        self.setRowCount(0)
        self.start_newrow()

        text = '0' * self.WordLength + ' '
        for i, val in enumerate(("note", text, text, text, "1", "1",)):
            self.setCellWidget(0, i, QtWidgets.QLabel(val))

        self.verticalHeader().setDefaultSectionSize(22)
        self.horizontalHeader().setSectionResizeMode(3)
        self.resizeColumnsToContents()

    def start_newrow(self, note: str = "new note         "):
        self.insertRow(self.rowCount())
        self.setCellWidget(self.rowCount() - 1, 0, QtWidgets.QLabel(note))


if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())

在这里输入图片描述

更新:

为了使第一个布局占用最小的空间,而另一个布局扩展,您必须在添加 rightpanel_Layout 时添加 1 的伸展程度,因此将其更改为:

central_Layout.addLayout(leftpanel_Layout)
central_Layout.addLayout(rightpanel_Layout, stretch=1) # <---

此外,不需要建立固定的锚点,布局会为您完成工作:
class DataEntryGroupLayout(QtWidgets.QGroupBox):
    def __init__(self, title):
        super().__init__(title)
        _form = QtWidgets.QFormLayout(self)
        # Add the form controls to the group box = list required
        _pairlist = ["x value", "n value"]
        for _pair in _pairlist:
            _label = QtWidgets.QLabel(_pair)
            _value = QtWidgets.QLineEdit()
            _form.addRow(_label, _value)

enter image description here


你的更新解决了我的问题。谢谢。作为 Python/QT 格式化的新手,我发现 "stretch" 很令人困惑。几年前我最后一次涉足是使用 Visual Studio 和 C#。 - steelej
@steelej 我认为一位资深程序员应该知道文档是最重要的事情之一,因此有必要研究它 :-),除此之外,99% 的东西都在文档中,而 Qt 有着出色的文档和示例。另一方面不要忘记将我的回答标记为正确,如果您不知道如何操作,请查看 [tour],那是表达感谢的最佳方式。 :-) - eyllanesc
我确实花了很多时间查看文档,但在这种情况下,我没有找到答案。我已经有将近30年没有做过C++编程,并且对Python也是新手,但大部分Qt文档都假定您熟悉C++语法。我的项目中的计算机模拟部分看起来很容易,虽然GUI对于输入和显示结果很重要,但那是我想要达到的部分。我现在已经找到了标记为已回答的方法!我现在正在努力掌握信号! - steelej

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接