【问题标题】:How do I use a Tkinter Button for two states?如何在两种状态下使用 Tkinter 按钮?
【发布时间】:2018-09-29 06:01:24
【问题描述】:

我有以下代码,当单击 Tkinter 按钮时会导致颜色/文本发生变化。第二次单击按钮时,我想恢复为原始颜色/文本。

from Tkinter import *

window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')

def clicked_rf1():
    btn_rf1.configure(text="Stop")
    lbl_rf1.configure(text="  ON  ", bg="green")

btn_rf1 = Button(window, text="Start", command=clicked_rf1)
btn_rf1.grid(column=1, row=1)
lbl_rf1 = Label(window, text="  OFF ", bg="red")
lbl_rf1.grid(column=2, row=1)

window.mainloop()

我想要一些更像开关的东西,但我想要一个按钮的外观。

感激不尽。

【问题讨论】:

  • 你想要切换按钮还是标签?
  • 文字/颜色变化只是一个例子。实际上,我想在第一次点击时运行一堆代码 A,在第二次点击时运行一堆代码 B。所以,我猜是按钮。
  • 在这种情况下,我认为 Novel 的回答应该为按钮和标签提供一个很好的例子。

标签: python button tkinter


【解决方案1】:

您将需要一个 if 块来选择要做什么。您可以创建另一个标志变量来跟踪状态,或者只使用当前的标签或按钮文本:

from Tkinter import *

window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')

def clicked_rf1():
    if btn_rf1['text'] == "Start":
        btn_rf1.configure(text="Stop")
        lbl_rf1.configure(text="  ON  ", bg="green")
    else:
        btn_rf1.configure(text="Start")
        lbl_rf1.configure(text="  OFF ", bg="red")

btn_rf1 = Button(window, text="Start", command=clicked_rf1)
btn_rf1.grid(column=1, row=1)
lbl_rf1 = Label(window, text="  OFF ", bg="red")
lbl_rf1.grid(column=2, row=1)

window.mainloop()

这将是创建自定义 Button 子类的理想场所,因此您可以在程序中包含许多此类:

from Tkinter import *

window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')

class Christina(Frame):
    def __init__(self, master=None, **kwargs):
        Frame.__init__(self, master, **kwargs)

        self.btn = Button(self, text="Start", command=self.clicked)
        self.btn.grid(column=0, row=0)
        self.lbl = Label(self, text="  OFF ", bg="red")
        self.lbl.grid(column=1, row=0)

    def clicked(self):
        if self.btn['text'] == "Start":
            self.btn.configure(text="Stop")
            self.lbl.configure(text="  ON  ", bg="green")
        else:
            self.btn.configure(text="Start")
            self.lbl.configure(text="  OFF ", bg="red")

btn1 = Christina(window)
btn1.grid()
btn2 = Christina(window)
btn2.grid()
btn3 = Christina(window)
btn3.grid()

window.mainloop()

【讨论】:

  • 你让我相信它:D。想了一件事。您可能想要为切换功能添加全局变量。我知道 python 最终会检查全局,即使它没有提供,但我认为它最适合 OP 和其他人学习。
  • 或者使用dict将当前状态映射到下一个状态。
  • 太棒了!谢谢大家!
  • 为什么你的Button继承自Frame
  • @ReblochonMasque 因为 OP 想要一个 Button 和一个 Label 组合,所以我用一个 Frame 来保存这两个。
【解决方案2】:

如果您想要切换,可以使用不带指示器的复选按钮。它具有选中和取消选中状态下的颜色选项,您可以将值和标签绑定在一起,以便在切换按钮时标签会发生变化。

像任何按钮一样,您可以将命令绑定到它。该命令可以检查变量的值以确定它应该执行“on”功能还是“off”功能。

这是一个简单的例子:

import Tkinter as tk

def toggle():
    if var.get() == "ON":
        print("turning on...")
    else:
        print("turning off...")

root = tk.Tk()
var = tk.StringVar()
toggle = tk.Checkbutton(root, onvalue="ON", offvalue="OFF", width=4,
                        indicatoron=False, 
                        variable=var, textvariable=var,
                        selectcolor="green", background="red",
                        command=toggle)

var.set("OFF")
toggle.pack()

root.mainloop()

【讨论】:

    【解决方案3】:

    另一种方法可能是将“代码堆”放入不同的函数中,将它们收集到一个迭代器中,然后从该迭代器中获取next 函数并执行它:

    def bunchofcode():
        print("foo")
    
    def somethingelse():
        print("bar")
    
    whattodo = iter([bunchofcode, somethingelse])
    
    def clicked_rf1():
        try:
            next(whattodo)()
        except StopIteration:
            print("nothing to do")
    

    或者对于循环行为:

    from itertools import cycle
    whattodo = cycle([bunchofcode, somethingelse])
    

    对于双状态切换按钮,您还可以使用dict 将当前状态映射到下一个状态。您也可以使用按钮的relief 来标记状态。

    def clicked_rf1():
        transition = {"raised": "sunken", "sunken": "raised"}
        btn_rf1["relief"] = transition[btn_rf1["relief"]]
    

    【讨论】:

      猜你喜欢
      • 2021-03-20
      • 2018-07-27
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-06
      • 2015-02-22
      相关资源
      最近更新 更多