I want to rotate and translate a line about the origin by reading text file values and it working but its giving me the last and final output in the last . I am not able to see this as animation . there is some problem with self.update() may be. Filename is log file of drone flying reading.
import math
from PyQt5.QtWidgets import QWidget, QApplication, QGraphicsScene
from PyQt5.QtGui import QPainter, QColor, QBrush, QPen
from PyQt5.QtCore import Qt
import sys
import xlrd
import time
class Heads_ups(QWidget):
lineno=0
pitch,roll=[],[]
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300,300,480,360)
self.setWindowTitle('Colours')
self.show()
def read_file(self,lineno):
withopen('text file having rows and columns','r',) as f :
lines = f.readlines()[4:]
for s in lines:
a = s.split()
#print (len(a))
if(len(a)!=14):
print("point reached")
lineno += 1
continue
self.pitch.append(float(a[4]))
self.roll.append(float(a[6]))
lineno += 1
# print(lineno)
return lineno
def counterrotate(self,origin,point1,roll):
ox,oy = origin
px,py = point1
angle=math.radians(roll)
#counterclockwise
qx= ox+ math.cos(angle)*(px-ox)-math.sin(angle)*(py-oy)
qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
return qx,qy
def rotate(self,origin,point,roll):
ox,oy = origin
px,py = point
angle=math.radians(roll)
#clockwise
qx= ox+ math.cos(angle)*(px-ox)+math.sin(angle)*(py-oy)
qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
return qx,qy
def paintEvent(self,e):
# print(filename)
qp= QPainter(self)
qp.begin(self)
self.drawLine(qp)
self.update()
self.move_line(qp)
qp.end()
def drawLine(self,qp):
pen= QPen(Qt.black,2,Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(0,180,480,180)
self.update()
QApplication.processEvents()
time.sleep(0.2)
def move_line(self,qp):
pen=QPen(Qt.green,2,Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(0,180+50,480,180+50)
# self.scene=QGraphicsScene(self)
lineno = self.read_file(self.lineno)
for m in range(0,lineno,1):
x0=-400
x1=880
y0=180
y1=180
xc=240
yc=180
point=(x0,y0)
point1= (x1,y1)
origin= (xc,yc)
x0,y0=self.rotate(origin,point,self.roll[m]*10)
y0=y0-(self.pitch[m]*60)
# canvas.move(point,x0,y0)
x1,y1=self.counterrotate(origin,point1,self.roll[m]*10)
y1=y1-(self.pitch[m]*60)
dlt=qp.drawLine(x0,y0,x1,y1)
self.update()
QApplication.processEvents()
time.sleep(0.5)
# self.scene.removeItem(dlt)
if __name__ == '__main__':
app=QApplication(sys.argv)
hp=Heads_ups()
filename=open('textfile having rows and columns','r')
sys.exit(app.exec_())
Thanks in advance.
You must avoid using time.sleep()
in a GUI since it blocks the event-loop and therefore generates that it does not update correctly. I have not taken the time to review what is wrong but to propose a correct implementation.
My solution proposes to have a class that provides the data every certain interval of time through signals, to generate the intervals of time I have used a QTimer
.
The widget obtains the data and performs the calculations as you wish.
import sys
import math
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
def counterrotate(origin,point1,roll):
ox,oy = origin
px,py = point1
angle=math.radians(roll)
#counterclockwise
qx= ox+ math.cos(angle)*(px-ox)-math.sin(angle)*(py-oy)
qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
return qx,qy
def rotate(origin,point,roll):
ox,oy = origin
px,py = point
angle=math.radians(roll)
#clockwise
qx= ox+ math.cos(angle)*(px-ox)+math.sin(angle)*(py-oy)
qy= oy+ math.sin(angle)*(px-ox)+math.cos(angle)*(py-oy)
return qx,qy
class Manager(QObject):
changedValue = pyqtSignal(tuple)
def __init__(self):
QObject.__init__(self)
filename = "Attitude_data_Manual_1232018_1158.txt"
res = self.read_content(filename)
self.results = zip(*res)
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_value)
self.timer.start(100)
@pyqtSlot()
def update_value(self):
try:
self.changedValue.emit(next(self.results))
except StopIteration:
self.timer.stop()
#QCoreApplication.instance().quit()
def read_content(self, filename):
pitch = []
roll = []
with open(filename,'r') as f :
lines = f.readlines()[4:]
for s in lines:
a = s.split()
if len(a) !=14:
print("point reached")
continue
pitch.append(float(a[4]))
roll.append(float(a[6]))
return pitch, roll
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.v = None
@pyqtSlot(tuple)
def update_value(self, v):
self.v = v
self.update()
def paintEvent(self, event):
QWidget.paintEvent(self, event)
painter = QPainter(self)
r = self.rect()
if self.v:
x0, x1, y0, y1, xc, yc = -400, 880, 180, 180, 240, 180
point1 = (x1,y1)
point = (x0,y0)
origin = (xc,yc)
pitch, roll = self.v
x0,y0 = rotate(origin, point, roll*10)
y0 -= pitch*60
x1, y1 = counterrotate(origin,point1, roll*10)
y1 -= pitch*60
posx0 = QPoint(x0, y0)
posx1 = QPoint(x1, y1)
upper_polygon = QPolygonF([r.topLeft(), posx0, posx1, r.topRight()])
bottom_polygon = QPolygonF([posx0, posx1, r.bottomRight(), r.bottomLeft()])
painter.setBrush(QColor("skyblue"))
painter.drawPolygon(upper_polygon)
painter.setBrush(QColor("green"))
painter.drawPolygon(bottom_polygon)
painter.drawLine(r.left(), r.center().y(), r.right(), r.center().y())
if __name__ == '__main__':
app = QApplication(sys.argv)
manager = Manager()
w = Widget()
manager.changedValue.connect(w.update_value)
w.show()
sys.exit(app.exec_())