pythonpython-3.xmatplotlibtkinterpython-nonlocal

SyntaxError: name 'v' is used prior to nonlocal declaration


I looked at similar problems, but I could not find solutions for my mistake in them.

Problem:

In the StartPage block, I enter the data for the graph, which is based on these values ​​in the PageOne block, but the data of the first block cannot be used in the second block. They need to ask something either global or nonlocal, but I don’t know where to insert it.

import matplotlib
from math import *
import pylab
from matplotlib import mlab
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import tkinter as tk
from tkinter import ttk
from tkinter import *

g = 9.81

class Fly(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        tk.Tk.wm_title(self, "Fly")

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (StartPage, PageOne):
            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()



class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Начальная страница")
        label.pack(pady=10, padx=10)

        button = ttk.Button(self, text="Visit Page 1",
                            command=lambda: controller.show_frame(PageOne))
        button.pack()

        v = IntVar()
        angle = IntVar()
        x0 = IntVar()
        y0 = IntVar()
        v2 = IntVar()
        angle2 = IntVar()
        x02 = IntVar()
        y02 = IntVar()
        v3 = IntVar()
        angle3 = IntVar()
        x03 = IntVar()
        y03 = IntVar()

        frame2 = Frame(self, borderwidth=4, relief=GROOVE)
        frame2.pack()

        first = Label(self, text='Данные для первого графика')
        first.pack()

        second = Label(self, text='Начальная скорость')
        second.pack()
        entry = Entry(self, width=10, textvariable=v)
        entry.pack()

        third = Label(self, text='Угол выстрела')
        third.pack()
        entry = Entry(self, width=10, textvariable=angle)
        entry.pack()

        fourth = Label(self, text='Начальная координата x')
        fourth.pack()
        entry = Entry(self, width=10, textvariable=x0)
        entry.pack()

        fifth = Label(self, text='Начальная координата y')
        fifth.pack()
        entry = Entry(self, width=10, textvariable=y0)
        entry.pack()

        frame3 = Frame(self, borderwidth=4, relief=GROOVE)
        frame3.pack()

        first = Label(self, text='Данные для второго графика')
        first.pack()

        second = Label(self, text='Начальная скорость')
        second.pack()
        entry = Entry(self, width=10, textvariable=v2)
        entry.pack()

        third = Label(self, text='Угол выстрела')
        third.pack()
        entry = Entry(self, width=10, textvariable=angle2)
        entry.pack()

        fourth = Label(self, text='Начальная координата x')
        fourth.pack()
        entry = Entry(self, width=10, textvariable=x02)
        entry.pack()

        fifth = Label(self, text='Начальная координата y')
        fifth.pack()
        entry = Entry(self, width=10, textvariable=y02)
        entry.pack()

        first = Label(self, text='Данные для третьего графика')
        first.pack()

        second = Label(self, text='Начальная скорость')
        second.pack()
        entry = Entry(self, width=10, textvariable=v3)
        entry.pack()

        third = Label(self, text='Угол выстрела')
        third.pack()
        entry = Entry(self, width=10, textvariable=angle3)
        entry.pack()

        fourth = Label(self, text='Начальная координата x')
        fourth.pack()
        entry = Entry(self, width=10, textvariable=x03)
        entry.pack()

        fifth = Label(self, text='Начальная координата y')
        fifth.pack()
        entry = Entry(self, width=10, textvariable=y03)
        entry.pack()

        nonlocal v
        nonlocal angle
        nonlocal x0
        nonlocal y0
        nonlocal v2
        nonlocal angle2
        nonlocal x02
        nonlocal y02
        nonlocal v3
        nonlocal angle3
        nonlocal x03
        nonlocal y03


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Generate")
        label.pack(pady=10, padx=10)

        button1 = ttk.Button(self, text="Поменять значения",
                             command=lambda: controller.show_frame(StartPage))
        button1.pack()

        f = Figure(figsize=(5, 5), dpi=100)
        a = f.add_subplot(111)

        canvas = FigureCanvasTkAgg(f, self)
        canvas.show()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

        toolbar = NavigationToolbar2TkAgg(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        t = ((2 * v * sin(angle)) / g)
        vx = v * cos(angle)

        t2 = ((2 * v2 * sin(angle2)) / g)
        vx2 = v2 * cos(angle2)

        t3 = ((2 * v3 * sin(angle3)) / g)
        vx3 = v3 * cos(angle3)

        dx = 0.01
        xmin = x0
        xmax = vx * t * cos(angle)
        xmin2 = x02
        xmax2 = vx2 * t2 * cos(angle2)
        xmin3 = x03
        xmax3 = vx3 * t3 * cos(angle3)

        def func(x0, v, g, y0, angle):
            y = x0 * tan(angle) - (1 / (2 * v ** 2)) * ((g * x0 ** 2) / (cos(angle) ** 2)) + y0
            if y == 0:
                return 0.0
            return y


        def func2(x02, v2, y02, angle2):
            y2 = x02 * tan(angle2) - (1 / (2 * v2 ** 2)) * ((g * x02 ** 2) / (cos(angle2) ** 2)) + y02
            if y2 == 0:
                return 0.0
            return y2


        def func3(x03, v3, y03, angle3):
            y3 = x03 * tan(angle3) - (1 / (2 * v3 ** 2)) * ((g * x03 ** 2) / (cos(angle3) ** 2)) + y03
            if y3 == 0:
                return 0.0
            return y3


        xlist = mlab.frange(xmin, xmax, dx)
        xlist2 = mlab.frange(xmin2, xmax2, dx)
        xlist3 = mlab.frange(xmin3, xmax3, dx)

        ylist = [func(x0, v, g, y0, angle) for x0 in xlist]
        ylist2 = [func2(x02, v2, y02, angle2) for x02 in xlist2]
        ylist3 = [func3(x03, v3, y03, angle3) for x03 in xlist3]

        pylab.plot(xlist, ylist)
        pylab.plot(xlist2, ylist2)
        pylab.plot(xlist3, ylist3)

        pylab.show()


app = Fly()
app.mainloop()

I don’t know what part of the code to throw, so I threw off the whole.

I apologize to those who read this, but did not understand my problem. Please write what will be incomprehensible, I will try to give more information.


Solution

  • You could declare such variables in the scope of the module, i.e. at the top of your code put:

    import matplotlib
    from math import *
    import pylab
    from matplotlib import mlab
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
    from matplotlib.figure import Figure
    import tkinter as tk
    from tkinter import ttk
    from tkinter import *
    
    g = 9.81
    v = IntVar()
    angle = IntVar()
    x0 = IntVar()
    y0 = IntVar()
    v2 = IntVar()
    angle2 = IntVar()
    x02 = IntVar()
    y02 = IntVar()
    v3 = IntVar()
    angle3 = IntVar()
    x03 = IntVar()
    y03 = IntVar()
    

    then rewrite StartPage like this:

    class StartPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            label = tk.Label(self, text="Начальная страница")
            label.pack(pady=10, padx=10)
    
            button = ttk.Button(self, text="Visit Page 1",
                                command=lambda: controller.show_frame(PageOne))
            button.pack()
    
            frame2 = Frame(self, borderwidth=4, relief=GROOVE)
            frame2.pack()
    
            first = Label(self, text='Данные для первого графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=v)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=angle)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=x0)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=y0)
            entry.pack()
    
            frame3 = Frame(self, borderwidth=4, relief=GROOVE)
            frame3.pack()
    
            first = Label(self, text='Данные для второго графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=v2)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=angle2)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=x02)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=y02)
            entry.pack()
    
            first = Label(self, text='Данные для третьего графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=v3)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=angle3)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=x03)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=y03)
            entry.pack()
    

    As another (maybe nicer?) alternative, you might consider using a shared object to store the data, and give both frames a reference to that object, for example:

    import matplotlib
    from math import *
    import pylab
    from matplotlib import mlab
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
    from matplotlib.figure import Figure
    import tkinter as tk
    from tkinter import ttk
    from tkinter import *
    
    g = 9.81
    
    
    class MyData():
        v = IntVar()
        angle = IntVar()
        x0 = IntVar()
        y0 = IntVar()
        v2 = IntVar()
        angle2 = IntVar()
        x02 = IntVar()
        y02 = IntVar()
        v3 = IntVar()
        angle3 = IntVar()
        x03 = IntVar()
        y03 = IntVar()
    
    
    class Fly(tk.Tk):
    
        def __init__(self, *args, **kwargs):        
            tk.Tk.__init__(self, *args, **kwargs)
    
            tk.Tk.wm_title(self, "Fly")
    
            container = tk.Frame(self)
            container.pack(side="top", fill="both", expand=True)
            container.grid_rowconfigure(0, weight=1)
            container.grid_columnconfigure(0, weight=1)
    
            self.frames = {}
            data = MyData
    
            for F in (StartPage, PageOne):
                frame = F(container, self, data)
    
                self.frames[F] = frame
    
                frame.grid(row=0, column=0, sticky="nsew")
    
            self.show_frame(StartPage)
    
        def show_frame(self, cont):
            frame = self.frames[cont]
            frame.tkraise()
    
    
    class StartPage(tk.Frame):
    
        def __init__(self, parent, controller, data):
            tk.Frame.__init__(self, parent)
            label = tk.Label(self, text="Начальная страница")
            label.pack(pady=10, padx=10)
    
            button = ttk.Button(self, text="Visit Page 1",
                                command=lambda: controller.show_frame(PageOne))
            button.pack()
    
            frame2 = Frame(self, borderwidth=4, relief=GROOVE)
            frame2.pack()
    
            first = Label(self, text='Данные для первого графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=data.v)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=data.angle)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=data.x0)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=data.y0)
            entry.pack()
    
            frame3 = Frame(self, borderwidth=4, relief=GROOVE)
            frame3.pack()
    
            first = Label(self, text='Данные для второго графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=data.v2)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=data.angle2)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=data.x02)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=data.y02)
            entry.pack()
    
            first = Label(self, text='Данные для третьего графика')
            first.pack()
    
            second = Label(self, text='Начальная скорость')
            second.pack()
            entry = Entry(self, width=10, textvariable=data.v3)
            entry.pack()
    
            third = Label(self, text='Угол выстрела')
            third.pack()
            entry = Entry(self, width=10, textvariable=data.angle3)
            entry.pack()
    
            fourth = Label(self, text='Начальная координата x')
            fourth.pack()
            entry = Entry(self, width=10, textvariable=data.x03)
            entry.pack()
    
            fifth = Label(self, text='Начальная координата y')
            fifth.pack()
            entry = Entry(self, width=10, textvariable=data.y03)
            entry.pack()
    
    
    class PageOne(tk.Frame):
    
        def __init__(self, parent, controller, data):
            tk.Frame.__init__(self, parent)
            label = tk.Label(self, text="Generate")
            label.pack(pady=10, padx=10)
    
            button1 = ttk.Button(self, text="Поменять значения",
                                 command=lambda: controller.show_frame(StartPage))
            button1.pack()
    
            f = Figure(figsize=(5, 5), dpi=100)
            a = f.add_subplot(111)
    
            canvas = FigureCanvasTkAgg(f, self)
            canvas.show()
            canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
    
            toolbar = NavigationToolbar2TkAgg(canvas, self)
            toolbar.update()
            canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
    
            t = ((2 * v * sin(data.angle)) / g)
            vx = data.v * cos(data.angle)
    
            t2 = ((2 * data.v2 * sin(data.angle2)) / g)
            vx2 = data.v2 * cos(data.angle2)
    
            t3 = ((2 * data.v3 * sin(data.angle3)) / g)
            vx3 = data.v3 * cos(data.angle3)
    
            dx = 0.01
            xmin = data.x0
            xmax = vx * t * cos(data.angle)
            xmin2 = data.x02
            xmax2 = vx2 * t2 * cos(data.angle2)
            xmin3 = data.x03
            xmax3 = vx3 * t3 * cos(data.angle3)
    
            def func(x0, v, g, y0, angle):
                y = x0 * tan(angle) - (1 / (2 * v ** 2)) * ((g * x0 ** 2) / (cos(angle) ** 2)) + y0
                if y == 0:
                    return 0.0
                return y
    
    
            def func2(x02, v2, y02, angle2):
                y2 = x02 * tan(angle2) - (1 / (2 * v2 ** 2)) * ((g * x02 ** 2) / (cos(angle2) ** 2)) + y02
                if y2 == 0:
                    return 0.0
                return y2
    
    
            def func3(x03, v3, y03, angle3):
                y3 = x03 * tan(angle3) - (1 / (2 * v3 ** 2)) * ((g * x03 ** 2) / (cos(angle3) ** 2)) + y03
                if y3 == 0:
                    return 0.0
                return y3
    
    
            xlist = mlab.frange(xmin, xmax, dx)
            xlist2 = mlab.frange(xmin2, xmax2, dx)
            xlist3 = mlab.frange(xmin3, xmax3, dx)
    
            ylist = [func(x0, data.v, g, data.y0, data.angle) for x0 in xlist]
            ylist2 = [func2(x02, data.v2, data.y02, data.angle2) for x02 in xlist2]
            ylist3 = [func3(x03, data.v3, data.y03, data.angle3) for x03 in xlist3]
    
            pylab.plot(xlist, ylist)
            pylab.plot(xlist2, ylist2)
            pylab.plot(xlist3, ylist3)
    
            pylab.show()
    
    
    app = Fly()
    app.mainloop()
    

    There are other errors too, but this works around your scoping issue.