fbpx

Как имитировать волну с помощью QPainter() в PySide/PyQt4

266 просмотра
0
0 Комментариев

Здравствуйте. Я пытаюсь нарисовать волну с помощью QPainter(). Точки должны поочереди опускаться, а затем подниматься. Написал такой код:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
 
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, time
 
class Test(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.pts = [[80, 50], [180, 50], [280, 50], [430, 50], [580, 50], [680, 50], [780, 50]]
        button = QPushButton(self)
        button.setText('Print Hello')
 
        exit_button = QPushButton(self)
        exit_button.setText('Exit App')
        exit_button.move(0, 50)
 
        self.timer = QTimer(self)
        QObject.connect(self.timer, SIGNAL('timeout()'), self.wave)
        self.timer.start(5)
 
        QObject.connect(button, SIGNAL('clicked()'), self.print_h)
        QObject.connect(exit_button, SIGNAL('clicked()'), example.closeAllWindows)
 
    def print_h(self):
        print 'hello!'
 
    def poly(self, pts):
        return QPolygonF(map(lambda p: QPointF(*p), pts))
 
    def paintEvent(self, event):
        painter = QPainter(self)
 
        pts = self.pts[:]
 
        painter.setPen(QPen(QColor(Qt.darkGreen), 3))
        painter.drawPolyline(self.poly(pts))
 
        painter.setBrush(QBrush(QColor(255, 0, 0)))
        painter.setPen(QPen(QColor(Qt.black), 1))
 
        for x, y in pts:
            painter.drawEllipse(QRectF(x - 4, y - 4, 8, 8))
 
            # print pts
 
    def wave(self):
 
        while True:
            y = 1
 
            if self.pts[0][1] and self.pts[6][1] == 49:
                y = y
 
            if self.pts[0][1] and self.pts[6][1] == 551:
                y = -y
 
            self.pts[0][1] += y
            self.pts[6][1] += y
 
            self.update()
 
            print self.pts
 
        #QApplication.processEvents()
 
if __name__ == '__main__':
    example = QApplication(sys.argv)
    test2 = Test()
    test2.resize(800, 600)
    test2.show()
    test2.raise_()
    #test2.wave()
    sys.exit(example.exec_())

Но изза него виснет программа, есть также альтернатива функции wave():

def wave(self):
    for point in self.pts:
        while point[1] < 600:
            point[1] += 1
            self.update()
            QApplication.processEvents()

Но она делает только половину работы и меня смущает факт присутствия QApplication.processEvents(). Заранее спасибо.


Добавить комментарий

1 Ответы

Python Опубликовано 19.01.2019
0

Насколько я понял у вас немного не правильно построена логика программы. У вас есть периодическое событие таймера, по которому вы вызываете метод wave(). И там застреваете в бесконечном цикле что приводит к остановке обработки сообщений GUI. Вызов метода processEvents() позволяет обработать накопившиеся сообщения. В вашем случае, насколько я знаю без него никак не обойтись. Если хотите без processEvents() тогда не делайте бесконечный цикл в методе wave().

Дополнение:
я бы делал так:

#! /usr/bin/env python
# -*- coding: utf-8 -*-
 
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, time, math
 
class Test(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.pts = [[80, 300],
                    [180, 300],
                    [280, 300],
                    [430, 300],
                    [580, 300],
                    [680, 300],
                    [780, 300]]
        self.time = 0
        self.time_step = 0.002
        self.timer_id = self.startTimer(1);
 
    def poly(self, pts):
        return QPolygonF(map(lambda p: QPointF(*p), pts))
 
    def timerEvent(self, event):
        if self.timer_id == event.timerId():
            self.update_wave()
            self.time += self.time_step
            self.update()
 
    def update_wave(self):
        k = 0
        phi = 0.7
        for p in self.pts:
            p[1] =300 + 100*math.sin(self.time+phi*k)
            k += 1
 
    def paintEvent(self, event):
        painter = QPainter(self)
        pts = self.pts
        painter.setPen(QPen(QColor(Qt.darkGreen), 3))
        painter.drawPolyline(self.poly(pts))
        painter.setBrush(QBrush(QColor(255, 0, 0)))
        painter.setPen(QPen(QColor(Qt.black), 1))
        for x, y in pts:
            painter.drawEllipse(QRectF(x - 4, y - 4, 8, 8))
 
if __name__ == '__main__':
    example = QApplication(sys.argv)
    test2 = Test()
    test2.resize(800, 600)
    test2.show()
    sys.exit(example.exec_())

В функцию update_wave() подставте своё уравнение волны.

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up