Python QTableWidget无法显示完整宽度

时间:2018-11-03 00:38:56

标签: python pyqt pyqt5 qtablewidget

我是一位经验丰富的(即使很生锈)Windows程序员。我正在尝试创建我在1963年设计的计算机(Ferranti Argus 400)的部分逻辑仿真(是的,我那年老!

但是我是Python编程的新手,并且在使用QTableWidget时遇到格式化问题。

我想在一组控件旁边显示该控件,以便为模拟功能输入测试数据(并使用QTableWidget显示模拟将要执行的步骤),例如,显示乘法器位的工作情况一点点。

我试图将QHBoxLayout()用作具有两个嵌入式Box的外部容器。左边的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_())

此版本产生第一张图像。如果取消注释显示的两行,则会生成第二个版本。我已经为此进行了一段时间的斗争,我无法理解如何使右手桌子发挥作用。我希望有人能对此有所启发。

我正在将PyQt5与1周前下载的最新版本的Python配合使用。我正在Windows 10上运行。

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

1 个答案:

答案 0 :(得分:0)

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

在您要更换的情况下,正确的做法是将布局设置为中央窗口。

要解决此问题,似乎是反复添加布局,这会导致问题,因此,我改进了代码以建立位置(我建议不要设置类的layout属性,因为通常不会重复使用它们)

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

更新

要使第一个布局占用最小空间,而另一个布局要扩展,则在添加1时必须添加一段rightpanel_Layout,因此将其更改为:

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