难以正确显示PyQt GUI元素

时间:2019-04-20 04:14:10

标签: python pyqt pyqt5

新的Python程序员在这里。我正在尝试制作一个简单的GUI,并且无法显示PyQt元素之一。也许有人可以向我指出正确的方向,并给出一些常规代码注释。不用担心我知道我的代码可能很糟糕。我们都必须从某个地方开始。

我有一个GUI,它由HBoxLayout中的两个小部件组成。一个小部件是一个简单的PushButton,另一个是自定义的ControlWidget。我可以使它们显示得很好(尽管有对齐问题)。在ControlWidget上,我有一个带有一些标签,ComboBoxes和一个子类QTextBrowser(调试器)的GridLayout。这是我无法出现的东西。

诚然,我不确定如何做到这一点。继承错误吗?我是否需要将其他内容传递给下层阶级?等等。我希望将各种元素分解成单独的文件,并希望将来的事件可以在代码的其他部分访问,但显然我缺少一些东西。

MainGUI.py

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

from ControlWidget import ControlWidget
# from MenuBar import MenuBar
from Debugger import Debugger

# Main 
class TopWindow(QMainWindow):
    def __init__(self):
        super(TopWindow, self).__init__()
        self.setWindowTitle('Test GUI')
        self.setGeometry(0, 0, 800, 600)
        self.setMaximumSize(1024, 768)
        self.initUI()

    def initUI(self):
        # MenuBar.initMenuBar(self)
        centralWidget = QWidget(self)
        self.setCentralWidget(centralWidget)
        hLayout = QHBoxLayout(centralWidget)
        pushButton = QPushButton("Button A")
        hLayout.addWidget(pushButton)
        hLayout.addWidget(ControlWidget())

        self.show()

# Program Entry Point        
if __name__ == '__main__':
    applicationInstance = QApplication(sys.argv)
    ex = TopWindow()
    sys.exit(applicationInstance.exec_())

ControlWidget.py

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * 
from PyQt5.QtCore import *

from Debugger import Debugger

class ControlWidget(QWidget):
    def __init__(self, parent=None):
        super(ControlWidget, self).__init__(parent)
        self.left = 100
        self.top = 100
        self.width = 320
        self.height = 100
        self.numClicks = 0
        self.setMaximumWidth(240) 
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.initUI()

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

        self.createGridLayout()

    def createGridLayout(self):
        # Create Grid Layout
        layout = QGridLayout()
        self.setLayout(layout)
        layout.setColumnStretch(0, 2)
        layout.setColumnStretch(1, 3)
        layout.setColumnStretch(2, 1)

        # Instantiate Labels
        labelA = QLabel()
        labelB = QLabel()
        labelC = QLabel()
        labelD = QLabel()
        labelE = QLabel()
        labelF = QLabel()
        self.labelFa = QLabel()
        labelA.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labelB.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labelC.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labelD.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labelE.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        labelF.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.labelFa.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        labelA.setText('ABCD: ')
        labelB.setText('BCDE: ')
        labelC.setText('CDEF: ')
        labelD.setText('DEFG: ')
        labelE.setText('EFGH: ')
        labelF.setText('FGHI: ')

        # Instantiate Combo Boxes
        comboBoxA = QComboBox()
        comboBoxB = QComboBox()
        comboBoxC = QComboBox()
        comboBoxD = QComboBox()
        comboBoxE = QComboBox()
        comboBoxA.addItems(["A", "B", "C", "D"])
        comboBoxB.addItems(["B", "C", "D", "E"])
        comboBoxC.addItems(["C", "D", "E", "F"])
        comboBoxD.addItems(["D", "E", "F", "G"])
        comboBoxE.addItems(["E", "F", "G", "H"])

        # Instantiate Push Buttons
        pushButtonF = QPushButton()
        pushButtonF.setText('Set Value')

        # Spacer
        spacer = QSpacerItem(10, 30, QSizePolicy.Fixed, QSizePolicy.Fixed)

        # Message Box
        labelDebug = QLabel()
        labelDebug.setText("Debug")
        labelDebug.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        debug = Debugger(self) # DOES NOT WORK

        # Add to Grid Layout (item, row, column, rowspan, colspan)
        layout.addWidget(labelA, 0, 0)
        layout.addWidget(labelB, 1, 0)
        layout.addWidget(labelC, 2, 0)
        layout.addWidget(labelD, 3, 0)
        layout.addWidget(labelE, 4, 0)
        layout.addWidget(labelF, 5, 0)
        layout.addWidget(comboBoxA, 0, 1, 1, 2)
        layout.addWidget(comboBoxB, 1, 1, 1, 2)
        layout.addWidget(comboBoxC, 2, 1, 1, 2)
        layout.addWidget(comboBoxD, 3, 1, 1, 2)
        layout.addWidget(comboBoxE, 4, 1, 1, 2)
        layout.addWidget(pushButtonF, 5, 1, 1, 1)
        layout.addWidget(self.labelFa, 5, 2, 1, 1)
        layout.addItem(spacer, 6, 0, 1, 3)
        layout.addWidget(labelDebug, 7, 0)
        layout.addWidget(debug, 8, 0)

        # Hook Up ComboBox Signals to Handlers
        comboBoxA.currentIndexChanged.connect(self.comboBoxAHandler)

        # Hook Up PushButton Signals to Handlers
        pushButtonF.clicked.connect(self.pushButtonFHandler)

        #self.horizontalGroupBox.setLayout(layout)

    def comboBoxAHandler(self, i):
        print('Combo Box A Selection Changed to {0}'.format(i))
        #Debugger.write(self, 'Combo Box A Selection Changed')

    def pushButtonFHandler(self):
        print('Push Button F Clicked')
        self.numClicks = self.numClicks + 1
        self.labelFa.setText(str(self.numClicks))

Debugger.py

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * 
from PyQt5.QtCore import *

class Debugger(QWidget):
    def __init__(self, parent=None):
        super(Debugger, self).__init__(parent)
        self.setMaximumWidth(240)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        self.createTextBrowser()

    def createTextBrowser(self):
        self.textBrowser = QTextBrowser()
        self.textBrowser.setReadOnly(True)

    def write(self, text):
        self.textBrowser.append("• " + text)

我缺少或做错的简单事情是什么?

2 个答案:

答案 0 :(得分:1)

我的猜测是,它与以下事实有关:您的textbrowser对象没有父级,并且您从未明确将其告知.show()。 通常,当小部件具有父级时,对父级小部件的show方法的调用也会显示子级。由于您的textbrowser对象没有父对象,因此替代方法是显式显示该对象,但您也没有这样做。

在TopWindow类的initUI方法中,调用self.show()。这是实际的发票,显示了父母的所有子女(父母是自己,即窗口)。这个单次调用正确显示了您的其他窗口小部件,因为您已将主窗口明确指定为它们的父窗口,但由于未给它父窗口,所以它不显示文本浏览器。 (请注意,由于调试器类使用的是合成而非继承,因此您确实给了调试器一个父级(即QWidget),但实际的QTextBrowser对象没有父级)

答案 1 :(得分:1)

您有2个错误:

  • 您不是在Debugger中使用继承,而是组合。

  • 如果要在同一类的其他方法中使用变量,则必须使该变量成为该类的成员。

考虑到上述情况,解决方案是:

Debugger.py

import sys
from PyQt5.QtWidgets import QTextBrowser, QSizePolicy

class Debugger(QTextBrowser):
    def __init__(self, parent=None):
        super(Debugger, self).__init__(parent)
        self.setMaximumWidth(240)
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
        self.setReadOnly(True)

    def write(self, text):
        self.append("• " + text)

ControlWidget.py


# ...
class ControlWidget(QWidget):
    # ...

    def initUI(self):
        # ...

        # Message Box
        labelDebug = QLabel()
        labelDebug.setText("Debug")
        labelDebug.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.debug = Debugger() # <---

        # ...
        layout.addWidget(labelDebug, 7, 0)
        layout.addWidget(self.debug, 8, 0) # <---

        # Hook Up ComboBox Signals to Handlers
        # ...

    def comboBoxAHandler(self, i):
        print('Combo Box A Selection Changed to {0}'.format(i))
        self.debug.write('Combo Box A Selection Changed') # <---
    # ...

我建议阅读以下出版物,以便您了解继承( is-a )和组合( has-a )之间的区别: