在单独文件中的函数之间发送变量时遇到问题 - Python和Tkinter

时间:2016-03-13 15:59:50

标签: python tkinter python-3.4

我有一个看似基本的问题,但我不确定如何解决它。

我正在制作一个让用户在画布上画线的程序。我之前将整个代码放在一个文件中,但由于我要添加许多新工具,因此将所有函数隔离到单独的文件中似乎是明智的决定。 但是这样做会导致问题。抱歉有很多代码可以解决。这是我的代码:

root程序:root.py(我实际运行的那个)

#Import TKINTER toolset:
from tkinter import *
import starting_variables

#Starting variables:
starting_variables.start_vars()

#Tool width control:
global tool_width
tool_width = Scale(control_panel,from_=1,to=32)

canvas.bind("<Button-1>",line_start_xy)

control_panel.pack(side=LEFT,fill=Y)
tool_width.pack()
wrkspace.pack()
canvas.pack()

#Runs window:
window.mainloop()

此文件定义了从开始所需的所有变量:(starting_variables.py)

from tkinter import *

def start_vars():
    #Starting variables:
    line_startx = 0
    line_starty = 0
    line_endx = 0
    line_endy = 0
    mouse_x = 0
    mouse_y = 0
    #Main window:
    window = Tk()
    #Workspace and Canvas:
    wrkspace =  Frame(window, bg="blue",width=640,height=480)
    canvas = Canvas(wrkspace,bg="white",width=640,height=480)
    control_panel = Frame(wrkspace,bg="white",width=32,relief=SUNKEN,bd=5)

出于某种原因,当我运行root程序时告诉我root.py control_panel的第10行尚未定义,但我运行了定义它的函数。我在这里做错了什么?

1 个答案:

答案 0 :(得分:0)

您需要了解python中的范围。你在start_vars函数中所做的一切对于程序的其余部分都是无用的。 control_panel仅存在于该函数的主体中。功能完成后,您没有control_panel

虽然这是一个糟糕的编程,但您可以尝试这样做:

def start_vars():
    #Starting variables:
    line_startx = 0
    line_starty = 0
    line_endx = 0
    line_endy = 0
    mouse_x = 0
    mouse_y = 0
    #Main window:
    window = Tk()
    #Workspace and Canvas:
    wrkspace =  Frame(window, bg="blue",width=640,height=480)
    canvas = Canvas(wrkspace,bg="white",width=640,height=480)
    control_panel = Frame(wrkspace,bg="white",width=32,relief=SUNKEN,bd=5)

    return locals()  # this gives a dictionary containing the local names... you don't have acces to them otherwise.

然后,在你的root.py中执行此操作

my_vars = starting_variables.start_vars()

然后你就可以像roottpy一样获得control_panel

control_panel = my_vars['control_panel']

此后,您可以使用control_panel变量。

另外你可以做这样的黑客

my_vars = starting_variables.start_vars()
globals().update(my_vars)

但这是一个糟糕的建议,你的程序结构很糟糕。

<强> [编辑] 既然你看起来有点困惑,我就会这样做:

class Application:
    # simple variables (ints, strings, etc) can be initiated here
    line_startx = 0
    line_starty = 0
    ...

    # you should have some arguments here, so as not to hard-code everything, so you can reuse this application class. For example, the widths, heights, colors maybe
    def __init__(self):  
        # In the init, put things that take a little more customization, that need parameterization, or that take longer to execute
        self.window = TK()
        self.workspace = Frame(self.window, bg="blue",width=640,height=480)
        self.canvas = Canvas(self.wrkspace, bg="white", width=640, height=480)
        self.control_panel = Frame(self.wrkspace, bg="white", width=32, relief=SUNKEN, bd=5)

这可以在您的starting_variables.py模块中 然后,在root.py中,您可以添加

from tkinter import *
import starting_variables

#Starting variables:
app = starting_variables.Application()  # here's where you'd pass the heights, widths, and the rest of the parameters.

#Tool width control:
tool_width = Scale(app.control_panel,from_=1,to=32)

app.canvas.bind("<Button-1>",app.line_start_xy)

app.control_panel.pack(side=LEFT,fill=Y)
tool_width.pack()
app.wrkspace.pack()
app.canvas.pack()

#Runs window:
app.window.mainloop()

我不确定你是否熟悉面向对象,但这只是我做的方式。你的方式完全可以在C中运行,但是Python没有像你期望的那样拥有全局变量....所有东西都是模块,对象......的一个属性。

为什么我认为编写代码的方式更好,因为触摸其他模块之类的函数(如localsglobals或触摸模块属性在Python中被认为是错误的,因为它是意外的。人们期望函数返回值,对象用于保存属性和方法,类用于描述对象等等...抱歉如果我对理论人太多无聊,只希望解释有所帮助:)