Python QTableWidget 不显示全宽

标签 python pyqt pyqt5 qtablewidget

我是一位经验丰富(虽然有些生疏)的 Windows 程序员。我正在尝试创建我在 1963 年设计的计算机(Ferranti Argus 400)的部分逻辑模拟(是的,我就这么老了!

但是,我对 Python 编程很陌生,并且在使用 QTableWidget 时遇到格式问题。

我想将其显示在右侧的一组控件旁边,用于输入模拟功能的测试数据(并使用 QTableWidget 来显示模拟将运行的步骤),例如显示乘法器位的工作情况一点一点地。

我正在尝试使用 QHBoxLayout() 作为带有两个嵌入框的外部容器。左侧 QVBox 将包含用于模拟的数据输入,右侧框将包含一个 QTablewidget 对象,其中滚动显示计算机寄存器的状态。

QTableWidget 可以正常工作(下面的一个是简化版),直到我在左侧添加一个包含控件的 Vbox(此处包含一组)。表格从其整个宽度缩小并将其自身定位在剩余空间的右侧。我希望它位于其他控件旁边的左侧,并在空间不足时滚动(目标机器有 32*24 位寄存器要显示,尽管我最初将使用 8 位进行测试)

左侧有一个组的屏幕

在此处输入图像描述

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_())

此版本生成第一张图像。如果取消注释显示的两行,则会生成第二个版本。我已经为此奋斗了一段时间,但我无法理解如何让右手边的 table 正常工作。我希望有人能阐明这一点。

我正在使用 PyQt5 以及大约 1 周前下载的最新版本的 Python。我在 Windows 10 上运行。

这是我在这里发表的第一篇文章。我希望它的格式正确

最佳答案

首先,我建议您在 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_())

enter image description here

更新:

为了让第一个布局占用最小空间,而另一个布局扩展,在添加 rightpanel_Layout 时必须添加 1 的拉伸(stretch),因此将其更改为:

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

也没有必要建立固定 anchor ,布局会为您完成工作:

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 QTableWidget 不显示全宽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53127389/

相关文章:

python - 在 python 中编写模块化代码

python - PySide Phonon 错误,后端插件无法加载

python - 将这个简单的 block 转换为惯用的 Python 代码

python - Opencv:值错误

python - 声明的列表引发 NoneType 异常

python - 如何在 QtGui 中创建动画?

python - 在 Pandas 中找到一个类的最小值(或最大值)

python - 如何为我在 PyQt 中绘制的图形制作动画?

python - 如果目标_blank,QWebengine 打开createwindow

python - 使用可拖动的 QLabel 进行裁剪