Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » Торможения таймера при зарисовки цветом [RSS Feed]

#1 Апрель 5, 2013 11:24:41

zeze
От: Москва
Зарегистрирован: 2013-04-05
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Прямоугольная область с торможениями закрашивается красным цветом. Но вот один раз я абсолютно также сделал и прямоугольная область быстро начала зарисовыватся красным цветом.
Как будто это сбой самого 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_())

А почему он в Python иногда проскакивает с быстрой скоростью? То есть раз 5 работало медленно, потом заработало быстро, а потом 15 раз медленно.
Принцип такой, я копировал папку с проектом и удалял не нужный код, до того кода который я выложил.

Я сделал так

timer.start(5000)

Проверял на секундомере на смартфоне. В итоге первые несколько раз по 3 секунды, а потом идёт интервал по 5 секунд, даже немного поменьше (4,7 или 4,8 секунды).

Я делал так

timer.start(15)

Картинка через каждые 0,5 секунды обновляется.
1. Что же с этим таймером?
2. Может я таймер не правильно описываю в коде, хотя Python ни какие ошибки не выдаёт?

Офлайн

#2 Апрель 5, 2013 13:13:52

Loki
Зарегистрирован: 2013-03-13
Сообщения: 28
Репутация: +  4  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Как по мне, то такая программа, сама по себе, на момент создания концепции, уже была ошибочна.
Во-первых: ты вызываешь перерисовку всего окна по таймеру и ждешь следующей перерисовки от таймера, это не верно (конечно, это мое, субьективное, мнение).
Во-вторых: для таких целей обычно используют модель-представление (опять только по моему очень небольшому опыту)
В-третих: если ты все же решил не пользоватся модель-представлением, то тебе нужно вынести таймер в отдельный поток и из этого потока посылать сигнал (не перерисовывать напрямую из паралельного потока, а только сигнал) и перерисовывать окно по сигналу.

Предположим, что ты хотел, чтобы окно твоей программы “подвисало” и с опозданием реагировало на события мыши. Тогда ты скорее всего стартуешь таймер не из того метода, почему именно с __init__?, ведь на момент инициализации экземпляра класса, таймер у тебя уже запущен и идет набор значения phi, так как в в методе MyTimer ты в не зависимости от того активен self.checkBox или нет, проверяешь phi на условие и в зависимости от результата меняешь его. Т.е. переменная характеризующая степень законченности процесса наберает значение без самого процесса.

Офлайн

#3 Апрель 5, 2013 13:52:39

zeze
От: Москва
Зарегистрирован: 2013-04-05
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

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__ не конструктор, а где же тогда надо было запускать таймер?

Офлайн

#4 Апрель 5, 2013 14:13:48

Loki
Зарегистрирован: 2013-03-13
Сообщения: 28
Репутация: +  4  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Я хотел объявить запуск таймера, как я это делал в Qt из конструктора, но из Вашего вопроса я понял, что __init__ не конструктор, а где же тогда надо было запускать таймер?
Запускать таймер нужно там где это логично и действительно нужно, например при нажатии на кнопку у тебя что-то должно выполнется через определенный момент, ну так и привязывай запуск таймера по событию кнопки…
Метод __init__ действительно конструктор и он запускается в момент создания экземпляра класса, и если он является конструктором класса, то это не значит, что именно в нем нужно стартовать таймер, ведь это бессмысленно - тебе так не кажется?…
Я не хотел подвисаний.
Если не хочешь чтобы программа висела не делай update() по таймеру.

Отредактировано Loki (Апрель 5, 2013 14:15:13)

Офлайн

#5 Апрель 5, 2013 15:01:46

zeze
От: Москва
Зарегистрирован: 2013-04-05
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Loki
Если не хочешь чтобы программа висела не делай update() по таймеру.

Удалил из таймера 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)

Офлайн

#6 Апрель 5, 2013 15:41:11

Loki
Зарегистрирован: 2013-03-13
Сообщения: 28
Репутация: +  4  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Попробую вечером сделать тебе пример с многопоточным приложением…

Офлайн

#7 Апрель 8, 2013 08:33:32

zeze
От: Москва
Зарегистрирован: 2013-04-05
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Loki
Попробую вечером сделать тебе пример с многопоточным приложением…

Хорошо, буду ждать.
Не ужели для такой простой задачи в Python без потоков не обойтись?

Офлайн

#8 Апрель 8, 2013 10:18:11

agalen
От:
Зарегистрирован: 2011-03-23
Сообщения: 185
Репутация: +  17  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Это будет тормозить всегда:

    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())



Офлайн

#9 Апрель 8, 2013 10:24:50

zeze
От: Москва
Зарегистрирован: 2013-04-05
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

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())

Объясните пожалуйста эти торможения, так как в Qt их нету?

И какже быть?
Дело в том, что мне нужно каждый раз, чтобы по таймеру менялись и рисовались разные картинки. А данная зада лишь упрощённый пример для понимания.

Отредактировано zeze (Апрель 8, 2013 10:26:03)

Офлайн

#10 Апрель 8, 2013 10:35:34

Loki
Зарегистрирован: 2013-03-13
Сообщения: 28
Репутация: +  4  -
Профиль   Отправить e-mail  

Торможения таймера при зарисовки цветом

Окно немного “подтармаживает” в момент установки нового рисунка, сделал потокоНЕбезопасным способом, только в качестве примера:

# -*- 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)

Офлайн

  • Начало
  • » GUI
  • » Торможения таймера при зарисовки цветом [RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version