2016-07-25 6 views
1

Цель: создать объект позиции, содержащий текстовое поле для элементов label, value и value в PySide.Методы ООП с элементами Python GUI (PySide)

Справочная информация: Я создаю панель управления для устройства, которое запускается из малины Pi, используя Python PySide (QtPython) для обработки графического интерфейса. Я использую схему сетки и имею общий мотив, который я пытаюсь инкапсулировать в класс, чтобы избежать повторения. Мне нужна помощь в создании этого класса.

Как правило, мой код выглядит следующим образом:

class Form(QDialog): 
    def __init__(self, parent=None): 
     super(Form, self).__init__(parent) 

     self.pressure_label = QLabel('Pressure:') 
     self.pressure_value = QLabel() 
     self.pressure_units = QLabel('psi') 

     self.temperature_label = QLabel('Temperature:') 
     self.temperature_value = QLabel() 
     self.temperature_units = QLabel('oC') 
     ... 

     grid = QGridLayout() 

     grid.addWidget(pressure_label, 0, 0) 
     grid.addWidget(pressure_value, 0, 1) 
     grid.addWidget(pressure_units, 0, 1) 

     grid.addWidget(temperature_label, 1, 0) 
     grid.addWidget(temperature_value, 1, 1) 
     grid.addWidget(temperature_units, 1, 1) 
     ... 

     self.setLayout(grid) 

    def update(self): 
     self.temperature_value.setText(t_sensor.read()) 
     self.pressure_value.setText(p_sensor.read()) 

То, что я пробовал:

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

class LineItem(object): 
    def __init__(self, label_text, unit_text, grid, row): 
     self.value = None 
     self.units = None 

     self.label_field = QLabel(label_text) 
     self.value_field = QLabel() 
     self.units_field = QLabel(unit_text) 

     grid.addWidget(self.label_field, row, 0) 
     grid.addWidget(self.value_field, row, 1) 
     grid.addWidget(self.units_field, row, 2) 

    @property 
    def value(self): 
     return self.value 

    @value.setter 
    def value(self, val): 
     self.value = val 
     self.value_field.setText(val) 

    @property 
    def units(self): 
     return self.value 

    @value.setter 
    def units(self, val): 
     self.units = val 
     self.units_field.setText(val) 

class Form(QDialog): 
    def __init__(self, parent=None): 
     grid = QGridLayout() 

     row_number = itertools.count() 
     tb_encoder_1 = LineItem('Distance:', 'm', grid, next(row_number)) 
     tb_encoder_2 = LineItem('Distance:', 'm', grid, next(row_number)) 

     self.setLayout(grid) 

Что мне нужно:

То, что я надеюсь сделать это инкапсулировать эту метку, значение, единицы структуры в классе, так что я не должен повторяться так много.

Где такой класс? Что он наследует? Как мне получить доступ к объекту grid (нужен ли ему даже доступ)?

С чем я сталкиваюсь, это понимание того, как классы и инкапсуляция преобразуются в формы и виджеты PySide. Большинство учебных пособий, которые я видел до сих пор, не идут по этому пути, они просто ставят всю логику и создают в одном большом классе Form(QDialog).

+0

У вас есть несколько способов сделать это, знаете ли вы о программировании Qt Model/View? http://doc.qt.io/qt-5/model-view-programming.html; иначе с помощью MVC ваш первый класс будет моделью, второй - точкой зрения, и вы можете использовать сигналы для запуска автообмена в компонентах графического интерфейса, передаваемых вашим контроллером. – PyNico

+0

Спасибо, что указали мне на этот ресурс, я должен буду его отдать прочитайте. –

+0

Но используя Qt, LineItem может быть просто виджетами. Вы можете создать свой собственный виджет. Для этого ваш пользовательский виджет должен наследовать от QWidget на пример. вы переопределите то, что вам нужно, напишите свой gui и логику управления, затем вы можете использовать его так же, как Button или любой виджет Qt. – PyNico

ответ

1

Вам просто нужен подкласс QWidget, чтобы действовать как контейнер для других виджетов. Его структура будет очень похожа на обычную форму - основное отличие состоит в том, что она будет в виде дочернего виджета другой формы, а не как окно верхнего уровня.

class LineItem(QWidget): 
    def __init__(self, label_text, unit_text, parent=None): 
     super(LineItem, self).__init__(parent) 

     self.label_field = QLabel(label_text) 
     self.value_field = QLabel() 
     self.units_field = QLabel(unit_text) 

     layout = QVBoxLayout() 
     layout.setContentsMargins(0, 0, 0, 0) 

     layout.addWidget(self.label_field) 
     layout.addWidget(self.value_field) 
     layout.addWidget(self.units_field) 

     self.setLayout(layout) 

class Form(QDialog): 
    def __init__(self, parent=None): 
     super(Form, self).__init__(parent) 

     self.pressure_line = LineItem('Pressure:', 'psi', self) 
     self.temperature_line = LineItem('Temperature:', 'oC', self) 

     layout = QHBoxLayout() 

     layout.addWidget(self.pressure_line) 
     layout.addWidget(self.temperature_line) 

     self.setLayout(layout) 
+0

Хорошо, спасибо, что поняли это. Меня особенно смутило то, как используется команда 'layout' при работе с разными классами. Для меня это смутно напоминает панель wxPython. Мне просто нужно некоторое время, чтобы сплести его в мое приложение и доказать, что он работает, прежде чем я соглашусь. –

+0

Работы (с некоторыми изменениями)! Строка 'super (Form, self) .__ init __ (parent)' должна быть добавлена ​​к инициатору 'Form (QDialog)', 'layout.setContentsMargin()' is 'layout.setContentsMargins()', и есть пара опечаток, которые препятствуют ее запуску. Могу ли я редактировать? –

+0

@MichaelMolter. Спасибо. Кажется, я все исправил. – ekhumoro