我正在尝试使用 tkinter 创建一个简单的 GUI 应用程序,该应用程序在按下按钮时运行三个测试脚本。我决定使用线程模块,因为我注意到 GUI 在尝试执行任何这些测试脚本(每个都是单独的 .py 文件)时会停止执行。此脚本中的每一个都使用 python CAN 模块,该模块在开始时有一个实例,允许脚本连接到 PCAN 设备
当我单独运行测试时,每个脚本都与 TKinter.py 应用程序同时运行并且 GUI 不会冻结,但是当我选择所有脚本一起运行时,每个脚本最终都会启动不同的线程,这会导致问题,因为我的 PCAN 设备一次只能为一个脚本初始化,如果我在相似的时间同时运行多个,结果最终会不准确。
我想知道是否有一种方法可以让 tkinter 应用程序在测试用例运行时不受影响地运行,但测试用例只能一个接一个地按顺序运行。
请注意,如果我使用线程中的 join 方法,GUI 仍然会因此停止响应。请帮忙。
# Library Imports
from tkinter import *
import os
import threading
from CAN_Test1 import Test1
from CAN_Test2 import Test2
from CAN_Test3 import Test3
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
## Dimensions of Window
root = Tk()
root.title("Acceptance Testing: UDS ISO-14229")
root.geometry("830x445")
# Plot Figure in Canvas's
f1 = Figure(figsize=(3,3), dpi=100)
axes_1 = f1.add_axes([0.2,0.15,0.7,0.7])
axes_1.set_title("Ignition Status")
axes_1.set_ylim(-1,8)
# axes_1.set_xlabel("Time")
axes_1.set_yticks(ticks=[0,1,3,4,6], labels=["OFF", "START", "ACC", "RUN", "CRANK"])
axes_1.set_xticks(ticks=[])
f2 = Figure(figsize=(3,3), dpi=100)
axes_2 = f2.add_axes([0.2,0.15,0.7,0.7])
axes_2.set_title("Vehicle Speed")
axes_2.set_ylim(-5,100)
# axes_2.set_xlabel("Time")
axes_2.set_ylabel("Speed in Kph")
axes_2.set_xticks(ticks=[])
# Canvas's for matplotlib figures
canvas3 = FigureCanvasTkAgg(f1,root)
canvas3.draw()
canvas3.get_tk_widget().grid(row=1, column=2, rowspan=10, columnspan=6, padx=10, pady=10)
canvas4 = FigureCanvasTkAgg(f2,root)
canvas4.draw()
canvas4.get_tk_widget().grid(row=1, column=8, rowspan=10, columnspan=6, padx=10, pady=10)
# Functions for test execution and opening logs, report and trace window:
def test1_runstat():
global option1
option1 = var1.get()
def test2_runstat():
global option2
option2 = var2.get()
def test3_runstat():
global option3
option3 = var3.get()
def test_run():
# count=0
# test_list=[Test1, Test2, Test3]
test_list_status=[]
test_list_status.append(option1)
test_list_status.append(option2)
test_list_status.append(option3)
# for item in test_list_status:
# if item == "ON":
# t1 = threading.Thread(target=test_list[count])
# t1.start()
# count += 1
# if count == 3:
# return
if test_list_status[0] == "ON":
t1 = threading.Thread(target=Test1)
t1.start()
if test_list_status[1] == "ON":
t1 = threading.Thread(target=Test2)
t1.start()
if test_list_status[2] == "ON":
t1 = threading.Thread(target=Test3)
t1.start()
else:
pass
def open_trace_window():
os.startfile("C:\\Program Files\\PEAK-System\\PEAK-Drivers 4\\Tools\\PcanView.exe")
def open_log_file_dir():
os.startfile("C:\\Users\\15202\\OneDrive\\Desktop\\L2P\\Python\\CAN_Logs")
# Declaring variables for checking receive a result (if the button is pressed or not)
var1 = StringVar()
var2 = StringVar()
var3 = StringVar()
# A) Assigning three check boxes for three tests; B) Assigning four buttons: Start Test/Tests,Open Logs,Generate Report
# and Open Pcan Viewer
# A)
myLabel1 = Label(root, text="Test Scenarios:")
e1 = Entry(root, width=30)
e1.grid(row=11,column=6)
e1.insert(0,"Enter Ign State: 0/1/3/4/6")
e2 = Entry(root, width=30)
e2.grid(row=11,column=13)
e2.insert(0,"Enter Veh Spd")
chk_btn1 = Checkbutton(root, text="Test Scenario 1", variable=var1, onvalue="ON", offvalue="OFF", command=test1_runstat)
chk_btn2 = Checkbutton(root, text="Test Scenario 2", variable=var2, onvalue="ON", offvalue="OFF", command=test2_runstat)
chk_btn3 = Checkbutton(root, text="Test Scenario 3", variable=var3, onvalue="ON", offvalue="OFF", command=test3_runstat)
# B)
btn1 = Button(root, text="Start Test/Tests", command=test_run)
btn2 = Button(root, text="Logs & Reports", command=open_log_file_dir)
btn3 = Button(root, text="Generate Report")
btn4 = Button(root, text="Open Trace Window", command=open_trace_window)
# C) Empty Space
myLabel4 = Label(root, text="").grid(row=12,column=0)
myLabel5 = Label(root, text="").grid(row=13,column=0)
# A) Place buttons on gui using grid; B) deselect them all initially; C) set option values to "OFF" the first time
# A)
myLabel1.grid(row=0, column=0)
chk_btn1.grid(row=1, column=0, pady=5)
chk_btn2.grid(row=2, column=0, pady=5)
chk_btn3.grid(row=3, column=0, pady=5)
chk_btn1.anchor(W)
chk_btn2.anchor(W)
chk_btn3.anchor(W)
btn1.grid(row=14, column=0, padx=5)
btn2.grid(row=14, column=1, padx=5)
btn3.grid(row=14, column=2, padx=5)
btn4.grid(row=14, column=13)
# B)
chk_btn1.deselect()
chk_btn2.deselect()
chk_btn3.deselect()
# C)
option1 = "OFF"
option2 = "OFF"
option3 = "OFF"
# The Runner !!!
root.mainloop()
'''
One Test Script of 3
'''
'''
1) Set up the H/W for the test
2) Create a Vehicle Simulation by defining some RBS messages and Tx them at their respective periodicity
3) Run the actual test for DTC
4) Stop the simulation
'''
# # Import the needed modules
import can
import time
def Test1():
# 1)
bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', baudrate=500000)
# 2)
## Define the messages to transmit periodically and as a single transmit:
msg_3B3 = can.message.Message(arbitration_id=0x3B3, data=[0x40,0x84,0xC0,0x0C,0x00,0x00,0x00,0x00], extended_id=False)
msg_41E = can.message.Message(arbitration_id=0x41E, data=[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF], extended_id=False)
msg_44C = can.message.Message(arbitration_id=0x44C, data=[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF], extended_id=False)
msg_59E = can.message.Message(arbitration_id=0x59E, data=[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF], extended_id=False)
msg_740_10_01 = can.message.Message(arbitration_id=0x740, data=[0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x00], extended_id=False)
msg_740_10_03 = can.message.Message(arbitration_id=0x740, data=[0x02,0x10,0x01,0x00,0x00,0x00,0x00,0x00], extended_id=False)
## Periodicty for messages per dbc file:
periodicity_msg_3B3 = 0.5
periodicity_msg_41E = 0.01
periodicity_msg_44C = 0.05
periodicity_msg_59E = 0.1
msgs_and_periodicity = [(msg_3B3,periodicity_msg_3B3),(msg_41E,periodicity_msg_41E),
(msg_44C,periodicity_msg_44C),(msg_59E,periodicity_msg_59E)]
for msg,period in msgs_and_periodicity:
bus.send_periodic(msg, period)
time.sleep(10)
print('Block has finished executing. Messages will now be sent at their respective periodicity')
# 3)
# bus.send()
# 4)
bus.stop_all_periodic_tasks()
bus.flush_tx_buffer()
bus.shutdown()