2014-10-18 88 views
0

我想製作一些動畫,但是我遇到了問題。當我檢查我的複選框,我得到的錯誤:PySide(PyQt)嘗試動畫。 (QWidget :: repaint:檢測到遞歸重繪)

QWidget::repaint: Recursive repaint detected 

那麼我該怎麼做動畫?我試圖做一個簡單的動畫:

def animation(self, paint): 
    for i in range(100): 
     paint.eraseRect(0, 0, 1000, 1000) 
     paint.drawPoint(i + 1, i + 1) 
     QtGui.QApplication.processEvents() 
     time.sleep(0.1) 
     self.update() 

全碼:

import sys, math, time 
from PySide import QtGui , QtCore 

class lab(QtGui.QWidget): 

    def __init__(self): 
     super(lab, self).__init__() 
     self.setFixedSize(900, 600) 
     self.scene = QtGui.QGraphicsScene(self) 
     self.scene.setSceneRect(0, 0, 600, 600) 
     self.view = QtGui.QGraphicsView() 
     self.view.setRenderHint(QtGui.QPainter.Antialiasing) 
     self.view.setScene(self.scene) 
     self.centerPoint_x_Lable = QtGui.QLabel("cX: ", self) 
     self.centerPoint_x_Lable.move(715, 24) 
     self.centerPoint_y_Lable = QtGui.QLabel("cY: ", self) 
     self.centerPoint_y_Lable.move(815, 24) 
     self.astroidRadius_Lable = QtGui.QLabel("R: ", self) 
     self.astroidRadius_Lable.move(715, 64) 
     self.rotationPoint_x_Lable = QtGui.QLabel("rX: ", self) 
     self.rotationPoint_x_Lable.move(715, 124) 
     self.rotationPoint_y_Lable = QtGui.QLabel("rY: ", self) 
     self.rotationPoint_y_Lable.move(815, 124) 
     self.rotationAngle_Lable = QtGui.QLabel("Ang: ", self) 
     self.rotationAngle_Lable.move(715, 164) 
     self.centerPoint_x = QtGui.QSpinBox(self) 
     self.centerPoint_x.setRange(0, 600) 
     self.centerPoint_x.setValue(300) 
     self.centerPoint_x.move(740, 20) 
     self.centerPoint_y = QtGui.QSpinBox(self) 
     self.centerPoint_y.setRange(0, 600) 
     self.centerPoint_y.setValue(300) 
     self.centerPoint_y.move(840, 20) 
     self.astroidRadius = QtGui.QSpinBox(self) 
     self.astroidRadius.setRange(20, 300) 
     self.astroidRadius.setValue(50) 
     self.astroidRadius.move(740, 60) 
     self.rotationPoint_x = QtGui.QSpinBox(self) 
     self.rotationPoint_x.setRange(0, 600) 
     self.rotationPoint_x.setValue(300) 
     self.rotationPoint_x.move(740, 120) 
     self.rotationPoint_y = QtGui.QSpinBox(self) 
     self.rotationPoint_y.setRange(0, 600) 
     self.rotationPoint_y.setValue(300) 
     self.rotationPoint_y.move(840, 120) 
     self.rotationAngle = QtGui.QSpinBox(self) 
     self.rotationAngle.setRange(0, 360) 
     self.rotationAngle.setValue(0) 
     self.rotationAngle.move(740, 160) 
     self.astroidSquare = QtGui.QLabel("S:  ", self) 
     self.astroidSquare.move(715, 220) 
     self.cursorPos_x = QtGui.QLabel("X:  ", self) 
     self.cursorPos_x.move(715, 260) 
     self.cursorPos_y = QtGui.QLabel("Y:  ", self) 
     self.cursorPos_y.move(815, 260) 
     self.checkBox = QtGui.QCheckBox("Animation", self) 
     self.checkBox.move(715, 420) 

     self.x0 = self.centerPoint_x.value() 
     self.y0 = self.centerPoint_y.value() 
     self.aX = [] 
     self.aY = [] 
     self.r = self.astroidRadius.value() 
     self.xr0 = self.rotationPoint_x.value() 
     self.yr0 = self.rotationPoint_y.value() 
     self.ang = self.rotationAngle.value() 
     self.astriodXY() 
     self.RaX = self.rotateX(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.RaY = self.rotateY(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.astroidSquare.setText("S: %d" % (math.pi *3/8 * self.r ** 2)) 


     self.connect(self.centerPoint_x, QtCore.SIGNAL("valueChanged(int)"), self.setFigure) 
     self.connect(self.centerPoint_y, QtCore.SIGNAL("valueChanged(int)"), self.setFigure) 
     self.connect(self.astroidRadius, QtCore.SIGNAL("valueChanged(int)"), self.changeSize) 
     self.connect(self.rotationPoint_x, QtCore.SIGNAL("valueChanged(int)"), self.rotationFigure) 
     self.connect(self.rotationPoint_y, QtCore.SIGNAL("valueChanged(int)"), self.rotationFigure) 
     self.connect(self.rotationAngle, QtCore.SIGNAL("valueChanged(int)"), self.rotationFigure) 

    def setFigure(self): 
     self.x0 = self.centerPoint_x.value() 
     self.y0 = self.centerPoint_y.value() 
     self.aX = [] 
     self.aY = [] 
     self.astriodXY() 
     self.RaX = self.rotateX(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.RaY = self.rotateY(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.update() 

    def changeSize(self): 
     self.r = self.astroidRadius.value() 
     self.aX = [] 
     self.aY = [] 
     self.astriodXY() 
     self.RaX = self.rotateX(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.RaY = self.rotateY(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.astroidSquare.setText("S: %d" % (math.pi *3/8 * self.r ** 2)) 
     self.update() 

    def rotationFigure(self): 
     self.xr0 = self.rotationPoint_x.value() 
     self.yr0 = self.rotationPoint_y.value() 
     self.ang = self.rotationAngle.value() 
     self.aX = [] 
     self.aY = [] 
     self.astriodXY() 
     self.RaX = self.rotateX(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.RaY = self.rotateY(self.xr0, self.yr0, self.aX, self.aY, self.ang) 
     self.update() 

    def astriodXY(self): 
     for i in range(180): 
      self.aX.append(self.r*math.cos(2*i*math.pi/180)**3 + self.x0) 
      self.aY.append(self.r*math.sin(2*i*math.pi/180)**3 + self.y0) 

    def rotateX(self, x0, y0, listX, listY, ang): 
     return [(listX[i] - x0)*math.cos(ang*math.pi/180) - (listY[i] - y0)*math.sin(ang*math.pi/180) + x0 for i in range(len(listX))] 

    def rotateY(self, x0, y0, listX, listY, ang): 
     return [(listX[i] - x0)*math.sin(ang*math.pi/180) + (listY[i] - y0)*math.cos(ang*math.pi/180) + y0 for i in range(len(listX))] 

    def rotX(self, x0, y0, X, Y, ang): 
     return (X - x0)*math.cos(ang*math.pi/180) - (Y - y0)*math.sin(ang*math.pi/180) + x0 

    def rotY(self, x0, y0, X, Y, ang): 
     return (X - x0)*math.sin(ang*math.pi/180) + (Y - y0)*math.cos(ang*math.pi/180) + y0 

    def mouseMoveEvent(self, event): 
     if self.checkBox.isChecked() == False: 
      self.cursorPos_x.setText("X: %d" % event.x()) 
      self.cursorPos_y.setText("Y: %d" % event.y()) 
      self.update() 

    def paintEvent(self, e): 
     painter = QtGui.QPainter(self) 
     painter.setPen(QtGui.QPen(QtCore.Qt.red, 3)) 
     if self.checkBox.isChecked() == False: 
      self.drawing(painter) 
     else: 
      self.animation(painter) 

    def drawing(self, paint): 
     for i in range(25): 
      if i > 0: 
       paint.setPen(QtGui.QPen(QtCore.Qt.red, 0.15)) 
      paint.drawLine(i*25, 0, i*25, 600) 
      paint.drawLine(0, i*25, 600, i*25) 
     paint.setPen(QtGui.QPen(QtCore.Qt.black, 1)) 
     for i in range(180): 
      if i < 179: 
       paint.drawLine(self.RaX[i], self.RaY[i], self.RaX[i+1], self.RaY[i+1]) 
      else: 
       paint.drawLine(self.RaX[i], self.RaY[i], self.RaX[i-i], self.RaY[i-i]) 

     x = QtGui.QCursor.pos().x() - 233 
     y = QtGui.QCursor.pos().y() - 96 
     for i in range(180): 
      if int(self.RaX[i]) == x and int(self.RaY[i]) == y: 
       if i < 179: 
        paint.setPen(QtGui.QPen(QtCore.Qt.blue, 1)) 
        paint.drawLine(self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i+1]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i+1]), self.RaX[i] + 1000*(self.RaX[i] - self.RaX[i+1]), self.RaY[i] + 1000*(self.RaY[i] - self.RaY[i+1])) 
        paint.setPen(QtGui.QPen(QtCore.Qt.green, 1)) 
        paint.drawLine(self.rotX(self.RaX[i], self.RaY[i], self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i+1]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i+1]), 90), self.rotY(self.RaX[i], self.RaY[i], self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i+1]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i+1]), 90), self.RaX[i], self.RaY[i]) 
       elif i == 179: 
        paint.drawLine(self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i-i]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i-i]), self.RaX[i] + 1000*(self.RaX[i] - self.RaX[i-i]), self.RaY[i] + 1000*(self.RaY[i] - self.RaY[i-i])) 
        paint.drawLine(self.rotX(self.RaX[i], self.RaY[i], self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i-i]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i-i]), 90), self.rotY(self.RaX[i], self.RaY[i], self.RaX[i] - 1000*(self.RaX[i] - self.RaX[i-i]), self.RaY[i] - 1000*(self.RaY[i] - self.RaY[i-i]), 90), self.RaX[i], self.RaY[i]) 

    def animation(self, paint): 
     for i in range(100): 
      paint.eraseRect(0, 0, 1000, 1000) 
      paint.drawPoint(i + 1, i + 1) 
      QtGui.QApplication.processEvents() 
      time.sleep(0.1) 
      self.update() 

if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    form = lab() 
    form.setWindowTitle("Animation") 
    form.show() 
    app.exec_() 
+0

Qt有一個內置的動畫框架。你可能有興趣看看這個:http://qt-project.org/doc/qt-4.8/animation-overview.html – 2014-10-19 01:44:40

回答

0

你從是從的paintEvent調用的函數中調用更新。

更新將再次調用paintEvent,導致遞歸。

+0

你可以解釋我,如何解決它? – byvaet 2014-10-18 18:02:17

+0

你可能不應該在動畫函數中循環,而是繪製一個動畫幀。循環應該在繪畫事件的外部。也許通過設置一個定時器(例如每秒30次)並在其回調中調用更新來繪製下一個動畫幀。 – Photon 2014-10-18 19:45:20

+0

謝謝!我改變了我的代碼並獲得了動畫。 – byvaet 2014-10-19 09:38:14