Python Forum

Full Version: tkinter button help
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi I am new to python and tkinter and am trying to create a simple button that when clicked starts my function which will randomly run through a list of pre determined words.
I have got the button to run the code but instead of printing inside the gui it prints in the console.

Below is what I have so far any help would be appreciated.

TIA

import tkinter as tk
import os
import random
import time

words = ["roll left", "pull", "duck", "roll right", "slip"]


root = tk.Tk()

def addApp():

        for choice in random.sample(words, len(words)):
                time.sleep(2)
                print(choice)

def closewindow():

        exit()



canvas = tk.Canvas(root,height=500, width=500,bg="#263D42")
canvas.pack()

frame = tk.Frame(root, bg="green")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1)

openfile = tk.Button(root, text="Open File",padx=10,
                     pady=5, fg="white", bg="#263D42", command= addApp)
openfile.pack()


closefile = tk.Button(root, text="Close Window",padx=10,
                     pady=5, fg="white", bg="#263D42", command=closewindow)

closefile.pack()


root.mainloop()
Don't use time.sleep in GUI code it blocks the GUI from being updated.
see [Tkinter] How to deal with code that blocks the mainloop, freezing the gui
Thanks so is that why nothing is showing on the GUI or do I still need to add a Label once the time issue is sorted?
You have the button pointed to each function (addApp), but there is not procedure for it to display the "choice" in the GUI. You need to add a place for it and then insert the "choice" into it to allow it to be displayed.

Clarity is key when asking for help. :)
That is why the gui is locking up, you will need a label to display one row of data or a list box to display multiple rows depending on what you want.
(May-26-2020, 07:35 PM)DT2000 Wrote: [ -> ]You have the button pointed to each function (addApp), but there is not procedure for it to display the "choice" in the GUI. You need to add a place for it and then insert the "choice" into it to allow it to be displayed.

Clarity is key when asking for help. :)

ok thank you so do I add a label to the function (addApp) or to the button or would it go somewhere else sorry I know this is probably the easiest thing to do but i'm trying to learn as I go.
I'm curious why you are using sleep? Is your intent for the program to constantly pick and display a random word ('choice'), and display it and then in 2 second change and display another random word until the program is terminated?
Or are you looking for it to display a random word ('choice') , and then another random word is the button is pressed again such as this?
import tkinter as tk
from tkinter import Text
from tkinter import END
import os
import random
import time

words = ["roll left", "pull", "duck", "roll right", "slip"]
root = tk.Tk()

def addApp():

        for choice in random.sample(words, len(words)):
                tbox.delete(1.0,END)
                tbox.insert('1.0',choice)

def closewindow():

        root.destroy()

canvas = tk.Canvas(root,height=545, width=500,bg="#263D42")
canvas.pack()

tbox = Text(root, font = ('arial',12), width=54, height=27, fg='white', bg='green', bd=0)
tbox.place(x=8,y=8)

openfile = tk.Button(root, text="Open File", width = 20, height = 2, fg="white", bg="#263D42", command= addApp)
openfile.place(x=100,y=503)

closefile = tk.Button(root, text="Close Window", width = 20, height = 2, fg="white", bg="#263D42", command=closewindow)

closefile.place(x=270,y=503)

root.mainloop()
(May-26-2020, 07:39 PM)Yoriz Wrote: [ -> ]That is why the gui is locking up, you will need a label to display one row of data or a list box to display multiple rows depending on what you want.
so I think I have added the label correctly now just need to get around the time.sleep freezing the app, I've read the link You attached but i'm afraid it makes no sense to me :/ any one able to dumb it down for me.

import tkinter as tk
import os
import random
import time

words = ["roll left", "pull", "duck", "roll right", "slip"]


root = tk.Tk()
root.title("Drill Training")

def addApp():

        for choice in random.sample(words, len(words)):
                time.sleep(2)
                print(choice)
        myLabel = tk.Label(frame, text=choice)
        myLabel.pack()


def closewindow():

        exit()



canvas = tk.Canvas(root,height=500, width=500,bg="purple")
canvas.pack()

frame = tk.Frame(root, bg="green")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1)



Start = tk.Button(root, text="Start",padx=10,
                     pady=5, fg="white", bg="#263D42", command= addApp)
Start.pack()


closefile = tk.Button(root, text="Close Window",padx=10,
                     pady=5, fg="white", bg="#263D42", command=closewindow)

closefile.pack()


root.mainloop()
(May-26-2020, 07:58 PM)DT2000 Wrote: [ -> ]I'm curious why you are using sleep? Is your intent for the program to constantly pick and display a random word ('choice'), and display it and then in 2 second change and display another random word until the program is terminated?
Or are you looking for it to display a random word ('choice') , and then another random word is the button is pressed again such as this?
import tkinter as tk
from tkinter import Text
from tkinter import END
import os
import random
import time

words = ["roll left", "pull", "duck", "roll right", "slip"]
root = tk.Tk()

def addApp():

        for choice in random.sample(words, len(words)):
                tbox.delete(1.0,END)
                tbox.insert('1.0',choice)

def closewindow():

        root.destroy()

canvas = tk.Canvas(root,height=545, width=500,bg="#263D42")
canvas.pack()

tbox = Text(root, font = ('arial',12), width=54, height=27, fg='white', bg='green', bd=0)
tbox.place(x=8,y=8)

openfile = tk.Button(root, text="Open File", width = 20, height = 2, fg="white", bg="#263D42", command= addApp)
openfile.place(x=100,y=503)

closefile = tk.Button(root, text="Close Window", width = 20, height = 2, fg="white", bg="#263D42", command=closewindow)

closefile.place(x=270,y=503)

root.mainloop()

I am looking to click start and have the programme show a new random word every 30 secs until the full list has been completed I asked for help with the timer and the time.sleep was what was advised at the time but they didn't know I would be using Tkinter so I'm guessing that's why.
It can't be dumbed down your just out of your depth at the moment, you need to spend some more time in the paddling pool before jumping in the deep end Wink
import functools
import random
import time
import tkinter as tk
from concurrent import futures

thread_pool_executor = futures.ThreadPoolExecutor(max_workers=1)


def tk_after(target):

    @functools.wraps(target)
    def wrapper(self, *args, **kwargs):
        args = (self,) + args
        self.after(0, target, *args, **kwargs)

    return wrapper


def submit_to_pool_executor(executor):
    '''Decorates a method to be sumbited to the passed in executor'''
    def decorator(target):

        @functools.wraps(target)
        def wrapper(*args, **kwargs):
            result = executor.submit(target, *args, **kwargs)
            result.add_done_callback(executor_done_call_back)
            return result

        return wrapper

    return decorator


def executor_done_call_back(future):
    exception = future.exception()
    if exception:
        raise exception


class MainFrame(tk.Frame):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.label = tk.Label(self, text='not running')
        self.label.pack()
        self.button = tk.Button(
            self, text='blocking task', command=self.on_button)
        self.button.pack(pady=15)
        self.pack()

    def on_button(self):
        print('Button clicked')
        self.blocking_code()

    @tk_after
    def set_label_text(self, text=''):
        self.label['text'] = text

    @tk_after
    def set_button_state(self, enabled=True):
        state = 'normal'
        if not enabled:
            state = 'disabled'
        self.button['state'] = state

    @submit_to_pool_executor(thread_pool_executor)
    def blocking_code(self):
        self.set_button_state(False)
        self.set_label_text('running')
        time.sleep(0.5)

        words = ["roll left", "pull", "duck", "roll right", "slip"]

        for choice in random.sample(words, len(words)):
            self.set_label_text(choice)
            time.sleep(0.5)

        self.set_label_text('not running')
        self.set_button_state(True)


if __name__ == '__main__':
    app = tk.Tk()
    main_frame = MainFrame()
    app.mainloop()
Pages: 1 2