Выполнение команды кнопки из другого файла?

Я начал работать над системой графического интерфейса, где мне нужно импортировать функцию из одного файла, которая будет выполняться в основном файле при нажатии кнопки, но каждый раз, когда я запускаю ее, я получаю:

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

Программа должна вводить два значения, Value_a и Value_b, а вызываемая функция должна складывать их и выводить результат в новом окне. Вот пример файла, который я хочу импортировать, и его функции. 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()

Когда это запускается, я получаю указанную выше ошибку.

2 ответа

Решение

Проблема в том, что у вас действительно есть циркуляр. Модуль импортирует модуль, который импортирует модуль ... и т. Д. Однако предложенного простого исправления @acw1668 недостаточно, чтобы исправить ситуацию, потому что модуль ссылается не только на Windowатрибут модуля. Мое решение передает вещи в модуль One функция в модуле нуждается в аргументах (так что Two модулю не нужно import чтобы получить к ним доступ).

Другая проблема с вашим кодом tkinter обсуждается в вопросе Tkinter: AttributeError: объект NoneType не имеет атрибута , который я предлагаю вам прочитать.

Ниже приведены изменения в обоих ваших модулях, которые устраняют все эти проблемы.

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)

(Вот еще один ответ, который очень похож на то, что я изначально получил в другом ответе, прежде чем сделать что-то, что, как мне казалось, было проще. Я отправляю его как отдельный ответ, потому что оказывается, что идея модуля, получающего ссылку на себя, была в течение очень долгого времени , так что это не так уж странно или хакерски, как я первоначально думал.)

Проблема в том, что у вас действительно есть циркуляр. Модуль импортирует модуль, который импортирует модуль ... и т. Д. Однако предложенного простого исправления @acw1668 недостаточно, чтобы исправить ситуацию, потому что модуль ссылается не только на Windowатрибут модуля. Мое решение проходит целиком One модуль к функции в качестве аргумента (так что модулю не нужно import чтобы получить доступ к его атрибутам).

Другая проблема с вашим кодом tkinter обсуждается в вопросе Tkinter: AttributeError: объект NoneType не имеет атрибута , который я предлагаю вам прочитать.

Ниже приведены изменения в обоих ваших модулях, которые устраняют все эти проблемы. Чтобы избежать циклического импорта, команда Button теперь передает вызывающий модуль в качестве аргумента в sum() функция в модуле Two. Хотя делать что - то вроде этого является несколько необычным, на самом деле является очень логичным , если вы думаете об этом (и хотите , чтобы избежать круговой import`).

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)
Другие вопросы по тегам