【问题标题】:Tkinter Entry() don't get numbers from inputTkinter Entry() 不从输入中获取数字
【发布时间】:2021-08-29 20:46:56
【问题描述】:

我对 Tkinter Entry 有疑问。我在循环中运行程序,创建和销毁两个类实例。在初始循环中,一切正常。游戏结束后,我正在销毁 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()

这个循环的主要对象是创建新的空类实例作为第一个实例。问题是重新启动输入框后不加载输入数字。当我调用 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)

我在哪里犯错了?

【问题讨论】:

  • 如果您可以将此代码缩减为 minimal reproducible example,将会有所帮助。例如,我们是否真的需要三个条目小部件,或者是否可以只用一个来说明问题。
  • 另外,请确保您知道如何使用类。大多数时候你不应该在类中使用全局变量。
  • @BryanOakley 我把它们都加了,因为我不确定哪一个是这里的问题
  • 所以,您刚刚证明您只需要一个条目,因此您可以简化示例。
  • 您似乎也缺乏基础知识,这意味着您应该首先学习这些,例如:start_game_button = Button(tk, text="Start Game", command=lambda: [self.get_attributes()]).pack() 可以而且实际上应该(仍然只是建议)简化为:Button(tk, text="Start Game", command=self.get_attributes).pack()

标签: python tkinter tkinter-entry


【解决方案1】:

你的错误是

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

【讨论】:

    猜你喜欢
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    相关资源
    最近更新 更多