【问题标题】:Tkinter: Passing StringVar from one window to anotherTkinter:将StringVar从一个窗口传递到另一个窗口
【发布时间】:2018-08-25 19:12:22
【问题描述】:

所以我有两个 python 文件,每个文件都包含两个 tkinter 窗口。一个是Root Tk 实例,另一个是Toplevel Tk 实例。一旦打开 Toplevel 实例,我试图从 Root 实例中获取 Toplevel 实例中的两个字符串变量,称为 self.taskhours 和 Root 实例中的 self.taskminutes。我相当确定我没有正确地将 Root 实例传递给 Toplevel 实例。有人可以帮忙吗?

这是第一个文件,名为“timex.py”:

import tkinter as tk
from tkinter import ttk

class TimeX(tk.Frame):
    def __init__(self,master):
        # INIT WINDOW
        import datetime
        tk.Frame.__init__(self,master=master)
        self.pack()

        self.master.title("TimeX") # Add title to main window
        # TOP MENU #
        self.master.menu = tk.Menu(master)
        # TOP MENU # FILE MENU #
        self.master.filemenu = tk.Menu(self.master.menu)
        self.master.menu.add_cascade(label="File",menu=self.master.filemenu)
        self.master.menu.add_command(label="New File",command=self.new_file)

        self.frames = [
            tk.Frame(self), # TASKITEM
            tk.Frame(self), # TIME INPUT
            tk.Frame(self), # INIT BUTTON
            # tk.Frame(self), # SHOWS 00:00:00 until INIT BUTTON PRESSED

        ]
        # START FRAME 0
        frame = self.frames[0]
        self.taskitem = tk.StringVar(self,"TaskItem") # Entry
        # self.taskplan = tk.StringVar(self) # Listbox
        # self.taskdesc = tk.StringVar(self) # Textbox
        frame.entries = [
            tk.Entry(frame,textvariable=self.taskitem),
        ]
        for i,entry in enumerate(frame.entries):
            entry.grid(row=0,column=i)
        frame = self.frames[1]
        # THE REAL
        # self.taskhours = tk.StringVar(self,"Hours")
        # self.taskminutes = tk.StringVar(self,"Minutes")
        # THE FOO
        self.taskhours = tk.StringVar(self,"1")
        self.taskminutes = tk.StringVar(self,"30")
        frame.labels = [
            tk.Label(frame,text="Estimated Duration")
        ]
        frame.entries = [
            tk.Entry(frame,textvariable=self.taskhours),
            tk.Entry(frame,textvariable=self.taskminutes)
        ]
        # frame.menubuttons = [
        #   tk.Menubutton(frame,text="Hour(s)",textvariable=self.taskhours),
        #   tk.Menubutton(frame,text="Minute(s)",textvariable=self.taskminutes)
        # ]
        # self.tasktime = [int(self.taskhours.get()),int(self.taskminutes.get())]
        # frame.items = frame.labels + frame.menubuttons
        frame.items = frame.labels + frame.entries
        for i,item in enumerate(frame.items):
            item.grid(row=0,column=i)
        frame = self.frames[2]
        frame.buttons = [
            tk.Button(frame,text="Start Task",command=self.start_timer).pack()
        ]
        # for i,button in enumerate(frame.buttons):
        #   button.grid(row=0,column=i)

        for frame in self.frames:
            for child in frame.winfo_children():
                child.grid_configure(padx=5,pady=5)
            frame.pack(padx=10,pady=10,anchor="w")

    def start_timer(self):
        import timer
        timer.run()

    def new_file(self):
        # import new_file
        # new_file.run()
        pass

def run():
    root = tk.Tk()
    app = TimeX(root)
    app.mainloop()

run()

这是第二个文件,名为“timer.py”:

import tkinter as tk
# import time
from datetime import datetime
# timeVar : MM
class Window(tk.Frame):
    def __init__(self,master):
        tk.Frame.__init__(self,master=master)
        self.pack()
        self.master.title("Timer")
        self.time = tk.StringVar(self,"00:00:00")
        self.label = tk.Label(self,text=self.time.get()).pack()
        self.totalseconds = self.tasktime_to_total_seconds(self.taskhours.get(),self.taskminutes.get())

        self.countdown(totalseconds)

    def tasktime_to_total_seconds(taskhours,taskminutes):
        taskhours = int(taskhours)
        taskminutes = int(taskminutes)
        totalseconds = taskhours * 3600 + taskminutes * 60
        return totalseconds

    def countdown(totalseconds):
        if totalseconds == 1:
            self.label.configure(text="On to the next!")
            tk.Button(self,text="Close Window",command=self.quit)
        totalseconds = totalseconds - 1
        stdtime = total_seconds_to_standard(totalseconds)
        self.time.set(stdtime)
        self.label.configure(text=self.time)
        self.master.after(1000,self.countdown)

    def total_seconds_to_standard(total_seconds):
        seconds = total_seconds
        hoursec = seconds - seconds % 3600
        hours = int(hoursec/3600)
        seconds = seconds - hoursec

        minutesec = seconds - seconds % 60
        minutes = int(minutesec/60)
        seconds = seconds - minutesec

        standard = str(hours) + ":" + str(minutes) + ":" + str(seconds)

        return standard

def run():
    top = tk.Toplevel()
    window = Window(top)

当我通过按“开始任务”按钮打开第二个窗口时遇到的错误是,

"AttributeError: 'Window' 对象没有属性 'taskhours'"

这显然是将根对象正确传递给顶层对象的问题,但我不确定确切的实现!提前感谢您的帮助!

为了让它工作,我只是要将变量存储在一个文件中,但这似乎不是最好的方法,所以我想我会看看 interwebz 对此事的看法。

【问题讨论】:

  • 嗯,Window 没有 有一个taskhours 属性,或者一个taskminutes,但是在它的__init__ 方法中你同时调用了self.taskhours.get()self.taskminutes.get()

标签: python user-interface tkinter tk


【解决方案1】:

如果你有两个 python 文件,你需要将它们作为模块导入以使用它们 函数和对象。

在此处查看循环依赖导入:
https://stackabuse.com/python-circular-imports/

【讨论】: