【问题标题】:Executing a Button command from another file?从另一个文件执行按钮命令?
【发布时间】:2021-03-19 06:05:41
【问题描述】:

我已经开始在一个 GUI 系统上工作,我需要从一个文件中导入一个函数,以便在按下按钮时在主文件中执行,但每次运行它都会得到:

AttributeError: partially initialized module 'Two' has no attribute 'sum'
  (most likely due to a circular import)

程序应该输入两个值,Value_aValue_b,而被调用的函数sum() 应该将这两个值相加并在新窗口中输出结果。这是我要导入的文件及其函数sum()的示例:

Two.py

from tkinter import *  #Import the tkinter module    
import One #This is the main file, One.py

def sum():
    newWindow = Toplevel(One.Window)
    newWindow.title("Sum")
    a = int(One.Value_a.get())
    b = int(One.Value_b.get())
    c = a+b
    Label(newWindow, text= str(c)).grid(row=1, column=0)

这是主文件的样子:

One.py

from tkinter import *
import Two

Window = Tk()
Window.title("Main Window")

Value_a = Entry(Window, width=15).grid(row=1, column=0)
Value_b = Entry(Window, width=15).grid(row=2, column=0)
my_button = Button(Window, text="Test", command=lambda: Two.sum).grid(row=3, column=0)

Window.mainloop()

运行时,我最终得到了上述错误。

【问题讨论】:

  • Two.py 中导入One 将创建Tk (One.Window) 的另一个实例,而不是在运行Tk (Window) 的实例时使用One.py。您需要将WindowValue_aValue_b 传递给Two.sum(),并且不要在Two.py 中导入One
  • @acw1668:没那么容易。请参阅我发布的答案。

标签: python tkinter tkinter-button


【解决方案1】:

问题是因为您确实有一个通知import。模块One 导入模块Two 导入模块One... 等等。但是建议的简单修复@acw1668 不足以解决问题,因为Two 模块引用的不仅仅是Window 的属性One 模块。我的解决方案将模块One 中的东西传递给模块Two 中的函数需要作为参数(因此Two 模块不需要import 来访问它们)。

问题Tkinter: AttributeError: NoneType object has no attribute 中讨论了您的tkinter 代码的另一个问题,我建议您阅读。

以下是解决所有这些问题的两个模块的更改。

One.py:

from tkinter import *
import Two


Window = Tk()
Window.title("Main Window")

Value_a = Entry(Window, width=15)
Value_a.grid(row=1, column=0)
Value_b = Entry(Window, width=15)
Value_b.grid(row=2, column=0)

my_button = Button(Window, text="Test",
                   command=lambda: Two.sum(Window, Value_a, Value_b))
my_button.grid(row=3, column=0)

Window.mainloop()

Two.py:

from tkinter import *


def sum(Window, Value_a, Value_b):
    newWindow = Toplevel(Window)
    newWindow.title("Sum")
    a = int(Value_a.get())
    b = int(Value_b.get())
    c = a+b
    Label(newWindow, text= str(c)).grid(row=1, column=0)

【讨论】:

  • 我更喜欢使用One.py 中的类并将类的实例传递给Two.sum()
  • @acw1668:当然可以,但将多个参数传递给sum() 会更简单。
  • @acw1668:因为它要简单得多,所以我修改了我的答案以这样做——整个sys.modules 方法太奇怪了……
  • 虽然比较简单,但是如果后面Two.sum()需要引用另一个widget,那么就需要修改函数定义了。你原来的设计(或者我建议使用类实例)不需要改变Two.sum()的定义,只需要改变函数的内容。
  • @martineau:感谢您的解决方案。由于您对代码的调整,该程序可以按我的意愿运行。谢谢。
【解决方案2】:

(这是另一个答案,与我最初在其他答案中的答案非常相似,然后再做一些我觉得更简单的事情。我将其作为单独的答案发布,因为事实证明@987654321 @,所以这样做并不像我最初想象的那么奇怪或那么骇人听闻。)

问题是因为你确实有一个通知import。模块One 导入模块Two 导入模块One... 等等。但是建议的简单修复@acw1668 不足以解决问题,因为Two 模块引用的不仅仅是Window 的属性One 模块。我的解决方案将整个 One 模块作为参数传递给函数(因此Two 模块不需要import 来访问其属性)。

问题Tkinter: AttributeError: NoneType object has no attribute 中讨论了您的tkinter 代码的另一个问题,我建议您阅读。

以下是解决所有这些问题的两个模块的更改。为了避免循环导入,Button 命令现在将调用模块作为参数传递给模块Two 中的sum() 函数。虽然这样做 有点不寻常,但如果你仔细想想,实际上是非常合乎逻辑的(并且希望避免循环导入)。

One.py:

from tkinter import *
import Two

CURRENT_MODULE = __import__(__name__)

Window = Tk()
Window.title("Main Window")

Value_a = Entry(Window, width=15)
Value_a.grid(row=1, column=0)
Value_b = Entry(Window, width=15)
Value_b.grid(row=2, column=0)

my_button = Button(Window, text="Test", command=lambda: Two.sum(CURRENT_MODULE))
my_button.grid(row=3, column=0)

Window.mainloop()

Two.py:

from tkinter import *

def sum(One):
    newWindow = Toplevel(One.Window)
    newWindow.title("Sum")
    a = int(One.Value_a.get())
    b = int(One.Value_b.get())
    c = a+b
    Label(newWindow, text= str(c)).grid(row=1, column=0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多