Сложность правильного отображения элементов графического интерфейса PyQt - PullRequest
1 голос
/ 20 апреля 2019

Новый программист Python здесь. Я пытаюсь создать простой графический интерфейс и не могу отобразить один из элементов PyQt. Возможно, кто-то здесь может указать мне правильное направление и дать некоторые общие комментарии кода. Не беспокойся Я знаю, что мой код, вероятно, ужасен. Нам всем нужно с чего-то начать.

У меня есть графический интерфейс, который состоит из двух виджетов в HBoxLayout. Один виджет представляет собой простую кнопку PushButton, а другой - настраиваемый виджет ControlWidget. Я могу заставить их отображаться очень хорошо (несмотря на проблемы с выравниванием). На ControlWidget у меня есть GridLayout с некоторыми метками, комбинированными списками и вложенным классом QTextBrowser (отладчик). Это то, что я не могу показать.

Правда, я не совсем уверен, как это сделать. Правильно ли наследство? Нужно ли передавать что-то еще в низшие классы? и т.д. Я хочу, чтобы различные элементы были разбиты на отдельные файлы и чтобы будущие события были доступны в других частях кода, но, очевидно, я что-то упускаю.

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 ]

1 голос
/ 20 апреля 2019

У вас есть 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 ):

1 голос
/ 20 апреля 2019

Я предполагаю, что это связано с тем фактом, что у вашего объекта textbrowser нет родителя, и вы никогда явно не сообщали об этом .show ().Обычно, когда у виджета есть родительский элемент, вызов метода show родительского виджета также показывает дочерние элементы.Поскольку у вашего объекта textbrowser нет родителя, альтернативой является явное отображение этого объекта, но вы этого также не сделали.

В методе initUI вашего класса TopWindow вы вызываете self.show ().Это фактический вызов, который показывает всех потомков родителя (родительский объект self, окно).Этот одиночный вызов правильно показывает ваши другие виджеты, потому что вы явно назначили главное окно в качестве их родителя, но он не показывает ваш текстовый браузер, потому что вы не дали ему родителя.(обратите внимание, поскольку ваш класс отладчика использует композицию, а не наследование, вы дали отладчику родительский элемент (который является QWidget), но сам объект QTextBrowser не имеет родителя)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...