如何绕原点旋转一条线?

how rotate a line about the origin?

我想通过读取文本文件值来旋转和平移一条关于原点的线,它可以工作,但它在最后一个 .我无法将其视为动画。 self.update() 可能存在一些问题。文件名为无人机飞行阅读日志文件。

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

提前致谢。

我在 tkinter 中试过了,它工作正常。这是代码。

from tkinter import *  
from tkinter import ttk 
import xlrd 
import time
import math

def read_file(lineno):
    with open('d:\detect\log_file\Attitude_data_Manual_1232018_1215.txt','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
            pitch.append(float(a[4]))
            roll.append(float(a[6]))
            lineno += 1        
       # print(lineno)
    return lineno


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




app=Tk()
app.title("Python GUI Application ")  
name=ttk.Label(app, text="Draw basic line")  
name.pack()  
canvas=Canvas()  
canvas.pack()  
canvas.config(width=480,height=360) 
filename = open('d:\detect\log_file\Attitude_data_Manual_1232018_1215.txt','r')
pitch,roll=[],[]
lineno = 0
lineno = read_file(lineno)
for m in range(0,lineno,1):
    x0=-400
    x1=880
    y0=180
    y1=180
    xc=240
    yc=180

    point1= (x1,y1)
    point= (x0,y0)
    origin= (xc,yc)
    x0,y0=rotate(origin,point,roll[m]*10)
    y0=y0-(pitch[m]*60)
    canvas.move(point,x0,y0)
    x1,y1=counterrotate(origin,point1,roll[m]*10)
    y1=y1-(pitch[m]*60)
    canvas.move(point,x1,y1)
    line1=canvas.create_line(x0,y0,x1,y1,fill='green',width=1)
    blue_point= [x0,y0,x1,y1,480,0,0,0]
    green_points=[x0,y0,x1,y1,480,360,0,360]
    blue_poly=canvas.create_polygon(blue_point,fill='sky blue',width=2)
    green_poly=canvas.create_polygon(green_points,fill='green',width=2)
    canvas.create_line(0,180,480,180,fill='black',width=1)
    canvas.update()
    time.sleep(0.1)
    canvas.delete(line1)
    canvas.delete(green_poly)
    canvas.delete(blue_poly)

app.mainloop()

您必须避免在 GUI 中使用 time.sleep(),因为它会阻止事件循环并因此导致无法正确更新。我没有花时间去审查哪里出了问题,而是提出了一个正确的实施方案。

我的解决方案建议有一个 class 通过信号每隔一定时间间隔提供数据,以生成我使用 QTimer.

的时间间隔

小组件获取数据,按照您的意愿进行计算。

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