简体   繁体   中英

Python Tkinter Crashing, every run but program continues? Final polishing of Tkinter

I am new to Tkinter and a newbie, so good easy on me. I have tried to code correctly, but I must be doing something wrong. These are the issues I face.

Issues:

  • Python crash as soon as I move the slider, though the program continues?? Random
  • The zoom button doesn't update the figure though it has the same code as the slider?
  • The figure has a big Black board around it that looks crap
  • General Speed of the code is poor.

The Crashes(that keep running) are:

  • Runtime Error! Program: C:\\Python27\\pythonw.exe [MS Visual C++ Runtime Library]
  • The exception unknown software exception (0x40000015) occurred in the application at location 0x1e06016a [TclNotifier: pythonw.exe]

Those are the thing that I really would like to know just to polish off the program, make it responsive and friendly.

Thanks for any help

# ---------- Imports ------------------------------------- #
from Tkinter import *
import matplotlib
import numpy as np
# ---------- Settings ------------------------------------ #
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
# ---------- Classes  ------------------------------------ #
class App(Frame):
    def __init__(self,master=None):
        Frame.__init__(self, master)
        self._job = None
        self.canvas = None
        self.Flag_Zoom = False
        self.pack()
        self._GUI_Design()
        self._GenData()
        self._Figure(self.Arm,self.Flag_Zoom)
        # Load the figure Window
        # Send to TK           
        self.canvas = FigureCanvasTkAgg(self.f, master=self.LF_Graph)

    def _GUI_Design(self):
        # Initial Frames        
        self.LF_Control = LabelFrame(self, text='Angle Controls', width=400, height=100, )
        self.LF_Graph = LabelFrame(self, text='Figure', width=400, height=400)
        self.LF_Control.grid(row=0, column=1, padx=5,pady=1)
        self.LF_Graph.grid(row=1, column=0,columnspan=2,padx=5,pady=3)

        # Insert Controls
        # Labels
        self.LB_Info = Label(self,text="Reduced Code", justify=LEFT)
        self.LB_SP = Label(self.LF_Control, text="Spoiler:")        

        #   Slider
        self.SpScale = Scale(self.LF_Control, from_=0, to=120, orient=HORIZONTAL, length=300, resolution=1, command=self._UpdateCanvas, tickinterval=10)      

        #   Buttons
        self.Zoomb = Button(self.LF_Control, text="Zoom", command=self._Zoom)
        self.Quit = Button(self.LF_Control, text="Quit", command=self.quit)

        # Grid Layout
        self.LB_Info.grid(row=0, column=0,padx=5,pady=1)
        self.LB_SP.grid(row=0, column=0,padx=10,pady=1)
        self.SpScale.grid(row=0, column=1,padx=10,pady=1)
        self.Zoomb.grid(row=0, column=3 ,padx=10,pady=1)
        self.Quit.grid(row=1, column=3 ,padx=10,pady=1)

    def _GenData(self):
        self.Arm     = [[0,10,184.533],[0,153.734,164.932]]                 

    def _UpdateCanvas(self, event):
        self._job = self.after(100, self._Execute(self.Flag_Zoom))  #miliseconds
        if self._job:
            self.after_cancel(self._job)

    def _Figure(self,Arm,Zoom):
        # Gen Figure
        self.f = plt.figure(1,figsize=(10,10))
        self.f.frame = False
        plt.clf()
        if Zoom == False:
            plt.axis([-500,2000,-1500,1000])
        else:
            plt.axis([-100,500,-100,500])                
        plt.axes().set_aspect('equal', 'datalim')
        plt.plot(Arm[0],Arm[1],"g")

    def _Zoom(self):
        self._UpdateCanvas
        if self.Flag_Zoom == True:
            self.Flag_Zoom = False
        else:
            self.Flag_Zoom = True

    def _Execute(self,Zoom):
        RotA = self.RotateNO(self.Arm,self.SpScale.get(),[0,0])
        self._Figure(RotA,Zoom)
        self.canvas.draw()
        self.canvas.show()
        if self.canvas:
            self.canvas.get_tk_widget().grid(row=0, column=0)
# ----------  Calculations -------------------------------- #
def RotateNO(self,List,Angle,Orig):       
    # Angle: deg2rad
    th = -1.*float(Angle)/180*np.pi
    Rot = [[],[]]
    # Loop through
    for i in xrange(0,len(List[0])):
        X1 = (List[0][i]-Orig[0])*np.cos(th) - (List[1][i]-Orig[1])*np.sin(th)+Orig[0]
        Y1 = (List[0][i]-Orig[0])*np.sin(th) + (List[1][i]-Orig[1])*np.cos(th)+Orig[1]
        Rot[0].append(X1)
        Rot[1].append(Y1)
    return Rot       
# ---------- Execute Application ------------------------- #
root = Tk()
root.title("Rotation")
Exe = App(master=root)
Exe.mainloop()
root.destroy()

You need RotateNO to be a part of your class. Also zoom doesn't need to take a zoom argument because you've already initialized self.Flag_Zoom . Also change root.destroy() to Exe.destroy() . Try this:

# ---------- Imports ------------------------------------- #
from Tkinter import *
import matplotlib
import numpy as np
# ---------- Settings ------------------------------------ #
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
# ---------- Classes  ------------------------------------ #
class App(Frame):
    def __init__(self,master=None):
        Frame.__init__(self, master)
        self._job = None
        self.canvas = None
        self.Flag_Zoom = False
        self.pack()
        self._GUI_Design()
        self._GenData()
        self._Figure(self.Arm)
        # Load the figure Window
        # Send to TK           
        self.canvas = FigureCanvasTkAgg(self.f, master=self.LF_Graph)

    def _GUI_Design(self):
        # Initial Frames        
        self.LF_Control = LabelFrame(self, text='Angle Controls', width=400, height=100, )
        self.LF_Graph = LabelFrame(self, text='Figure', width=400, height=400)
        self.LF_Control.grid(row=0, column=1, padx=5,pady=1)
        self.LF_Graph.grid(row=1, column=0,columnspan=2,padx=5,pady=3)

        # Insert Controls
        # Labels
        self.LB_Info = Label(self,text="Reduced Code", justify=LEFT)
        self.LB_SP = Label(self.LF_Control, text="Spoiler:")        

        #   Slider
        self.SpScale = Scale(self.LF_Control, from_=0, to=120, orient=HORIZONTAL, length=300, resolution=1, command=self._UpdateCanvas, tickinterval=10)      

        #   Buttons
        self.Zoomb = Button(self.LF_Control, text="Zoom", command=self._Zoom)
        self.Quit = Button(self.LF_Control, text="Quit", command=self.quit)

        # Grid Layout
        self.LB_Info.grid(row=0, column=0,padx=5,pady=1)
        self.LB_SP.grid(row=0, column=0,padx=10,pady=1)
        self.SpScale.grid(row=0, column=1,padx=10,pady=1)
        self.Zoomb.grid(row=0, column=3 ,padx=10,pady=1)
        self.Quit.grid(row=1, column=3 ,padx=10,pady=1)

    def _GenData(self):
        self.Arm     = [[0,10,184.533],[0,153.734,164.932]]                 

    def _UpdateCanvas(self, event):
        self._job = self.after(100, self._Execute(self.Flag_Zoom))  #miliseconds
        if self._job:
            self.after_cancel(self._job)

    def _Figure(self,Arm):
        # Gen Figure
        self.f = plt.figure(1,figsize=(10,10))
        self.f.frame = False
        plt.clf()
        if not self.Flag_Zoom:
            print 'no zoom'
            plt.axis([-500,2000,-1500,1000])
        else:
            print 'zoom'
            plt.axis([-100,500,-100,500])                
        plt.axes().set_aspect('equal', 'datalim')
        plt.plot(Arm[0],Arm[1],"g")

    def _Zoom(self):
        if self.Flag_Zoom:
            self.Flag_Zoom = False
        else:
            self.Flag_Zoom = True
        self._UpdateCanvas
        RotA = self.RotateNO(self.Arm,self.SpScale.get(),[0,0])
        self._Figure(RotA)
        self.canvas.draw()
        self.canvas.show()

    def RotateNO(self,List,Angle,Orig):       
        # Angle: deg2rad
        th = -1.*float(Angle)/180*np.pi
        Rot = [[],[]]
        # Loop through
        for i in xrange(0,len(List[0])):
            X1 = (List[0][i]-Orig[0])*np.cos(th) - (List[1][i]-Orig[1])*np.sin(th)+Orig[0]
            Y1 = (List[0][i]-Orig[0])*np.sin(th) + (List[1][i]-Orig[1])*np.cos(th)+Orig[1]
            Rot[0].append(X1)
            Rot[1].append(Y1)
        return Rot

    def _Execute(self,Zoom):
        RotA = self.RotateNO(self.Arm,self.SpScale.get(),[0,0])
        self._Figure(RotA)
        self.canvas.draw()
        self.canvas.show()
        if self.canvas:
            self.canvas.get_tk_widget().grid(row=0, column=0)

# ---------- Execute Application ------------------------- #
root = Tk()
root.title("Rotation")
Exe = App(master=root)
Exe.mainloop()
Exe.destroy()

To minimize the grey border around your plot add

plt.xticks([])
plt.yticks([])
plt.tight_layout(pad=0.0, w_pad=0.0, h_pad=0)

to the end of your _Figure(self,Arm) method. That gives me:

tknoborder

(I changed the figsize so that the entire thing would fit on my screen)

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