【问题标题】:error with tkinter python always recive error but no correct conditionstkinter python的错误总是收到错误但没有正确的条件
【发布时间】:2019-01-23 20:02:36
【问题描述】:

为什么这段代码会失败

我试图在按下设置按钮时召唤一个允许用户更改前景和背景颜色的窗口

我得到了单选按钮,但每次我提交颜色时都会收到一个错误,即使它们的值不是 0

我该如何解决这个问题?为什么会这样?

from tkinter import *
import os
from tkinter import messagebox as mgb
import tkinter.ttk as tk2

global colour_1, colour_2
colour_1 = "pink"
colour_2 = "purple" #background

def sayclick() :
    btn.configure(text = "saying")
    text = txt.get()
    os.system("""PowerShell -Command "Add-Type –AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('""" + text + """ ');" """)
    btn.configure(text = "say")

def colourmenu():
    window = Tk()

    window.title("colour menu")

    selected = IntVar()
    selected2 = IntVar()

    rad11 = tk2.Radiobutton(window,text='blue  ', value=1, variable=selected)# set 1

    rad21 = tk2.Radiobutton(window,text='green', value=2, variable=selected)#

    rad31 = tk2.Radiobutton(window,text='red   ', value=3, variable=selected)#

    rad41 = tk2.Radiobutton(window,text='black', value=4, variable=selected)#

    rad12 = tk2.Radiobutton(window,text='blue ', value=1, variable=selected2)

    rad22 = tk2.Radiobutton(window,text='green', value=2, variable=selected2)

    rad32 = tk2.Radiobutton(window,text='red  ', value=3, variable=selected2)

    rad42 = tk2.Radiobutton(window,text='black', value=4, variable=selected2)

    def submitbut():
       if selected.get() == 0 :
          mgb.showinfo("error", "error: invalid colour choise")
       elif selected2.get() == 0 :
          mgb.showinfo("error", "error: invalid colour choise")
       else :
          for n in range(1,3):
             if n == 1 :
                val = selected.get()
                rep = 1
             else :
                val = selected2.get()
                rep = 2
             if val == 1:
                colour = "blue"
             elif val == 2 :
                colour = "green"
             elif val == 3 :
                colour = "red"
             else :
                colour = "black"
             if rep == 1 :
                bg = colour
             else :
                fg = colour



    submit = Button(window, text="submit", command=submitbut)

    txt1 = Label(window, text = "background")
    txt1.grid(column = 0, row = 0)

    txt2 = Label(window, text = "forground")
    txt2.grid(column = 1, row = 0)
    rad11.grid(column=0, row=1)#set 1

    rad21.grid(column=0, row=2)#

    rad31.grid(column=0, row=3)#

    rad41.grid(column=0, row=4)#

    rad12.grid(column=1, row=1)

    rad22.grid(column=1, row=2)

    rad32.grid(column=1, row=3)

    rad42.grid(column=1, row=4)

    submit.grid(column=0, row=5)

    window.mainloop()


root = Tk()
root.geometry("170x120")
root.title("tts entry box")
root.configure(background = colour_2)

lab = Label(root, text = "enter text and than press\n\"say\" to say the text", font = ("Arial Bold", 10), fg = colour_2, bg = colour_1)
lab.grid(column = 0, row = 0)

btn = Button(root, text = "   say.   ", font = ("Arial", 8), bg = colour_1, fg = colour_2, command = sayclick)
btn.grid(column = 0, row = 3)

btn2 = Button(root, text = "settings", font = ("Arial", 8), bg = colour_1, fg = colour_2, command = colourmenu)
btn2.grid(column = 0, row = 4)

txt = Entry(root, width = 10, bg = colour_1, fg = colour_2)
txt.grid(column = 0, row = 2)

root.mainloop()

【问题讨论】:

  • 我应该使用另一种输入方法
  • 你遇到了什么错误?
  • 我注意到,如果我删除从 root = Tk()root.mainloop() 的所有内容并将其替换为 colourmenu(),那么 selected.get()selected2.get() 将返回正确的值。也许与此有关?例如,我不确定您是否应该多次致电mainloop
  • @Kevin 您可以在mainloop 中执行mainloop — 这通常不是一个好主意,但不会导致这里出现问题。您甚至可以创建多个独立的根实例,在一个根上调用 mainloop 确实意味着另一个根及其所有后代在完成之前都没有响应。 (这曾经是在 Classic Mac、Win16 和 Motif 中伪造模态对话框的一种 hacky 但偶尔有用的方法,但它在大多数现代系统中没有用……但无论如何,OP 并没有注意到这个问题。)
  • 为什么人们总是对我投反对票?

标签: python windows user-interface tkinter radio-button


【解决方案1】:

问题是您的程序中有两个独立的Tk 对象。这几乎总是一个坏主意,而 原因 这是一个坏主意,这意味着任何依赖于“默认 Tk 对象”的代码都可能做错事。 p>

尤其是当你这样做时:

selected = IntVar()

…您正在创建一个 IntVar,它是您创建的第一个 Tk 的一部分。1,2 但是 Radiobutton 小部件附加到一个不同 em>Tk。因此,它们无法读取这些变量(这就是为什么您从所有处于不确定状态的单选按钮开始),它们也无法写入它们。3

如果你想创建一个新的顶级窗口,你不需要创建一个全新的 Tk 环境,只需使用一个Toplevel 小部件:

def colormenu():
    window = Toplevel()
    # the rest of your code can be the same

然后,IntVars 最终成为与window 相同的Tk 的一部分。


当我们这样做时,您真的想在另一个 mainloop 中添加一个 mainloop 吗?这是合法的,但我不认为这是你想要的。在submit.grid 之后从colormenu 返回并让主mainloop 循环几乎肯定会更好。 (如果你试图让colormenu 成为一个模式对话框,它会阻止与主窗口的交互,这不是这样做的方法。)


1。您可以在创建IntVar 时显式指定父级,就像为小部件所做的那样。例如,selected = IntVar(window) 将使这个问题消失。但是这里有一个单独的Tk 会有额外的问题,所以最好不要一个就一次性解决所有问题。

2。如果您需要拥有多个Tk 实例,并且需要知道变量、小部件等附加到哪个实例,您可以查看它的_root 属性。例如,selected._root is window._root 会告诉您它们是否属于同一 Tk 的一部分——在这种情况下,您编写的代码为 False,但下一段中的更改为 True。

3。如果您很好奇为什么这没有给您一个有用且易于调试的错误,您必须了解 tkinter 的实际工作原理。 Tkinter 是 Tk 库的包装器,用一种完全独立的脚本语言 Tcl 编写。每个Tk 根实例都有自己完全独立的Tcl 解释器,有自己独立的全局变量。因此,您的selected = IntVar() 正在您的第一个 Tcl 解释器中创建一个名为PY_VAR0 的 Tcl 全局变量。然后,您的variable=selected 告诉 Tcl 在您的第二个 Tcl 解释器中存储对全局变量 PY_VAR0 的更改。因此,只要有变化,Tcl 就会在第二个解释器中写入全局变量PY_VAR0,这是完全合法的,但完全没用,因为您的selected 在第一个解释器中查找PY_VAR0

【讨论】:

    猜你喜欢
    • 2020-05-07
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2016-05-20
    • 2022-01-23
    • 1970-01-01
    • 2013-01-29
    相关资源
    最近更新 更多