Форум сайта python.su
Незнал как тему назвать, получаеться есть приложение, использующее PyQt, и в нем много QLabel-ов, в которые выводится кол-во обработанных данных, для кадой заводиться счетчик , увеличиваеться, и устанавливаеться значение лэйблу.
Насколько правильно будет, опрделить наследника у QLabel добавить int аттрибут в котором будет храниться кол-во обработанных данных, и метод который будет увеличивать аттрибут с кол-вом даных и устанавливать значение в Label.
С точки зрения правильности кода насколько это правильно?
Выглядеть будет это так:
class NumLabel(QLabel) def __init__(self, parent = None): super(QLabel, self).__init__(parent) self.current_value = 0 def inc_value(self, count = 1): self.current_value += count self.setText(str(self.current_value))
Офлайн
Не зная что это за счетчики и QLabel (и почему их много), без общей картины тут не ответишь. Возможно в конкретном приложении это нормально.
А на первый взгляд получается, что объединяется логика и представление.
Офлайн
reclosedev, есть приложение для взаимодействия VK API, есть там класс
Main
Наследованный от QApplication, и там куча таких строк .
def inc_upload_count(self, count): self.upload_count += count self.main_form.upload_page.load_count.setText(str(self.upload_count)) def inc_upload_errors_count(self): self.upload_error_count += 1 #Счетчик ошибок загрузки self.main_form.upload_page.errors_ct_label.setText(str(self.upload_error_count)) #Ставим лэйблу кол-во ошибок загрузки
def inc_and_set(self, counter, label): counter += 1 label.setText(counter)
signal.connect(lambda: inc_and_set(self.err_count, self.mainform.errLabel))
Отредактировано mironich (Янв. 20, 2013 17:32:04)
Офлайн
В данном случае код из первого поста может и подойдет.
Проблема в том, что сразу идет привязка к лэйблам. Код, который ничего о них не знает, и возможно работает в другом потоке будет вызывать методы которые меняют GUI.
Можно рассмотреть такое решение:
# -*- coding: utf-8 -*- import functools from PyQt4 import QtGui, QtCore class ObservableVariable(QtCore.QObject): changed = QtCore.pyqtSignal(object) def __init__(self, initial_value=0): super(ObservableVariable, self).__init__() self._value = initial_value def get_value(self): return self._value def set_value(self, new_val): self._value = new_val self.changed.emit(new_val) value = property(get_value, set_value) def __iadd__(self, other): self.value += other return self def __isub__(self, other): self.value -= other return self def __str__(self): return str(self.value) class GuiExample(QtGui.QWidget): def __init__(self): super(GuiExample, self).__init__() self.counter1 = ObservableVariable(10) self.counter2 = ObservableVariable() self.counter3 = ObservableVariable() self.create_gui_associated_with_counters() def create_gui_associated_with_counters(self): layout = QtGui.QVBoxLayout(self) # связать можно с Label self.label1 = QtGui.QLabel(str(self.counter1)) layout.addWidget(self.label1) self.label2 = QtGui.QLabel(str(self.counter2)) layout.addWidget(self.label2) def on_value_changed(label, value): label.setText(str(value)) self.counter1.changed.connect(functools.partial(on_value_changed, self.label1)) self.counter2.changed.connect(functools.partial(on_value_changed, self.label2)) # Или с другими виджетами spinbox = QtGui.QSpinBox() layout.addWidget(spinbox) self.counter3.changed.connect(spinbox.setValue) # изменение значения пользователем spinbox.valueChanged.connect(self.counter3.set_value) button = QtGui.QPushButton('test', clicked=self.some_operation) layout.addWidget(button) def some_operation(self): self.counter1 -= 1 self.counter2 += 2 self.counter3 += 1 if self.counter1.value == 0: self.counter1.value = 10 app = QtGui.QApplication([]) gui = GuiExample() gui.show() app.exec_()
Отредактировано reclosedev (Янв. 20, 2013 20:42:28)
Офлайн
Я вот еще подумал, м.б Event использовать, слать сообщения обьекту который наследует QApplication…
Кода поубавиться, но насколько это правильно?
reclosedev, изучаю ваше решение, выглядит хорошо.
reclosedev, ваше решение прекрасно!
Жаль сам к нему не дошел…:( Подобное вообще в голову не приходило…
Спасибо!
Отредактировано mironich (Янв. 20, 2013 20:53:21)
Офлайн
А если засунуть счетчик ошибок обычное int поле в базовый класс форм для приложения, в обработчике события его увеличивать и устанавливать в label, не будет ли это “бъединяется логика и представление.”, это просто уменьшит кол-во кода существенно.
Выглядеть примерно так будет:
class BasePage(QWidget): QWidget.__init__(self, parent): self.error_counter = 0 self.errors_counter_label = BadLabel('0') def customEvent(self, event): //Обрабатываем свои события if event.type() == events.ErrorEvent(): self.error_counter += 1 self.errors_counter_label.setText(self.error_counter )
Офлайн
А если засунуть счетчик ошибок обычное int поле в базовый класс форм для приложения, в обработчике события его увеличивать и устанавливать в label, не будет ли это “бъединяется логика и представление.”, это просто уменьшит кол-во кода существенно.
Выглядеть примерно так будет:
class BasePage(QWidget): QWidget.__init__(self, parent): self.error_counter = 0 self.errors_counter_label = BadLabel('0') def customEvent(self, event): //Обрабатываем свои события if event.type() == events.ErrorEvent(): self.error_counter += 1 self.errors_counter_label.setText(self.error_counter )
Отредактировано mironich (Янв. 22, 2013 13:08:07)
Офлайн
Сильно задумываться по этому поводу, наверное, не стоит. Не фреймворк же пишите.
mironichНа первый взгляд, получается много типов event'ов, if'ов, и опять жестко на каждый if привязан лэйбл. А если “и в нем много QLabel” может потом это станет таблицей, а может и не изменится.
Выглядеть примерно так будет:
mironichСмотря какая форма, какие данные. По мне, тут нет однозначного ответа. Зачастую, достаточно QValidator'ов в инпутах, а может логика проверки сложная и форме просто не хватит данных.
И где должна производиться проверка пользовательских данных?
В классе формы, или приложения?
Отредактировано reclosedev (Янв. 22, 2013 16:25:33)
Офлайн
На первый взгляд, получается много типов event'ов,Ну да у меня моих пользовательских уже 7 штук, но все кроме этого делают другие вещи.
if'овБольшое кол-во ведет к чему-то не хорошему?
Зачастую, достаточно QValidator'ов в инпутах,Да они стоят, но!
Отредактировано mironich (Янв. 22, 2013 16:51:22)
Офлайн
На словах сложно все это воспринимается.
Честно говоря, не вижу преимуществ евентов над сигналами.
mironichНу если if'ы выглядят как:
if'ов
Большое кол-во ведет к чему-то не хорошему?
Плохая читабельность кода, и.т.д… Или это нормально 6-7 условий elif?
if event.type() == events.XXXEvent(): self.XXX_counter += 1 self.XXX_counter_label.setText(self.XXX_counter ) elif event.type() == events.YYYEvent(): self.YYY_counter += 1 self.YYY_counter_label.setText(self.YYY_counter ) elif ...
mironichА должен ли класс для работы с ВК знать о форме?
В итоге при создании обьекта для работы с VK_API в конструктор надо всеголишь передать форму которая будет получать event-ы и все…
Не каких сигналлов коннектов..
mironichА зачем? Скорее он будет использован один раз, а вот VK_API может и в другом приложении.
но тогда бы класс формы перестал бы быть независимым.
Отредактировано reclosedev (Янв. 22, 2013 17:36:37)
Офлайн