问题描述:
提示:使用Tkinter写的程序通过pycharm IDEA的pyinstaller 打包exe,执行之后报错
报错内容如下:
Traceback (most recent call last):
File "peakcan.py", line 2096, in <module>
File "tkinter\tix.py", line 214, in __init__
_tkinter.TclError: can't find package Tix
解决方案:
将tix放到相同路径下即可正常运行。
也可以将二者通过WinRAR等工具合并
原因我们可以根据它的报错行进行查找,File “tkinter\tix.py”, line 214, in init
索引进去的话我们可以看到他的路径是本地索引路径,因此打包后就找不到tix包。
tix包的位置在哪里
首先我们要找到编译器python 打开tcl文件夹,文件Tix就在里面。
问题描述
提示:通过pycharm IDEA使用Tkinter写的程序,当我们在子线程对gui进行更新的时候会出现错误,那何种方法可以让他通过子线程来操控gui呢
解决方案:
提示:这里填写该问题的具体解决方案:
我的解决方案为在子线程中判断当前状态,在主线程中创建计时器作响应,并在程序的工作开始与结束正确打开和结束计时器,节省资源,保证软件正确运行。
介绍:我们通过子线程对这些变量进行修改,再通过主线程中的函数做相应的gui更新。
#这里是更新的函数 通过root.after递归进行循环
#self.timer_running的意义是 当我们执行我们要的操作之后,可以将这个定时器关掉。
def timer(self):
self.gui_fresh()
if self.timer_running:
root.after(1000, self.timer)
#这只是一个例子,子线程中的标识赋值后,通过定时器判断更新gui
def gui_fresh(self):
if self.erase_fin == 1:
if self.error_1 == 1 or self.error_2 == 1:
self.IncludeTextMessage("Once the radar is powered back on, click 'Start' quickly")
self.timer_running = 0
elif self.error_1 == 2 or self.error_2 == 2:
self.IncludeTextMessage("Disconnect the radar first, restart the software/initialization and re-power the radar")
self.timer_running = 0
else:
self.IncludeTextMessage("Erasing is complete")
self.IncludeTextMessage("The firmware is being updated, please be patient...")
self.erase_fin = 0
if self.trans1_fin == 1:
self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(30, self.finsh, self.dur))
self.trans1_fin = 0
if self.trans2_fin == 1:
self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(60, self.finsh, self.dur))
self.trans2_fin = 0
if self.trans3_fin == 1:
self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(100, self.finsh, self.dur))
self.trans3_fin = 0
if self.trans4_fin == 1:
self.IncludeTextMessage("Sending complete!")
self.trans4_fin = 0
self.timer_running = 0
不过需要注意的是,要注意好时间问题,比如下面我对时间的处理
首先这是子线程的定义
erase = threading.Thread(target=self.erasing)
erase.start()
transmit = threading.Thread(target=self.transmiting)
transmit.start()
下面是第一个子线程的操作
def erasing(self):
print("ok1")
output_lock.acquire()
print("ok1")
try:
print("ok2")
result = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
st = time.perf_counter()
while result != PCAN_ERROR_OK:
result = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
if time.perf_counter() - st >= 5:
self.error_1 = 1
break
if time.perf_counter() - st <= 0.15:
self.error_1 = 2
result = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
print("ok2")
st = time.perf_counter()
while result != PCAN_ERROR_OK:
result = self.ReadMessageFD() if self.m_IsFD else self.ReadMessage()
if time.perf_counter() - st >= 7:
self.error_2 = 1
break
if time.perf_counter() - st <= 0.12:
self.error_2 = 2
# self.IncludeTextMessage("Erasing is complete")
print("ok3")
finally:
# ?????
if self.error_2 == 0 and self.error_1 == 0:
self.error_ok = 1
else:
self.error_ok = 0
self.erase_fin = 1
output_lock.release()
下面是第二个子线程的操作,注意在一开始进行了14秒的休眠,这是因为这个应用的实际意义就是更新一个固件在雷达上,所以需要确保擦除完成,再进行写入,还要添加一些限制如果擦除失败则不进行,并且关闭定时器,这些都需要根据自己的需求去修改。
def transmiting(self):
time.sleep(14)
output_lock.acquire()
print(self.error_ok)
if self.error_ok == 1:
try:
prt = 0
self.last_time = 0
start_time = time.perf_counter()
for i in range(self.num_of_packets):
for j in range(10):
start_index = (i * 10 + j) * 8
end_index = min(((i * 10 + j) + 1) * 8, self.data_len)
data_len_this_packet = end_index - start_index
data_array_this_packet = self.ubyte_array(*self.data_array[start_index:end_index])
CANMsg = TPCANMsg()
CANMsg.ID = int("29E", 16)
CANMsg.LEN = int(data_len_this_packet)
CANMsg.MSGTYPE = PCAN_MESSAGE_STANDARD
for k in range(CANMsg.LEN):
CANMsg.DATA[k] = int(hex(data_array_this_packet[k]), 16)
while 1:
if time.perf_counter() - self.last_time > 0.0004:
break
stsResult = self.m_objPCANBasic.Write(self.m_PcanHandle, CANMsg)
self.last_time = time.perf_counter()
if stsResult != PCAN_ERROR_OK:
break
if end_index == self.data_len:
break
progress = end_index / self.data_len * 100
self.finsh = "\u2593" * int(progress // 2)
self.dur = time.perf_counter() - start_time
if 30 <= progress <= 31 and prt == 0:
prt += 1
# self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(progress, finsh, dur))
self.trans1_fin = 1
if 60 <= progress <= 61 and prt == 1:
prt += 1
# self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(progress, finsh, dur))
self.trans2_fin = 1
if progress == 100:
# self.IncludeTextMessage("\rProgress: {:^3.0f}%[{}]{:.2f}s\n".format(progress, finsh, dur))
self.trans3_fin = 1
break
time.sleep(0.5)
CANMsg = TPCANMsg()
CANMsg.ID = int("29E", 16)
CANMsg.LEN = int(8)
CANMsg.MSGTYPE = PCAN_MESSAGE_STANDARD
text = "02 01 03 04 55 66 77 88"
numbers = text.split(" ")
int_numbers = [int(num) for num in numbers]
data = self.ubyte_array(*int_numbers)
for z in range(8):
CANMsg.DATA[z] = int(hex(data[z]), 16)
self.m_objPCANBasic.Write(self.m_PcanHandle, CANMsg)
# self.IncludeTextMessage("Sending complete!")
self.trans4_fin = 1
self.__m_iCount = 1
finally:
# ?????
output_lock.release()
else:
output_lock.release()