【问题标题】:how rotate a line about the origin?如何绕原点旋转一条线?
【发布时间】:2018-06-15 09:09:56
【问题描述】:

我想通过读取文本文件值来旋转和翻译关于原点的一行,它可以工作,但它给了我最后一个和最后一个输出。我无法将其视为动画。 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_())

提前致谢。

【问题讨论】:

  • 请分享文件
  • @eyllanesc 它只是具有行和列的 .txt 文件。我的代码正在为 txt 文件运行,但问题是它一次显示所有行。
  • 请查看 tkinter 代码,我希望在 pyqt5 中使用相同的代码。请帮帮我。
  • tkinter 不是 PyQt,如果你分享我可以测试你的代码的文件,我不想浪费时间创建一个新的 .txt,认为如果你节省我的时间,我可以节省你。

标签: python-3.x pyqt5 qpainter


【解决方案1】:

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

我的解决方案建议有一个通过信号每隔一定时间间隔提供数据的类,以生成我使用的时间间隔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_())

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 2018-08-03
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多