Форум сайта python.su
Прямоугольная область с торможениями закрашивается красным цветом. Но вот один раз я абсолютно также сделал и прямоугольная область быстро начала зарисовыватся красным цветом.
Как будто это сбой самого Pathon-а. Решил привести полный код. Может кто увидит, где может быть ошибка и отпишется.
Мой код:
# -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui, uic import math import os import struct phi = 0.0 timer = QtCore.QTimer() im = QtGui.QImage(720, 492, QtGui.QImage.Format_ARGB32) class ld(QtGui.QDialog): def __init__(self, parent=None): super(ld, self).__init__(parent) self.ui = uic.loadUi("ld.ui", self) self.connect(timer, QtCore.SIGNAL("timeout()"), self.MyTimer) timer.start((0.05 * 1000) / 60) 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 global im if self.ui.checkBox.isChecked(): for j in range(0, 720, 1): for i in range(491, -1, -1): im.setPixel(j, i, QtGui.QColor(255, 0, 0, 255).rgba()) 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 im global phi Tochka = QtGui.QPainter() Tochka.begin(self) Tochka.translate(50, 50) Tochka.drawImage(0, 0, im, 0, 0, int((2 * self.MyRadianToGradus(phi)) + 0.5), 492) Tochka.end() if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = ld() window.show() sys.exit(app.exec_())
timer.start(5000)
timer.start(15)
Офлайн
Как по мне, то такая программа, сама по себе, на момент создания концепции, уже была ошибочна.
Во-первых: ты вызываешь перерисовку всего окна по таймеру и ждешь следующей перерисовки от таймера, это не верно (конечно, это мое, субьективное, мнение).
Во-вторых: для таких целей обычно используют модель-представление (опять только по моему очень небольшому опыту)
В-третих: если ты все же решил не пользоватся модель-представлением, то тебе нужно вынести таймер в отдельный поток и из этого потока посылать сигнал (не перерисовывать напрямую из паралельного потока, а только сигнал) и перерисовывать окно по сигналу.
Предположим, что ты хотел, чтобы окно твоей программы “подвисало” и с опозданием реагировало на события мыши. Тогда ты скорее всего стартуешь таймер не из того метода, почему именно с __init__?, ведь на момент инициализации экземпляра класса, таймер у тебя уже запущен и идет набор значения phi, так как в в методе MyTimer ты в не зависимости от того активен self.checkBox или нет, проверяешь phi на условие и в зависимости от результата меняешь его. Т.е. переменная характеризующая степень законченности процесса наберает значение без самого процесса.
Офлайн
Loki
в методе MyTimer ты в не зависимости от того активен self.checkBox или нет, проверяешь phi на условие и в зависимости от результата меняешь его. Т.е. переменная характеризующая степень законченности процесса наберает значение без самого процесса.
def MyTimer(self): global phi global im1 if self.ui.checkBox_4.isChecked(): for j in range(0, 720, 1): for i in range(491, -1, -1): im1.setPixel(j, i, QtGui.QColor(255, 0, 0, 255).rgba()) self.update() if int(self.MyRadianToGradus(phi)+0.5)*720/360 < 720: phi += self.MyGradusToRadian(6.0) else: phi = self.MyGradusToRadian(6.0)
Loki
Предположим, что ты хотел, чтобы окно твоей программы “подвисало” и с опозданием реагировало на события мыши.
Loki
Тогда ты скорее всего стартуешь таймер не из того метода, почему именно с __init__?, ведь на момент инициализации экземпляра класса, таймер у тебя уже запущен и идет набор значения phi
Офлайн
Я хотел объявить запуск таймера, как я это делал в Qt из конструктора, но из Вашего вопроса я понял, что __init__ не конструктор, а где же тогда надо было запускать таймер?Запускать таймер нужно там где это логично и действительно нужно, например при нажатии на кнопку у тебя что-то должно выполнется через определенный момент, ну так и привязывай запуск таймера по событию кнопки…
Я не хотел подвисаний.Если не хочешь чтобы программа висела не делай update() по таймеру.
Отредактировано Loki (Апрель 5, 2013 14:15:13)
Офлайн
Loki
Если не хочешь чтобы программа висела не делай update() по таймеру.
# -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui, uic import math import os import struct phi = 0.0 im1 = QtGui.QImage(720, 492, QtGui.QImage.Format_ARGB32) class ld(QtGui.QDialog): def __init__(self, parent=None): super(ld, self).__init__(parent) self.ui = uic.loadUi("ld.ui", self) self.connect(self.ui.radioButton, QtCore.SIGNAL("clicked()"), self.MyClickRect) self.connect(self.ui.pushButton_3, QtCore.SIGNAL("clicked()"), self.BlockTimer) self.timer = QtCore.QTimer() self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.MyTimer) self.ui.pushButton.setText(u"Запустить") def paintEvent(self, QPaintEvent): if self.ui.radioButton.isChecked(): # Выбор прямоугольных координат self.MyDraw() self.update() def MyClickRect(self): 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 global im1 if self.ui.checkBox.isChecked(): for j in range(0, 720, 1): for i in range(491, -1, -1): im.setPixel(j, i, QtGui.QColor(255, 0, 0, 255).rgba()) 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 im1 global phi Tochka = QtGui.QPainter() Tochka.begin(self) Tochka.translate(50, 50) Tochka.drawImage(0, 0, im, 0, 0, int((2*self.MyRadianToGradus(phi))+0.5), 492) Tochka.end() def BlockTimer(self): # Выбор "Запустить" if self.ui.pushButton.text() == u"Запустить": self.timer.start((0.005 * 1000) / 60) self.ui.pushButton.setText(u"Остановить") else: self.timer.stop() self.ui.pushButton.setText(u"Запустить") if __name__ == '__main__': import sys app = QtGui.QApplication(sys.argv) window = ld() window.show() sys.exit(app.exec_())
Отредактировано zeze (Апрель 5, 2013 15:02:33)
Офлайн
Попробую вечером сделать тебе пример с многопоточным приложением…
Офлайн
Loki
Попробую вечером сделать тебе пример с многопоточным приложением…
Офлайн
Это будет тормозить всегда:
for j in range(0, 720, 1):
for i in range(491, -1, -1):
im.setPixel(j, i, QtGui.QColor(255, 0, 0, 255).rgba())
Офлайн
agalen
Это будет тормозить всегда:for j in range(0, 720, 1): for i in range(491, -1, -1): im.setPixel(j, i, QtGui.QColor(255, 0, 0, 255).rgba())
Отредактировано zeze (Апрель 8, 2013 10:26:03)
Офлайн
Окно немного “подтармаживает” в момент установки нового рисунка, сделал потокоНЕбезопасным способом, только в качестве примера:
# -*- 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_())
Отредактировано Loki (Апрель 8, 2013 10:38:54)
Офлайн