简体   繁体   English

Tkinter 应用程序在执行后没有立即响应

[英]Tkinter app does not respond immediately after execution

tryin to learn python right now.现在尝试学习 python。 Starting to build some gui's with tkinter.开始使用 tkinter 构建一些 gui。 Right now I got the problem that immediately after I run my app, the program does not respond.现在我遇到的问题是,在我运行我的应用程序后,程序没有响应。 No errors seen in the ide.在 ide 中未发现任何错误。 I think the problem is somewhere in my function roll .我认为问题出在我的 function中。 Deleting the command paramater from the rollbtn allows the gui to run.rollbtn中删除命令参数允许 gui 运行。 Any ideas would be appreciated.任何想法,将不胜感激。

With kind regards DachsAdmin亲切的问候 DachsAdmin

# Author: DachsAdmin
# ------------------------------------------------------------------------packages and variables
from tkinter import *
import random

app = Tk()
app.title("Dice Tool")
app.geometry("600x400+700+300")
app.resizable(width=False, height=False)
#app.iconbitmap("C:\PYTHON\Code\img\dice.ico")


# ----------------------------------------------------------------------------------------------------functions
def roll(dice_type, dice_quantity):
    dice_result = []
    print(dice_type)
    dice_type = dice_type()[1:]
    dice_type = int(dice_type)
    counter = 0

    while counter != dice_quantity:
        dice_result.append(random.randrange(1, dice_type))
        counter = counter + 1

    for x in dice_result:
        resultbox.insert(END, x + "\n")
    resultbox.pack()


# ----------------------------------------------------------------------------------------------------coreWindow
frameleft = Frame(app, bg="grey")
frameleft.place(x=10, y=10, width=380, height=380)

resultbox = Text(frameleft)
resultbox.configure(state="disabled")
resultbox.place(x=10, y=10, width=360, height=360)

frameright = Frame(app, bg="grey")
frameright.place(x=410, y=10, width=180, height=380)

variable = StringVar(app)
variable.set("W6")

diceoptionmenu = OptionMenu(frameright, variable, "W3","W4","W6","W8","W10","W12")
diceoptionmenu.place(x=10, y=10, width=75, height=30)

dicequantity = Spinbox(frameright, from_=1, to=99)
dicequantity.place(x=95, y=10, width=75, height=30)

rollbtn = Button(frameright, text="Roll!", width=100, bg="white", command=roll(variable.get, dicequantity.get))
rollbtn.place(x=40, y=300, width=100, height=30)

exitbtn = Button(frameright, text="Exit", width=100, bg="white", command=app.quit)
exitbtn.place(x=40, y=340, width=100, height=30)

app.mainloop()

Your code got stuck in the while loop.您的代码卡在了while循环中。 This happened because you tried to compare an integer to string .发生这种情况是因为您尝试将integerstring进行比较。 Also, instead of forwarding a function ( dice_quantity.get, dict_type.get ), I change it for you.另外,我没有转发 function ( dice_quantity.get, dict_type.get ),而是为您更改它。 I forward the function address and then I called it inside the roll function.我转发了 function 地址,然后我在roll function 中调用了它。

import random
from tkinter import Tk, Frame, Text, StringVar, OptionMenu, Spinbox, Button, END

app = Tk()
app.title("Dice Tool")
app.geometry("600x400+700+300")
app.resizable(width=False, height=False)

def roll(dice_type, dice_quantity):
    dice_result = []
    dice_type = int(dice_type.get()[1:])
    counter = 0

    while counter != int(dice_quantity.get()):
        dice_result.append(random.randrange(1, dice_type))
        counter += 1

    for x in dice_result:
        resultbox.insert(END, x, "\n")
    resultbox.pack()


frameleft = Frame(app, bg="grey")
frameleft.place(x=10, y=10, width=380, height=380)

resultbox = Text(frameleft)
resultbox.configure(state="disabled")
resultbox.place(x=10, y=10, width=360, height=360)

frameright = Frame(app, bg="grey")
frameright.place(x=410, y=10, width=180, height=380)

variable = StringVar(app)
variable.set("W6")

diceoptionmenu = OptionMenu(frameright, variable, "W3","W4","W6","W8","W10","W12")
diceoptionmenu.place(x=10, y=10, width=75, height=30)

dicequantity = Spinbox(frameright, from_=1, to=99)
dicequantity.place(x=95, y=10, width=75, height=30)
rollbtn = Button(frameright, text="Roll!", width=100, bg="white", command=roll(variable, dicequantity))
rollbtn.place(x=40, y=300, width=100, height=30)

exitbtn = Button(frameright, text="Exit", width=100, bg="white", command=app.quit)
exitbtn.place(x=40, y=340, width=100, height=30)

app.mainloop()

Do this:做这个:

rollbtn = Button(
  frameright, text="Roll!", width=100, bg="white", 
  command=roll
)

and this:和这个:

def roll():
    dice_type = variable.get()
    dice_quantity = dicequantity.get()

Ok, sorry did not look further.好的,抱歉没有进一步看。 Some changes:一些变化:

def roll():
    dice_type = variable.get()
    dice_type = int(dice_type[1:])
    dice_quantity = int(dicequantity.get())
    
    dice_result = []
    for i in range(dice_quantity):
        dice_result.append(random.randrange(1, dice_type))

    for x in dice_result:
        resultbox.insert(END, str(x) + "\n")

Remove:消除:

resultbox.configure(state="disabled")

Some clarifications (initially wanted to keep it short:):一些澄清(最初想保持简短:):

This was capturing the functions (function addresses) 'get',这是捕获函数(函数地址)'get',
of 'variable' and 'dicequantity': 'variable' 和 'dicequantity' 的:

command=roll(variable.get, dicequantity.get)

Could solve with a lambda expression:可以用 lambda 表达式解决:

command=lambda: roll(variable.get(), dicequantity.get())

For simplicity, just used roll directly + called get() there为简单起见,直接使用 roll + 调用 get()

command=roll
...
def roll():
    ... = variable.get()
    ... = dicequantity.get()

About roll() body: The issues were due to type mismatches:关于 roll() 正文:问题是由于类型不匹配造成的:
mixing int and string, expecting one but getting the other.混合 int 和 string,期待一个但得到另一个。
It's easy to get mixed up in a dynamic language.在动态语言中很容易混淆。
Hint: to see a variable's type (if not using IDEs etc.),提示:查看变量的类型(如果不使用 IDE 等),
try using: print(type(variable)).尝试使用:打印(类型(变量))。

Finally, disabling the Text widget disallows updates to it.最后,禁用 Text 小部件将禁止对其进行更新。
You may want to start it disabled, enable it before updates,您可能希望禁用它,在更新之前启用它,
and disable it again after (to avoid user modifications):并在之后再次禁用它(以避免用户修改):

def  roll(): 
  ...
  resultbox.configure(state="normal")
  for x in dice_result:
        resultbox.insert(END, str(x) + "\n")
  resultbox.configure(state="disabled")

One hint: Run from command line (eg "python3./MyScript.py"),一个提示:从命令行运行(例如“python3./MyScript.py”),
and watch the error messages: they help a lot.并查看错误消息:它们有很大帮助。

There are two main issues causing the problem:导致该问题的主要问题有两个:

  • rollbtn = Button(frameright, text="Roll,", width=100, bg="white". command=roll(variable,get. dicequantity.get))

    roll() function will be executed immediately, not what you expect when the button is clicked. roll() function 将立即执行,而不是单击按钮时的预期。

  • while counter:= dice_quantity: inside roll() function. while counter:= dice_quantity: inside roll() function。 As dice_quantity is a reference of Spinbox.get() , counter != dice_quantity always evaluated as True.由于dice_quantitySpinbox.get()的引用,因此counter != dice_quantity始终评估为 True。 So it is an infinite while loop.所以这是一个无限的while循环。

So to fix it:所以要修复它:

  • Use lambda in command option: command=lambda: roll(variable.get(), dicequantity.get())command选项中使用lambdacommand=lambda: roll(variable.get(), dicequantity.get())

  • update roll() :更新roll()

    def roll(dice_type, dice_quantity):
        print(dice_type, dice_quantity)
        dice_type = int(dice_type[1:])
        resultbox.config(state='normal')
        for i in range(int(dice_quantity)):
            x = random.randrange(1, dice_type)
            resultbox.insert(END, str(x)+'\n')
        resultbox.config(state='disabled')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM