我有一个看似基本的问题,但我不确定如何解决它。
我正在制作一个让用户在画布上画线的程序。我之前将整个代码放在一个文件中,但由于我要添加许多新工具,因此将所有函数隔离到单独的文件中似乎是明智的决定。 但是这样做会导致问题。抱歉有很多代码可以解决。这是我的代码:
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行尚未定义,但我运行了定义它的函数。我在这里做错了什么?
答案 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没有像你期望的那样拥有全局变量....所有东西都是模块,对象......的一个属性。
为什么我认为编写代码的方式更好,因为触摸其他模块之类的函数(如locals
,globals
或触摸模块属性在Python中被认为是错误的,因为它是意外的。人们期望函数返回值,对象用于保存属性和方法,类用于描述对象等等...抱歉如果我对理论人太多无聊,只希望解释有所帮助:)