【问题标题】:Can I keep a tkinter window open while using stored variables?我可以在使用存储变量时保持 tkinter 窗口打开吗?
【发布时间】:2026-01-22 20:15:01
【问题描述】:

在 Jupyter 笔记本中,我使用 tkinter 收集用户输入,以便其他代码可以生成输出文件。我创建了一个提交按钮来存储变量,但我必须在其余代码能够使用它们并运行到输出之前关闭 tkinter 窗口。

我希望能够一直运行到输出文件,然后在不关闭和重新启动的情况下输入新的输入。我怎样才能让 tkinter 窗口一直打开?


from tkinter import *
import datetime
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import pandas as pd

class MyWindow:
    def __init__(self, win):
        self.lbl=Label(win, text="Tool")
        self.lbl1=Label(win, text='ndays')
        self.lbl2=Label(win, text='Date 1')

        self.t1=Entry()
        self.t2=Entry()

        self.lbl.place(x=150, y=10)

        self.lbl1.place(x=50, y=50)
        self.t1.place(x=150, y=50)

        self.lbl2.place(x=50, y=90)
        self.t2.place(x=150, y=90)    
        self.b1=Button(win, text='Submit', command=self.submit)

        self.b2=Button(win, text='Refresh')
        self.b2.bind('<Button-1>', self.refresh)

        self.b1.place(x=150, y=260)
        self.b2.place(x=270, y=260)

    def submit(self):
        global ndays, screen

        ndays=self.t1.get()
        screen=self.t2.get()

    #in case of refresh
    def refresh(self, event):
        self.t1.delete(0, 'end')
        self.t2.delete(0, 'end')

window=Tk()
mywin=MyWindow(window)
window.title("Tool")
window.geometry("400x400+10+10")
window.mainloop()

如果不退出 tkinter 窗口,我将无法访问名称和屏幕日期变量。我希望能够刷新变量并再次将其运行到输出,而无需关闭窗口。

下面的代码是我将运行以创建自定义日历的后续步骤。


screen = datetime.datetime.strptime(screen, '%m/%d/%y').date()

# find the of the number of days backwards.
ndays=int(ndays)
thirty_back = screen + relativedelta(days=-ndays - 1)

delta1 = screen - thirty_back

# Empty lists to loop into
date_list = []  # dates
day_counter_thing = []
day_o_week = []  # real day of week
counter = []  # list for the days used

day_count = -1  # starts at -1 so that screen day can be 0

for i in range(delta1.days):
    day = screen - timedelta(days=i)  # know where to start the tlfb

    date_list.append(day)  # list of dates in the loop
    day_count = day_count + 1  # add a count for each day in the loop
    counter.append(day_count)  # keep a list of all the day counts

    day_o_week.append(day.strftime("%A"))  # add the real day of the week
    name = day.weekday()  # name of day by index of day in week
    day_counter_thing.append(name)  # keep the list
max_day = max(counter)  # gives you reference so that you can swap the counter after screen

# put the values from the loops into a dataframe
df = pd.DataFrame({'Date': date_list, "Day": day_o_week, "Counter": day_counter_thing, "TLFB_Day": counter})

【问题讨论】:

  • 为什么您认为在使用这些值之前需要退出窗口?没有要求您必须这样做。
  • 我正在使用 jupyter,如果我尝试在下面的内核中使用该变量,它只会在侧面显示 * 并且不会运行。
  • 我认为使用 jupyter 是您在问题中遗漏的一个重要细节。
  • 我的错!不过,我现在也尝试过使用 IDLE。当我在 .py 文件中通过 IDLE 运行此代码时,我也遇到了同样的问题,即需要在变量可以在其他地方使用之前退出窗口。下一步是什么?
  • 我还是不明白为什么你不能在破坏窗口之前使用它。您的 submit 函数可以在窗口被销毁之前访问变量。事实上,它无法在销毁后访问变量。

标签: python tkinter calendar global-variables jupyter


【解决方案1】:

一旦在窗口上单击提交,此代码就会将数据框打印到终端中。只要窗口没有关闭,主循环就会运行,并且无法运行任何其他代码。

from tkinter import *
import datetime
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import pandas as pd

class MyWindow:
    def __init__(self, win):
        self.lbl=Label(win, text="Tool")
        self.lbl1=Label(win, text='ndays')
        self.lbl2=Label(win, text='Date 1')

        self.t1=Entry()
        self.t2=Entry()

        self.lbl.place(x=150, y=10)

        self.lbl1.place(x=50, y=50)
        self.t1.place(x=150, y=50)

        self.lbl2.place(x=50, y=90)
        self.t2.place(x=150, y=90)    
        self.b1=Button(win, text='Submit', command=self.submit)

        self.b2=Button(win, text='Refresh')
        self.b2.bind('<Button-1>', self.refresh)

        self.b1.place(x=150, y=260)
        self.b2.place(x=270, y=260)

    def calendar( self, screen, ndays ):
        # find the of the number of days backwards.

        screen = datetime.datetime.strptime(screen, '%m/%d/%y').date()
        ndays=int(ndays)
        thirty_back = screen + relativedelta(days=-ndays - 1)

        delta1 = screen - thirty_back

        # Empty lists to loop into
        date_list = []  # dates
        day_counter_thing = []
        day_o_week = []  # real day of week
        counter = []  # list for the days used

        day_count = -1  # starts at -1 so that screen day can be 0

        for i in range(delta1.days):
            day = screen - timedelta(days=i)  # know where to start the tlfb

            date_list.append(day)  # list of dates in the loop
            day_count = day_count + 1  # add a count for each day in the loop
            counter.append(day_count)  # keep a list of all the day counts

            day_o_week.append(day.strftime("%A"))  # add the real day of the week
            name = day.weekday()  # name of day by index of day in week
            day_counter_thing.append(name)  # keep the list
        max_day = max(counter)  # gives you reference so that you can swap the counter after screen

        # put the values from the loops into a dataframe
        return pd.DataFrame({'Date': date_list, "Day": day_o_week, "Counter": day_counter_thing, "TLFB_Day": counter})

    def submit(self):
        print( self.calendar( self.t2.get(), self.t1.get()) )

    #in case of refresh
    def refresh(self, event):
        self.t1.delete(0, 'end')
        self.t2.delete(0, 'end')

window=Tk()
mywin=MyWindow(window)
window.title("Tool")
window.geometry("400x400+10+10")
window.mainloop()

另一种方法是在窗口本身中显示结果,而不是在文本对象或标签系列中打印结果。

【讨论】:

  • 好的,我从中学到了很多关于 tkinter 的知识。谢谢你的开始,但我想我需要在前面澄清一下,我的程序后面有更多代码来格式化和清理数据框,然后将其导出到 xlsx 文件。对我来说,它看起来可以在 def 提交按钮中完成,但我犹豫不决,因为我希望有更多清晰的代码块为我的不同功能(GUI、日期数据框创建、格式化、导出)提供服务以后自己参考。我对此还是很陌生——线程在某种程度上是否合适?
  • 我猜你最好的解决方案是在submit方法中处理数据。 Ii 可以在mywindow 类之外编写用于数据框创建、格式化和写入excel 的函数或对象集,并在其中调用它们。这使您可以将活动的代码分开,但从一个点调用。要记住的要点是 GUI 界面对事件(如按钮点击)采取行动并作出反应。让它们也在后台工作要困难得多,而且通常是不必要的。
  • 我将它全部移到了提交方法下,它可以工作。谢谢你们的cmets!