Python GUI在打开线程时释放

Python GUI在打开线程时释放,python,multithreading,user-interface,arduino,serial-communication,Python,Multithreading,User Interface,Arduino,Serial Communication,我相信这是你见过的最糟糕的代码之一,但这是我的第一个面向对象程序。 该程序应与Arduino通信,以收集有关太阳能电池阵列和一些电池的信息。它还必须自动管理一些逆变器等。 我已经删除了GUI的大部分,以使代码更易于阅读,但它仍然相当大。 我试图编写的代码是,一旦串行通信开始,我就可以更改GUI上的参数,我试图通过打开一个在后台工作的新线程来实现这一点,并收集或发送数据。 实际情况是,一旦串行通信启动,GUI就会冻结,过了一段时间,一切都会死灰复燃。 我在线程中添加了一个打印,以检查通信是否开始,

我相信这是你见过的最糟糕的代码之一,但这是我的第一个面向对象程序。 该程序应与Arduino通信,以收集有关太阳能电池阵列和一些电池的信息。它还必须自动管理一些逆变器等。 我已经删除了GUI的大部分,以使代码更易于阅读,但它仍然相当大。 我试图编写的代码是,一旦串行通信开始,我就可以更改GUI上的参数,我试图通过打开一个在后台工作的新线程来实现这一点,并收集或发送数据。 实际情况是,一旦串行通信启动,GUI就会冻结,过了一段时间,一切都会死灰复燃。 我在线程中添加了一个打印,以检查通信是否开始,以及在python chrash之前是否从串行端口收集了一些信息

import Tkinter
import tkMessageBox
import ttk
import serial
import sys
import glob
import threading
from time import sleep


class PaginaPrincipale(Tkinter.Tk, threading.Thread):
    dati_in = None
    dati_out = None

    def __init__(self, parent):
        Tkinter.Tk.__init__(self, parent)
        self.parent = parent
        si1 = Tkinter.IntVar()
        au1 = Tkinter.IntVar()
        si2 = Tkinter.IntVar()
        au2 = Tkinter.IntVar()

        self.grid()

        # those classes will manage the auto function
        def manuale(variable):
            if variable == 1:
                print(si1.get())
            if variable == 2:
                print(si2.get())

        def automatico(variable):
            if variable == 1:
                print(au1.get())
            if variable == 2:
                print(au2.get())

        # this class manages the serial connection, it scans for the available ports
        # and when the user select the desired one it should open it and start a thread
        # I still haven't implemented the update of the GUI
        def connetti():

            # Here I extract the clicked value on the listbox
            def selezione(evt):
                w = evt.widget
                index = int(w.curselection()[0])
                value = w.get(index)
                scelta_box.config(text=value)

            # Here I try to open the selected port and to start a new thread which keeps exchanging
            # information with the microcontroller (Arduino)
            def avvia_seriale(porta):
                try:
                    print(porta)
                    pagina_connessione.destroy()
                    threading.Thread(target=comunicazione(porta))

                except:
                    # Here PiCharm gives me a warning: too broad exception clause
                    tkMessageBox.showerror('Serial port', 'Can''t open the selected serial port')
                    pass

            # here I will place all the serial communication statements
            def comunicazione(porta):
                porta_seriale = serial.Serial(porta)
                while porta_seriale.isOpen():
                    porta_seriale.write(1)
                    sleep(.1)
                    self.dati_in = porta_seriale.readline()
                    sleep(.1)
                    print self.dati_in
                pass

            # Here I scan for available ports and I put them inside the listbox
            if sys.platform.startswith('win'):
                ports = ['COM%s' % (i + 1) for i in range(256)]
            elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
                # this excludes your current terminal "/dev/tty"
                ports = glob.glob('/dev/tty[A-Za-z]*')
            elif sys.platform.startswith('darwin'):
                ports = glob.glob('/dev/tty.*')
            else:
                raise EnvironmentError('Unsupported platform')

            result = []
            for port in ports:
                try:
                    s = serial.Serial(port)
                    s.close()
                    result.append(port)  # il metodo append() aggiunge alla lista result l'ultimo termine trovato
                except (OSError, serial.SerialException):
                    pass

            # I open a new toplevel so that when I choose and open the serial port I close it and nothing remains
            # on the main page
            pagina_connessione = Tkinter.Toplevel()
            pagina_connessione.title('Gestione connessione')

            descrizione_scelte = Tkinter.Label(pagina_connessione, text='Lista scelte:', justify='left')
            descrizione_scelte.grid(column=0, row=0, sticky='W')
            lista_scelte = Tkinter.Listbox(pagina_connessione, height=len(result), selectmode='single')
            contatore = len(result)
            for item in result:
                lista_scelte.insert(contatore, item)
                contatore += 1

            if contatore == 0:
                lista_scelte.insert(0, 'Nessuna porta seriale')

            lista_scelte.grid(column=0, row=1)
            lista_scelte.bind('<<ListboxSelect>>', selezione)

            bottone_connessione = Tkinter.Button(pagina_connessione, text='Connetti!',
                                                 command=lambda: avvia_seriale(scelta_box.cget("text")))
            bottone_connessione.grid(column=1, row=1)

            scelta_box = Tkinter.Label(pagina_connessione, width=15, height=1, borderwidth=3, background='blue')
            scelta_box.grid(column=0, row=2)

            pagina_connessione.mainloop()

        #
        #
        # This is the main GUI
        #
        #
        frame_batteria1 = Tkinter.Frame(self, borderwidth=2, bg="black")
        frame_batteria1.grid(column=0, row=0, sticky='news')

        self.descrittore_v_b_1 = Tkinter.Label(frame_batteria1, text="V Batteria 1", font=("Helvetica", 8),
                                               justify='center')
        self.descrittore_v_b_1.grid(column=0, row=0, sticky='news')
        self.descrittore_i_b_1 = Tkinter.Label(frame_batteria1, text="I Batteria 1", font=("Helvetica", 8),
                                               justify='center')
        self.descrittore_i_b_1.grid(column=1, row=0, sticky='NEWS')

        self.vbatteria1 = Tkinter.Scale(frame_batteria1, bd=4, troughcolor='blue', resolution=0.1, state='disabled',
                                        from_=15, to=0)
        self.vbatteria1.grid(column=0, row=1, sticky='NEWS')
        self.ibatteria1 = Tkinter.Scale(frame_batteria1, bd=4, troughcolor='blue', resolution=0.1, state='disabled',
                                        from_=10, to=0)
        self.ibatteria1.grid(column=1, row=1, sticky='NEWS')

        self.descrittore_inverter1 = Tkinter.Label(self, text="Inverter 1", font=("Helvetica", 8), justify='left')
        self.descrittore_inverter1.grid(column=0, row=3, sticky='NEWS')

        self.scelte_manuali_inverter1 = Tkinter.Radiobutton(self, text="Acceso", variable=si1, value=1,
                                                            command=lambda: manuale(1))
        self.scelte_manuali_inverter1.grid(column=0, row=4, sticky='NEWS')
        self.scelte_manuali_inverter1 = Tkinter.Radiobutton(self, text="Spento", variable=si1, value=0,
                                                            command=lambda: manuale(1))
        self.scelte_manuali_inverter1.grid(column=0, row=5, sticky='NEWS')

        self.scelta_automatica_inverter1 = Tkinter.Checkbutton(self, text="Automatico", variable=au1, onvalue=1,
                                                               offvalue=0, command=lambda: automatico(1))
        self.scelta_automatica_inverter1.grid(column=2, row=4, sticky='NEWS')

        #
        #
        # separators
        #
        #
        ttk.Separator(self, orient='horizontal').grid(row=6, columnspan=8, sticky='EW')
        ttk.Separator(self, orient='vertical').grid(row=2, column=3, rowspan=4, sticky='NS')

        self.gestisci_connessione = Tkinter.Button(self, text="Connetti!", command=connetti)
        self.gestisci_connessione.grid(row=7, column=6, sticky='EW')


if __name__ == "__main__":
    applicazione = PaginaPrincipale(None)
    applicazione.title('Pannello di controllo')
    applicazione.mainloop()
导入Tkinter
导入tkMessageBox
导入ttk
导入序列号
导入系统
导入glob
导入线程
从时间上导入睡眠
PaginaPrincipale类(Tkinter.Tk,threading.Thread):
dati_in=无
dati_out=无
定义初始化(自身,父级):
Tkinter.Tk.\uuuuu init\uuuuuu(自,父)
self.parent=parent
si1=Tkinter.IntVar()
au1=Tkinter.IntVar()
si2=Tkinter.IntVar()
au2=Tkinter.IntVar()
self.grid()
#这些类将管理自动功能
def手册E(可变):
如果变量==1:
打印(si1.get())
如果变量==2:
打印(si2.get())
def automatico(变量):
如果变量==1:
打印(au1.get())
如果变量==2:
打印(au2.get())
#这个类管理串行连接,它扫描可用的端口
#当用户选择所需的线程时,它应该打开它并启动一个线程
#我还没有实现GUI的更新
def connetti():
#在这里,我提取列表框上单击的值
def selezione(evt):
w=evt.widget
index=int(w.curselection()[0])
值=w.get(索引)
scelta_box.config(text=value)
#在这里,我尝试打开所选端口并启动一个新线程,该线程将继续交换
#微控制器信息(Arduino)
def avvia_串行(端口):
尝试:
打印(porta)
帕吉纳·康涅狄格州摧毁()
threading.Thread(目标=Comuniczione(端口))
除:
#这里PiCharm给了我一个警告:过于宽泛的例外条款
tkMessageBox.Burror('串行端口','无法打开所选串行端口')
通过
#这里我将放置所有串行通信语句
def Comuniczione(传送):
porta_serial=串行。串行(porta)
而porta_serial.isOpen()
串行端口写入(1)
睡眠(.1)
self.dati_in=porta_serial.readline()
睡眠(.1)
在中打印self.dati_
通过
#在这里,我扫描可用端口,并将它们放在列表框中
如果sys.platform.startswith('win'):
端口=['COM%s'(i+1)用于范围(256)内的i]
elif sys.platform.startswith('linux')或sys.platform.startswith('cygwin'):
#这不包括您当前的终端“/dev/tty”
ports=glob.glob('/dev/tty[A-Za-z]*'))
elif sys.platform.startswith('darwin'):
ports=glob.glob('/dev/tty.*')
其他:
raise环境错误(“不支持的平台”)
结果=[]
对于端口中的端口:
尝试:
s=串行。串行(端口)
s、 关闭()
result.append(port)#il metodo append()aggiunge alla lista result l'ultimo termine trovato
除了(OSError,serial.SerialException):
通过
#我打开一个新的toplevel,这样当我选择并打开串行端口时,我会关闭它,而不会留下任何东西
#在主页上
pagina_connessione=Tkinter.Toplevel()
pagina_connessione.名称(“Gestione connessione”)
descripiione\u scelte=Tkinter.Label(pagina\u conversation,text='Lista scelte:',justify='left')
描述一个网格(列=0,行=0,粘性=W')
lista\u scelte=Tkinter.Listbox(连接页面,高度=len(结果),选择mode='single')
contatore=len(结果)
对于结果中的项目:
列表插入(续,项目)
contatore+=1
如果contatore==0:
lista_scelte.insert(0,'Nessuna porta Serial')
lista_scelte.grid(列=0,行=1)
lista_scelte.bind(“”,selezione)
bottone_connessione=Tkinter.Button(pagina_connessione,text='Connetti!',
command=lambda:avvia_serial(scelta_box.cget(“text”))
bottone_connessione.grid(列=1,行=1)
scelta_box=Tkinter.Label(页码连接,宽度=15,高度=1,边框宽度=3,背景为蓝色)
scelta_box.grid(列=0,行=2)
pagina_connessione.mainloop()
#
#
#这是主GUI
#
#
边框1=Tkinter.frame(自,边框宽度=2,bg=“黑色”)
frame_batteria1.grid(列=0,行=0,sticky='news')
self.descriptore_v_b_1=Tkinter.Label(frame_bateria1,text=“v bateria 1”,font=(“Helvetica”,8),
对齐(中间)
自我描述1.gr
threading.Thread(target=comunicazione(porta))
threading.Thread(target=lambda:comunicazione(porta))
t = threading.Thread(target=lambda:comunicazione(porta))
t.start()