necrozyablo
Май 3, 2010 20:53:48
Вот столкнулся с непонятным есть простой код
for i in range(5):
self.ui.log_frame_5.insertHtml('123')
self.ui.log_frame_5.insertHtml('<br>')
time.sleep(1)
log_frame_5 это QTextBrowser
Визуально строки ‘123’ выводится все вместе и через 5 секунд. А как сделать чтобы вывод происходил мгновенно?
По сути у меня сейчас получается выводить только когда завершается работа исполняемого кода.
truporez
Май 3, 2010 21:12:52
Используйте qt-сигналы, либо питоновские очереди. Можно, конечно, вызывать QtGui.qApp.processEvents(), но так или иначе, таким образом как делаете вы, нормальной gui *не будет*. Лучше начните с изучения qt-примеров.
necrozyablo
Май 4, 2010 10:00:19
truporez
Используйте qt-сигналы, либо питоновские очереди. Можно, конечно, вызывать QtGui.qApp.processEvents(), но так или иначе, таким образом как делаете вы, нормальной gui *не будет*. Лучше начните с изучения qt-примеров.
А нормальный это какой?
Просто по всяким кнопочкам у меня идёт срабатывание через сингалы, потом вызов функций. Вот в этих функциях сложные расчёты и данные берутся из баз. Всё выводил принтом в консоль, но вот решил в gui сделать окошечко.
Не подскажете линку на хорошие примеры по PyQT, а то в тех что я видел как раз делали как я…
truporez
Май 4, 2010 12:05:39
На длительных операциях используйте генераторы, либо отдельные нити. Для визуализации процесса в QT есть QProgressDialog, доступ к нему из другого потока можно организовать либо через Queue, либо эмитить преварительно подписаные слоты.
А то как делали вы будет замораживать интерфейс, что не есть хорошо.
Если владеете языком вероятного противника - на этом форуме была тема с книгами по QT. Если нет - примеры из site-packages\PyQt4\examples\
Вот еще по русски _ttp://forum.script-coding.info/viewforum.php?id=6
necrozyablo
Май 7, 2010 15:31:06
truporez
На длительных операциях используйте генераторы, либо отдельные нити. Для визуализации процесса в QT есть QProgressDialog, доступ к нему из другого потока можно организовать либо через Queue, либо эмитить преварительно подписаные слоты.
А то как делали вы будет замораживать интерфейс, что не есть хорошо.
Если владеете языком вероятного противника - на этом форуме была тема с книгами по QT. Если нет - примеры из site-packages\PyQt4\examples\
Вот еще по русски _ttp://forum.script-coding.info/viewforum.php?id=6
Почитал Rapid GUI Programming with Python and Qt
Как я понял правильно это главный тред это GUI, в нём прописать какие то сигналы и из него запускать всякие другие треды которые будут делать emit в главный тред. А поскольку emit дело быстрое он не будет задумываться. А QtGui.qApp.processEvents() это такой костыль который больше для одно поточных долгих приложений, который посылает всё что наработано в GUI?
truporez
Май 7, 2010 17:05:23
В целом верно. Часто processEvents применяется для обработки событий при вызове QProgressDialog.
Схематично это выглядит так:
pd = MyProgressDialog(self)
th = MyThread(self)
th.start()
while th.isRunning():
if pd.wasCanceled():
th.terminate()
break
QtGui.qApp.processEvents()
pd.close()
Если прогрессдиалог нежелателен, можно организовать работу через очередь(Queue) и timerEvent: нитка отправляет в очередь данные которые по таймеру форма выводит в gui.
necrozyablo
Май 10, 2010 23:16:43
А можно ещё пару вопросов?
Я вот просто в общем не знаю как лучше реализовать т.к. похоже методов несколько
У меня ситуация с сервера я по шифрованному протоколу(т.е. напрямую данные сам брать не могу) в 2 окна получаю всякие данные о заказчиках и некоторые логи. Все эти данные я через pywin считываю и окнами формы также нормально уже управляю.
Собственно поскольку я не знаю в какой момент произойдёт обновления информации. Я решил создать Стековый тред в котором по таймеру каждую секунду идёт сигнал в 2 треда которые проверяют данные с окон(один с одного второй со второго). В этих тредах я считываю данные из окон и произвожу расчёты если что то нужно сделать то я записываю время когда это надо сделать и добовляю в очередь Стекового треда из которого по времени эти команды запускаются.
Вообще так нормально делать или я создавая свой Стековый тред пишу велосипед?
————
И ещё я не совсем понял как работает lock = QReadWriteLock() и self.mutex = QMutex() наверное сказывается не очень хорошее знание англ.
В примерах зачем то используют и то и то, а в документации написано что это конкурирующие методы?
И вот я пытаюсь сделать 2 раза подряд
self.Test.start()
self.Test.start()
Но срабатывает только первый, хотя если дождаться выполнения Test и тогда его запустить 2 раз то он тоже сработает.
Test это
class Test(QThread):
def __init__(self, lock, parent=None):
super(Test, self).__init__(parent)
self.lock = lock
self.mutex = QMutex()
self.num=parent.num
def method3(self):
self.mutex.lock();
self.num *= 5;
time.sleep(1.5)
self.num /= 4;
self.mutex.unlock();
def run(self):
self.method3()
self.emit(SIGNAL(“indexed(int)”), self.num)
Что интересно если сделать Test2 (копия Test только имя др) и запустить его одновременно то они нормально будут вместе выполнятся, но self.mutex.lock(); для переменной self.num не сработает. И получится что если взять за входное число 6 то будет 6*5*5/4/4, а не 6*lock(5/4)unlock*5/4
Складывается у меня чувство что всё работает как то не так как я думаю…
necrozyablo
Май 10, 2010 23:39:01
Вот а с таким кодом всё нормально локается и анлокается и получается в конце из 6 число 8, а не 9
Заработало после того как я сделал через lock.lockForWrite()
self.Test.start()
self.Test2.start()
print self.num
class Test(QThread):
def __init__(self, lock, parent=None):
super(Test, self).__init__(parent)
self.lock = lock
self.mutex = QMutex()
self.num=parent.num
print 'init test qthread'
def method3(self):
self.mutex.lock();
try:
self.lock.lockForWrite()
self.num[0] *= 5;
time.sleep(1.5)
self.num[0] /= 4;
finally:
self.lock.unlock()
self.mutex.unlock();
def run(self):
self.method3()
self.emit(SIGNAL("indexed(int)"), self.num[0])
class Test2(QThread):
def __init__(self, lock, parent=None):
super(Test2, self).__init__(parent)
self.lock = lock
self.stopped = False
self.mutex = QMutex()
self.num=parent.num
def method3(self):
print 'method3',self.num[0]
try:
self.lock.lockForWrite()
self.num[0] *= 5;
time.sleep(1.5)
self.num[0] /= 4;
finally:
self.lock.unlock()
print 'method3',self.num[0]
self.mutex.unlock();
def run(self):
self.method3()
self.emit(SIGNAL("indexed(int)"), self.num[0])
Я вот одного понять не могу почему я 2 раза подряд не могу заюзать self.Test.start()
pasaranax
Май 11, 2010 09:22:04
Не понял, а зачем вызывать метод start у класса Test, а не у его экземпляра?
necrozyablo
Май 11, 2010 12:50:07
pasaranax
Не понял, а зачем вызывать метод start у класса Test, а не у его экземпляра?
Ну вообще там по коду у меня так
from functions import Test
class StartQT4(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.lock = QReadWriteLock()
self.num=[6,8]
self.Test = Test(self.lock, self)
self.Test2 = Test2(self.lock, self)
self.connect(self.Test, SIGNAL("indexed(int)"), self.log_frame_deb3)
self.connect(self.ui.DebugButton, QtCore.SIGNAL("clicked()"), self.log_frame_deb)
def log_frame_deb3(self, fstatus):
self.num[0]=fstatus
def log_frame_deb(self):
self.Test.start()
#self.Test.start()
self.Test2.start()
print self.num
Нажимаю на DebugButton срабатывает log_frame_deb в нём у меня запускаются Threds Test и Test2 они делают emit ‘indexed(int)’ в log_frame_deb3
Нить Test я постом выше писал.