Форум сайта python.su
zezeВ последнем примере на моем компе отрисовка выполняется 0.08 сек., а ведь там всего 270x40.
Объясните пожалуйста эти торможения, так как в Qt их нету?
p = QtGui.QPainter( im ) p.fillRect( 0, 0, phi, 40, QtGui.QColor('red') ) p.fillRect( phi, 0, 270-phi, 40, QtGui.QColor('gray') ) del p
Офлайн
Loki
Окно немного “подтармаживает” в момент установки нового рисунка, сделал потокоНЕбезопасным способом, только в качестве примера:# -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui import sys, math class MyThread(QtCore.QThread): def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.running = False self.phi=0.0 def run(self): self.running = True while self.running: self.emit(QtCore.SIGNAL("mysignal(QString)"), "%s" % self.phi) if int(self.MyRadianToGradus(self.phi)+0.5)*280/360 < 280: self.phi += self.MyGradusToRadian(20.0) else: self.phi = self.MyGradusToRadian(0.0) self.sleep(1) def MyRadianToGradus(self, phiedit): gradus = phiedit * 360/(2*math.pi) return gradus def MyGradusToRadian(self, phiedit): radian = phiedit * 2*math.pi / (360) return radian class MyLabel(QtGui.QLabel): def __init__(self, title=None, parent=None): super(MyLabel, self).__init__(title, parent) self.setFrameShape(QtGui.QFrame.Box) self.setMinimumSize(280,50) self.setText("<font color='red'>Закрашивание полосы</font>") self.phi = 0.0 def MyDraw(self, phi): phi = 270/6.2*phi im = QtGui.QImage(270, 40, QtGui.QImage.Format_ARGB32) for j in range(0, 270, 1): for i in range(39, -1, -1): if j<phi: im.setPixel(j, i, QtGui.QColor('gray').rgba()) else: im.setPixel(j, i, QtGui.QColor('red').rgba()) self.setPixmap(QtGui.QPixmap(im)) class MyWindow(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.label = MyLabel() self.label.setAlignment(QtCore.Qt.AlignCenter) self.btnStart = QtGui.QPushButton("Запустить зарисовку") self.btnStop = QtGui.QPushButton("Остановить зарисовку") self.btnStop.setEnabled(False) self.vbox = QtGui.QVBoxLayout() self.vbox.addWidget(self.label) self.vbox.addWidget(self.btnStart) self.vbox.addWidget(self.btnStop) self.setLayout(self.vbox) self.mythread = MyThread() self.connect(self.btnStart, QtCore.SIGNAL("clicked()"), self.on_start) self.connect(self.btnStop, QtCore.SIGNAL("clicked()"), self.on_stop) self.connect(self.mythread, QtCore.SIGNAL("mysignal(QString)"), self.on_change, QtCore.Qt.QueuedConnection) def on_start(self): if not self.mythread.isRunning(): self.mythread.start() self.btnStart.setEnabled(False) self.btnStop.setEnabled(True) def on_stop(self): self.mythread.running = False self.btnStart.setEnabled(True) self.btnStop.setEnabled(False) def on_change(self, phi): self.label.MyDraw(float(phi)) def closeEvent(self, event): self.hide() self.mythread.running = False self.mythread.wait(5000) event.accept() if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = MyWindow() window.setWindowTitle("Запуск и остановка закрашивания") window.resize(300, 100) window.show() sys.exit(app.exec_())
Офлайн
zeze, незнаю, у меня все работает…
Попробуй все скопировать и запустить, а не кусками!
Офлайн
Loki
Попробуй все скопировать и запустить, а не кусками!
Офлайн
class MyLabel(QtGui.QLabel): def __init__(self, title="", parent=None):
Офлайн
agalenclass MyLabel(QtGui.QLabel): def __init__(self, title="", parent=None):
agalenp = QtGui.QPainter(im) p.fillRect(0, 0, phi, 40, QtGui.QColor('red')) p.fillRect(phi, 0, 270-phi, 40, QtGui.QColor('gray')) del p
im = QtGui.QImage(270, 40, QtGui.QImage.Format_ARGB32) for j in range(0, 270, 1): for i in range(39, -1, -1): if j<phi: im.setPixel(j, i, QtGui.QColor('gray').rgba()) else: im.setPixel(j, i, QtGui.QColor('red').rgba()) self.setPixmap(QtGui.QPixmap(im))
Отредактировано zeze (Апрель 8, 2013 14:33:01)
Офлайн
Код от Loki для python 2.6:
# -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui import sys, math, time class MyThread(QtCore.QThread): def __init__(self, parent=None): QtCore.QThread.__init__(self, parent) self.running = False self.phi=0.0 def run(self): self.running = True while self.running: self.emit(QtCore.SIGNAL("mysignal(QString)"), "%s" % self.phi) if int(self.MyRadianToGradus(self.phi)+0.5)*280/360 < 280: self.phi += self.MyGradusToRadian(20.0) else: self.phi = self.MyGradusToRadian(0.0) self.sleep(1) def MyRadianToGradus(self, phiedit): gradus = phiedit * 360/(2*math.pi) return gradus def MyGradusToRadian(self, phiedit): radian = phiedit * 2*math.pi / (360) return radian class MyLabel(QtGui.QLabel): def __init__(self, title="", parent=None): super(MyLabel, self).__init__(title, parent) self.setFrameShape(QtGui.QFrame.Box) self.setMinimumSize(280,50) self.setText(u"<font color='red'>Закрашивание полосы</font>") self.phi = 0.0 def MyDraw(self, phi): phi = 270/6.2*phi im = QtGui.QImage(270, 40, QtGui.QImage.Format_ARGB32) #c = time.clock() #for j in range(0, 270, 1): # for i in range(39, -1, -1): # if j<phi: # im.setPixel(j, i, QtGui.QColor('gray').rgba()) # else: # im.setPixel(j, i, QtGui.QColor('red').rgba()) #print time.clock() - c c = time.clock() p = QtGui.QPainter( im ) p.fillRect( 0, 0, phi, 40, QtGui.QColor('red') ) p.fillRect( phi, 0, 270-phi, 40, QtGui.QColor('gray') ) print time.clock() - c del p self.setPixmap(QtGui.QPixmap(im)) class MyWindow(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.label = MyLabel() self.label.setAlignment(QtCore.Qt.AlignCenter) self.btnStart = QtGui.QPushButton(u"Запустить зарисовку") self.btnStop = QtGui.QPushButton(u"Остановить зарисовку") self.btnStop.setEnabled(False) self.vbox = QtGui.QVBoxLayout() self.vbox.addWidget(self.label) self.vbox.addWidget(self.btnStart) self.vbox.addWidget(self.btnStop) self.setLayout(self.vbox) self.mythread = MyThread() self.connect(self.btnStart, QtCore.SIGNAL("clicked()"), self.on_start) self.connect(self.btnStop, QtCore.SIGNAL("clicked()"), self.on_stop) self.connect(self.mythread, QtCore.SIGNAL("mysignal(QString)"), self.on_change, QtCore.Qt.QueuedConnection) def on_start(self): if not self.mythread.isRunning(): self.mythread.start() self.btnStart.setEnabled(False) self.btnStop.setEnabled(True) def on_stop(self): self.mythread.running = False self.btnStart.setEnabled(True) self.btnStop.setEnabled(False) def on_change(self, phi): self.label.MyDraw(float(phi)) def closeEvent(self, event): self.hide() self.mythread.running = False self.mythread.wait(5000) event.accept() if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = MyWindow() window.setWindowTitle(u"Запуск и остановка закрашивания") window.resize(300, 100) window.show() sys.exit(app.exec_())
Офлайн
Причина тормозов, как правильно отметил agalen, - это попиксельная отрисовка. Она даже на С++ скорее всего бы тормозила.
По поводу организации анимации.
Все-таки, можно обойтись без потоков.
В Qt можно рисовать прямо в виджетах (без промежуточной картинки), но делать это можно только в paintEvent().
Поэтому обычно создают таймер, по сигналу которого обновляется анимация (точнее ее параметры, в данном случае длина закраски phi), и вызывается метод виджета update(), который вызовет событие перерисовки.
Почему нельзя обновлять параметры (модель, phi в данном случае) в paintEvent? Потому что paintEvent вызывается при разных событиях, например, изменение размера виджета.
В виде кода (на базе agalen и Loki):
# -*- coding: utf-8 -*- import sys import math from PyQt4 import QtCore, QtGui def phi_generator(width=720, step=10): phi = 0.0 while True: if (math.degrees(phi) + 0.5) * width / 360 < width: phi += math.radians(step) else: phi = 0 yield phi class MyLabel(QtGui.QLabel): def __init__(self, title="", parent=None): super(MyLabel, self).__init__(title, parent) self.setMinimumSize(280, 50) self.setText(u"<font color='red'>Закрашивание полосы</font>") self.phi = 0.0 self.phi_gen = phi_generator() def paintEvent(self, event): width, height = self.width(), self.height() phi = width / 6.2 * self.phi p = QtGui.QPainter(self) p.fillRect(0, 0, phi, height, QtGui.QColor('red')) p.fillRect(phi, 0, width - phi, height, QtGui.QColor('gray')) def animation_step(self): self.phi = self.phi_gen.next() self.update() class MyWindow(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.label = MyLabel() self.label.setAlignment(QtCore.Qt.AlignCenter) self.btnStart = QtGui.QPushButton(u"Запустить зарисовку") self.btnStop = QtGui.QPushButton(u"Остановить зарисовку") self.vbox = QtGui.QVBoxLayout() self.vbox.addWidget(self.label) self.vbox.addWidget(self.btnStart) self.vbox.addWidget(self.btnStop) self.setLayout(self.vbox) self.paint_timer = QtCore.QTimer( interval=50, timeout=self.label.animation_step, ) self.btnStart.clicked.connect(self.paint_timer.start) self.btnStop.clicked.connect(self.paint_timer.stop) if __name__ == "__main__": import sys app = QtGui.QApplication(sys.argv) window = MyWindow() window.setWindowTitle(u"Запуск и остановка закрашивания") window.resize(300, 100) window.show() sys.exit(app.exec_())
Офлайн
reclosedev
В виде кода (на базе agalen и Loki):
# -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui, uic import math phi = 0.0 class ld(QtGui.QDialog): def __init__(self, parent=None): super(ld, self).__init__(parent) self.ui = uic.loadUi("ld.ui", self) self.timer = QtCore.QTimer() self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.MyTimer) self.timer.setInterval(3) self.timer.start() def paintEvent(self, QPaintEvent): if self.ui.radioButton.isChecked(): painterRect = QtGui.QPainter(self) painterRect.setBrush(QtGui.QColor('black')) painterRect.drawRect(50, 50, 720, 492) self.MyDraw() self.update() def MyRadianToGradus(self, phiedit): gradus = phiedit * 360 / (2 * math.pi) return gradus def MyGradusToRadian(self, phiedit): radian = phiedit * 2 * math.pi / (360) return radian def MyTimer(self): global phi self.update() if int(self.MyRadianToGradus(phi) + 0.5) * 720 / 360 < 720: phi += self.MyGradusToRadian(6.0) else: phi = self.MyGradusToRadian(6.0) def MyDraw(self): global phi p = QtGui.QPainter(self) p.translate(50, 50) p.fillRect(0, 0, int(self.MyRadianToGradus(phi)+0.5)*720/360, 492, QtGui.QColor('red')) if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = ld() window.show() sys.exit(app.exec_())
reclosedev
Причина тормозов, как правильно отметил agalen, - это попиксельная отрисовка. Она даже на С++ скорее всего бы тормозила.
Отредактировано zeze (Апрель 9, 2013 09:59:44)
Офлайн
Покажите код загрузки и отображения картинок.
Офлайн