简体   繁体   中英

Multi-Threading Tkinter Python

I am trying to create an instrumental cluster using the OBDII and the tkinter as the GUI. The problem is that, the GUI is non responsive and the draw time is very bad as I have only 1 thread. I am new to python and the OOP concepts and is the reason I am not sure how to proceed here. This is what I want to do, I want two threads one for the drawing while other too process the data. Also can I use multiple threads to draw the objects too? Any help is appreciated

import tkinter as tk
from PIL import ImageTk
from PIL import Image
import datetime
import obd


class SimpleApp(object):
    def __init__(self, master, **kwargs):
        self.master = master
        self.canvas = tk.Canvas(width=1400, height=800)
        self.canvas.pack()
        self.update = self.draw().__next__
        master.after(1, self.update)

    def draw(self):
        image_bk = Image.open("img/1.png")
        image = Image.open("img/2.png")
        image1 = Image.open("img/3.png")
        image_prnd = Image.open("img/4.png")
        angle = 2  # 0 -> 270
        angle1 = 0  # 0 -> 89
        Speed = 0
        RPM = 0
        Fuel = 0
        Temp = 0
        Time = ' '
        tkimage_bk = ImageTk.PhotoImage(image_bk)
        self.canvas.create_image(700, 400, image=tkimage_bk)
        self.canvas.create_text(100, 770, fill="white", font="BatmanForeverOutline 20 bold", text=" 70 F")
        tkimage_prnd = ImageTk.PhotoImage(image_prnd)

        while True:

            tkimage = ImageTk.PhotoImage(image.rotate(angle))
            tkimage1 = ImageTk.PhotoImage(image1.rotate(angle1))

            canvas_obj = self.canvas.create_image(690, 400, image=tkimage)
            canvas_obj1 = self.canvas.create_image(700, 400, image=tkimage1)
            self.canvas.create_image(700, 400, image=tkimage_prnd)
            self.canvas.create_text(700, 350, fill="white", font="BatmanForeverAlternate 20 bold ", text="MPH")
            self.canvas.create_text(700, 525, fill="white", font="BatmanForeverAlternate 20 bold ", text="RPM")
            self.canvas.create_text(700, 655, fill="white", font="BatmanForeverOutline 22 bold  ",  text="P  R  N      S")
            self.canvas.create_text(760, 655, fill='white', font="BatmanForeverAlternate 45  ", text="D")
            speed = self.canvas.create_text(700, 290, fill="white", font="Beyond 80  ", text=str(Speed))
            rpm = self.canvas.create_text(700, 465, fill="white", font="Beyond 65  ", text=str(RPM))
            temp = self.canvas.create_text(1250, 240, fill="white", font="BatmanForeverOutline 22   ",text=str(Temp) + " F")
            fuel = self.canvas.create_text(1250, 470, fill='white', font="BatmanForeverOutline 22  ", text=str(Fuel) + " %")
            time1 = self.canvas.create_text(1000, 770, fill="white", font="BatmanForeverOutline 20 bold", text=datetime.datetime.now().strftime("%a, %d %B"))
            time2 = self.canvas.create_text(1250, 770, fill="white", font="BatmanForeverOutline 20 bold", text=datetime.datetime.now().strftime("%I : %M : %S"))
            run_time = self.canvas.create_text(500, 770, fill="white", font="BatmanForeverOutline 20 bold",text=str(Time))
            self.master.after_idle(self.update)

            yield
            self.canvas.delete(time1)
            self.canvas.delete(canvas_obj)
            self.canvas.delete(canvas_obj1)
            self.canvas.delete(time1)
            self.canvas.delete(time2)
            self.canvas.delete(run_time)
            self.canvas.delete(temp)
            self.canvas.delete(fuel)
            self.canvas.delete(speed)
            self.canvas.delete(rpm)


            RPM = str(connection.query(cmd).value)
            RPM = RPM.split()
            RPM = int(RPM[ 0 ])

            Speed = str(connection.query(cmd1).value)
            Speed = Speed.split()
            Speed = int(Speed[ 0 ] / 1.60934)

            Temp = str(connection.query(cmd2).value)
            Temp = float(Temp.split()[ 0 ])

            Time = str(connection.query(cmd3).value)
            Time = int(Time.split()[ 0 ])

            Fuel = str(connection.query(cmd4).value)
            Fuel = int(float(Fuel.split()[ 0 ]))


            if (Speed > -1 and Speed < 21):
                angle = (Speed * 0.75)
                angle = 360 - angle
            else:
                angle = ((20 * 0.75) + ((Speed - 20) * 1.5))
                angle = 360 - angle

            if (RPM > -1 and RPM < 1000):
                angle1 = 0.016 * RPM

            else:
                angle1 = 16 + (RPM - 1000) * 0.0296


connection = obd.OBD()

cmd = obd.commands.RPM
cmd1 = obd.commands.SPEED
cmd2 = obd.commands.COOLANT_TEMP
cmd3 = obd.commands.RUN_TIME
cmd4 = obd.commands.FUEL_LEVEL

root = tk.Tk()
app = SimpleApp(root)

root.mainloop()

As far as I remember, tkinter incorrectly processes changes to the gui not from the main thread. But you can perform calculations in other threads and transfer to the main one.

Pay attention to the tkinter after method. Using it, you can check the data in streams at some intervals.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM