Tkinter Entry() 不从输入中获取数字

Tkinter Entry() don't get numbers from input

我对 Tkinter Entry 有疑问。我是 运行 循环中的程序,创建和销毁两个 class 实例。在初始循环中,一切正常。游戏结束后,我将销毁 Tkinter 实例:

self.frame.destroy()
self.tk.destroy()

然后程序回到主循环:

def main():
  root = Tk()
  data = get_data(root)
  root.mainloop()
  del root
  root = Tk()
  main_window = Main_field(root, data)
  root.mainloop()
  del data, root, main_window
  msg = "Play again?"
  res = messagebox.askyesno("Game Over", message=msg)
  if res:
    del res
    main()
  else:
    quit()

此循环的主要对象是创建新的空 class 实例,作为第一个实例。问题是重新启动后输入框不加载输入数字。当我调用 get() 方法时,我有一个空字符串:

class get_data():
  def __init__(self, tk):
     global mines_var
     mines_var = tkinter.StringVar()
     entry_box_mines = Entry(tk, textvariable=mines_var, width=50)
     entry_box_mines.pack()
     entry_box_mines.insert(0, 0)
     self.width = 0
     self.len_ = 0
     self.mines = 0
     self.tk = tk
     start_game_button = Button(tk, text="Start Game", command=lambda: [self.get_attributes()]).pack()

   def get_attributes(self):
     res = self.validate(len_var.get(), width_var.get(), mines_var.get())
     if res == "OK":
        self.tk.destroy()
     else:
        messagebox.showinfo(message=res)

我哪里出错了?

你的错误是

mines_var = tkinter.StringVar()

mines_var 中删除了之前的 tkinter.StringVar() 并删除了之前的值。

您应该只将值保留在全局变量中,然后再将其放回 StringVar()

您还应该使用父级 - tk - 就像在小部件中一样。

mines_var = tkinter.StringVar(parent, value=global_value)

我的版本有其他改动。

PEP 8-- Style Guide for Python Code

import tkinter as tk  # PEP8: `import *` is not preferred
from tkinter import messagebox

# --- classes ---

class GetDataWindow():  # PEP8: `CamelCaseNames` for classes, and `noun` as name (PL: rzeczownik)

    def __init__(self):

        self.root = tk.Tk()

        # variables

        print('[DEBUG] __init__:', global_len, global_width, global_mines)

        self.len_var   = tk.StringVar(self.root, value=global_len)
        self.width_var = tk.StringVar(self.root, value=global_width)
        self.mines_var = tk.StringVar(self.root, value=global_mines)

        # widgets

        tk.Label(self.root, text='Settings').grid(row=0, column=0, columnspan=2)

        tk.Label(self.root, text='len:').grid(row=1, column=0, sticky='e')
        tk.Entry(self.root, textvariable=self.len_var).grid(row=1, column=1)

        tk.Label(self.root, text='width:').grid(row=2, column=0, sticky='e')
        tk.Entry(self.root, textvariable=self.width_var).grid(row=2, column=1)

        tk.Label(self.root, text='mines:').grid(row=3, column=0, sticky='e')
        tk.Entry(self.root, textvariable=self.mines_var).grid(row=3, column=1)

        tk.Button(self.root, text="Start Game", command=self.get_attributes).grid(row=4, column=0, columnspan=2)

        self.root.mainloop()

    def get_attributes(self):
        global global_len
        global global_width
        global global_mines

        res = self.validate(self.len_var.get(), self.width_var.get(), self.mines_var.get())

        if res == "OK":
            global_len   = self.len_var.get()
            global_width = self.width_var.get()
            global_mines = self.mines_var.get()
            print('[DEBUG] get_attributes:', global_len, global_width, global_mines)
            self.root.destroy()
        else:
            messagebox.showinfo(message=res)

    def validate(self, *values):
        return 'OK'

class MainWindow():

    def __init__(self):
        self.root = tk.Tk()

        tk.Label(self.root, text='Game').grid(row=0, column=0, columnspan=2)

        tk.Label(self.root, text='len:').grid(row=1, column=0, sticky='e')
        tk.Label(self.root, text=global_len).grid(row=1, column=1)

        tk.Label(self.root, text='width:').grid(row=2, column=0, sticky='e')
        tk.Label(self.root, text=global_width).grid(row=2, column=1)

        tk.Label(self.root, text='mines:').grid(row=3, column=0, sticky='e')
        tk.Label(self.root, text=global_mines).grid(row=3, column=1)

        tk.Button(self.root, text="OK", command=self.root.destroy).grid(row=4, column=0, columnspan=2)

        self.root.mainloop()

# --- main ---

# default value at start
global_len   = '0'
global_width = '0'
global_mines = '0'

while True:
    GetDataWindow()
    MainFieldWindow()

    #win = GetDataWindow()
    #del win
    #win = MainWindow()
    #del win

    # create and hide main window before creating message
    root = tk.Tk()
    root.withdraw()

    res = messagebox.askyesno("Game Over", message="Play again?")
    if not res:
       break

    root.destroy()

顺便说一句:

当然可以不用关键字global,比如:

len_  = 0
width = 0
mines = 0

while True:

    win = GetDataWindow(len_, width, mines)

    len_  = win.len_
    width = win.width
    mines = win.mines

    MainWindow(len_, width, mines)

    # ... the rest ...

或更简单:

settings = {
    'len': 0,
    'width': 0,
    'mines': 0,
}

while True:

    GetDataWindow(settings)
    MainWindow(settings)

    # ... the rest ...

但是我跳过了这部分。

我也可以使用 IntVar 而不是 StringVar