How to create a tkinter toggle button?

30,096

Solution 1

The background and fg are set only in the if-clause. You need to set them also in the else clause:

def onNightMode(self):
    if index:
        self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')

    else:
        self.text.config(font=('courier', 12, 'normal'))

    index = not index

i.e.,

else:
    self.text.config(font=('courier', 12, 'normal'), background='green', fg='black')

Solution 2

You can import tkinter library (Use capital letter for python 2.7):

import Tkinter 

Create tkinter objects...

root = tk.Tk()

...and tkinter button

toggle_btn = tk.Button(text="Toggle", width=12, relief="raised")
toggle_btn.pack(pady=5)
root.mainloop()

Now create a new command button called "toggle" in order to create the effect of "toggle" when you press playing on the relief property (sunken or raised) :

def toggle():

    if toggle_btn.config('relief')[-1] == 'sunken':
        toggle_btn.config(relief="raised")
    else:
        toggle_btn.config(relief="sunken")

At the end apply this behaviour on your button:

toggle_btn = tk.Button(text="Toggle", width=12, relief="raised", command=toggle)

Solution 3

Here's a code snippet that will help you with the toggle button animation if you would like to. You only need to add the functions that you want to execute when clicking of course, that's up to you.

'''
    import tkinter as tk

    # --- functions ---

    def move(steps=10, distance=0.1):
        if steps > 0:
            # get current position
            relx = float(frame.place_info()['relx'])

            # set new position
            frame.place_configure(relx=relx+distance)

            # repeate it after 10ms
            root.after(10, move, steps-1, distance)

    def toggle(event):
        if button["text"] == "Yes":
            move(25, 0.02)  # 50*0.02 = 1
            button["text"] = "No"
            print("Clicked on yes")
        elif button["text"] == "No":
            move(25, -0.02)
            button["text"] = "Yes"
            print("Clicked on no")


    # --- main --

    root = tk.Tk()

    frame = tk.Frame(root, background='red')
    frame.place(relx=0, rely=0, relwidth=0.5, relheight=1)

    # to center label and button
    #frame.grid_columnconfigure(0, weight=1)
    #frame.grid_rowconfigure(0, weight=1)
    #frame.grid_rowconfigure(3, weight=1)




    button = tk.Button(frame, text='Yes',width=5,height=1)
    button.place(relx=0.25,rely=0.5,relwidth=0.5, relheight=0.1)
    button.bind("<Button-1>",toggle)


    root.mainloop()
Share:
30,096
Potato_head
Author by

Potato_head

Updated on April 14, 2020

Comments

  • Potato_head
    Potato_head about 4 years

    I've been working on a text editor using Tkinter in Python 2.7. A feature that I'm trying to implement is the Night Mode, where the user can toggle between a black background and a light one, that switches from light to dark with a click of the toggle button.

    from Tkinter import *
    
    from tkSimpleDialog import askstring
    
    from tkFileDialog   import asksaveasfilename
    from tkFileDialog import askopenfilename
    
    from tkMessageBox import askokcancel
    
    Window = Tk() 
    Window.title("TekstEDIT")
    index = 0
    
    class Editor(ScrolledText):
    
        Button(frm, text='Night-Mode',  command=self.onNightMode).pack(side=LEFT)
    
        def onNightMode(self):
        if index:
            self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')
    
        else:
            self.text.config(font=('courier', 12, 'normal'))
    
        index = not index   
    

    However, on running the code, it is always in the night mode and the toggle doesn't work. Help. Source Code: http://ideone.com/IVJuxX

  • unutbu
    unutbu about 10 years
    The UnboundLocalError is due to the assignment to index which makes it a local variable by default when you really want it to refer to the global variable. The quick fix is to add the statement global index inside the function. But a better fix would be to avoid using a mutable global and instead make index an instance attribute, self.index.
  • Russell Smith
    Russell Smith over 9 years
    Your code isn't formatted properly. Also, code-only answers aren't usually as good with code plus an explanation. Can you explain a bit why your code solves the problem?
  • Albe
    Albe over 9 years
    I do not know English well but I know very well python: What do you mean formatted propely? For Python 2.7 works fine !!!! Copy it and paste into a text file and save it as .py! Test before giving a bad comments!!!
  • Russell Smith
    Russell Smith over 9 years
    At the time I wrote the comment, the body of toggle was indented the same as the def statement and you could not copy and paste it. Look at the history of the edits and you'll see your original version was edited by someone else to fix the indentation.
  • Albe
    Albe over 9 years
    was the first time and I was wrong with the editor of stack overflow for the code but I assure you that I was in good faith and that the code has always worked. Next time send me a private message and correct it instead of a negative comment and judgment !!!
  • Russell Smith
    Russell Smith over 9 years
    It wasn't a negative comment, I was merely stating a fact. I didn't want to edit the answer because I thought you might not know how to format it properly (since it was originally wrong), and by making you fix it you would learn how to format your answers. I'm sorry if you were offended. My only intention was to help you write a better answer.
  • Albe
    Albe over 9 years
    Sorry but the tone of your response seemed very aggressive. Anyway thanks for the help, I think I learned to write properly with this editor; I rewrote a new answer with code comments.
  • Russell Smith
    Russell Smith over 9 years
    It would have been better if you edited this answer, than to provide another answer with the same information.