Question

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

Was it helpful?

Solution 2

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')

OTHER TIPS

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)

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()

Albe's answer is good but it has some bad coding practices.

Following the same steps:

Import Tkinter as tk 
top = tk.TK()

Define your function here and make it work for any button, not hard coded to the specific button you might use.

def toggle(button: tk.Button):
    if button.config('relief')[-1] == 'sunken':
        button.config(relief="raised")
    else:
        button.config(relief="sunken")

Then create and pack all the toggle buttons you want.

toggleButton = tk.Button(text="Toggle", width=12, relief="sunken",
command =lambda:toggle(toggleButton))
toggleButton.pack(pady=5)
top.mainloop()

This is better for two reasons. Creating the button object twice is redundant and will lead to buggy code. Hard coding the button to a specific toggle function is unscalable. This solution makes the code reusable and simple to add to. For example, replace that last block with:

for _ in range(4):
    b = tk.Button(text="Toggle", width=12, relief="sunken")
    b['command']= lambda a=b:toggle(a)
    b.pack(pady=5)

And now you get 4 toggling buttons without any additional functions or copy/paste

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top