How do I make a button console using Tkinter? - python-3.x

I have got a script wiht nine diferent options in a text menu. I would like to change the menu for a GUI using tkinter.
The menu has nine options which are a bucle if, elif... esle from 1 to 9. The last one is the 'exit' one.
How do I transform the menu if, elif, elif....else in a window with nine buttons each one for a different option and run the same script ?
I am trying the following code:
from tkinter import*
ventana = Tk()
variable = ''
def opcion1():
global variable
variable = '1'def opcion2 ():
global variable
variable = '2'
root = Tk()
boton1 = Button(ventana, text='OPCION1',command=opcion1)
boton1.pack()
boton2 = Button(ventana, text='OPCION2',command=opcion2)
boton2.pack()
botonSalir = Button(ventana, text='EXIT',command=quit)
botonSalir.pack()
root.mainloop()
How can I do that?

Hopefully this helps!
from Tkinter import *
root = Tk()
def f1():
print('f1')
def f2():
print('f2')
def f3():
print('f3')
MODES = [("Option1", f1, '1'), ("Option2", f2, '2'), ("Option3", f3, '3')]
v = StringVar()
v.set("L") # initialize
for text, function, mode in MODES:
b = Radiobutton(root, text=text, indicatoron=0, variable=v, command=function, value=mode)
b.pack(anchor=W)
root.mainloop()

Related

Output text in multiple text-boxes rather than single..tkinter python

import tkinter as tk
win = tk.Tk()
win.title('New App')
win.geometry('800x800')
def passgen():
num = str(inp.get())
# text field for output
disp = tk.Text(master=win, height=4, width=80, )
disp.pack()
disp.insert(tk.END, num)
lab = tk.Label(text='First Label')
lab.pack()
inp = tk.Entry()
inp.pack()
btn = tk.Button(text='Submit', command=passgen)
btn.pack()
win.mainloop()
Above is my simple tkinter code but when I run it I get the output in multiple boxes. All I want is each time I use the submit button the output should be in one single box rather than multiple boxes. Is there any way to do it?I am using python 3.
Screenshot
the issue is in the way that the passgen() method works where it creates a new tk.Text() object. to fix this you want to add to the same Text object which means creating it outside of the function and then using the global object from the function:
...
def passgen():
global disp
num = str(inp.get())
disp.insert(tk.END, num)
disp = tk.Text(master=win, height=4, width=80, )
disp.pack()
...

How to make a label cycle through preset words or phrases when a button is pressed in tkinter

So I'm trying to make it cycle through each letter of the alphabet when the button is clicked.
I have tried the method i am showing now.
I have also tried many others and i couldn't get anything to work.
If you do have a solution please try keep it simple i am kinda new too this.
from tkinter import *
win = Tk()
win.title('ab')
a = 0
def changetext():
a = a+1
if a == 1:
lbl.config(text='b')
def changetext():
if a == 2:
lbl.config(text='c')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()```
In python, variables inside functions are local, which means that if you define a variable a = 0 outside the function, then do a = 1 in the function, the a equals 1 inside the function but it still equals 0 outside. If you want to change the value of a outside the function from inside the function, you need to declare a as a global variable (see code below).
import tkinter as tk # avoid import * to because it leads to naming conflicts
win = tk.Tk()
win.title('ab')
i = 0
letters = "abcdefghijklmnopqrstuvwxyz"
def changetext():
global i # change value of i outside function as well
i += 1
i %= 26 # cycle through the alphabet
lbl.configure(text=letters[i])
lbl = tk.Label(win, text='a')
lbl.grid(row=1, column=1)
btn = tk.Button(win,text='u', command=changetext)
btn.grid(row=2, column=1)
win.mainloop()
You can use itertools.cycle to create a cycle list and then use next() function to get the next item in the cycle list:
import tkinter as tk
from itertools import cycle
words = cycle(['hello', 'world', 'python', 'is', 'awesome'])
root = tk.Tk()
lbl = tk.Label(root, text=next(words), width=20)
lbl.pack()
tk.Button(root, text='Next', command=lambda: lbl.config(text=next(words))).pack()
root.mainloop()
I actually used the first method and adapted it by making the variable global because then it will update it for all the functions making my first method work
from tkinter import *
win = Tk()
win.title('ab')
i = 0
def changetext():
global i
i = i + 1
if i == 1:
lbl.config(text='word 2')
if i == 2:
lbl.config(text='word 1 ')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()

How to use a single button to take input from multiple Tkinter entries?

This program is being written in Tkinter. I am writing a program that will have multiple entry boxes where the user will input certain parameters. I want there to be a single button that saves all the entries from all the entry boxes to be used later by another part of my program. At this moment, the entry boxes and the button are done but the button does not do anything. How could I go about making the button read and save all the entries? Thanks!
You just need to get the data in the Entries and store them as variables, inside functions and globalize those variables. After that just call all the functions in a separate function. And then give this function as a command to the button.
import tkinter as tk
root = tk.Tk()
e_1 = tk.Entry(root)
e_1.pack()
e_2 = tk.Entry(root)
e_2.pack()
e_3 = tk.Entry(root)
e_3.pack()
var_1 = 0
var_2 = 0
var_3 = 0
def func_1():
global var_1
var_1 = e_1.get()
def func_2():
global var_2
var_2 = e_2.get()
def func_3():
global var_3
var_3 = e_3.get()
def store_all():
func_1()
func_2()
func_3()
print(var_1)
print(var_2)
print(var_3)
b = tk.Button(root, text="get", width=10, command=store_all)
b.pack()
root.mainloop()
I have used print() inside the function to confirm to you that the values are stored successfully. You can just remove those.
Here is an example of a program that reads contents of one Entry and prints it:
https://effbot.org/tkinterbook/entry.htm#patterns
Below you can find code in python 3:
from tkinter import *
master = Tk()
e = Entry(master)
e.pack()
e.focus_set()
def callback():
print(e.get())
b = Button(master, text="get", width=10, command=callback)
b.pack()
mainloop()
Just add more Entry widgets and read them all in the callback method.

Python 3 Radio button controlling label text

I am in the process of learning Python3 and more of a necessity, the TkInter GUI side. I was working my way through a book by James Kelly, when I encountered this problem. All his examples made a new window with just label/canvas/check box etc which seemed to work OK.
But as I wanted to experiment in a more real world scenario I put most things on one window. This where I encountered my problem. I can not get the radio button in the frame to alter the wording of a label in the parent window.
Complete code is:-
#! /usr/bin/python3
from tkinter import *
def win_pos(WL,WH,xo=0,yo=0) :
# Screen size & position procedure
# Screen size
SW = home.winfo_screenwidth()
SH = home.winfo_screenheight()
# 1/2 screen size
sw=SW/2
sh=SH/2
# 1/2 window size
wl=WL/2
wh=WH/2
# Window position
WPx=sw-wl+xo
WPy=sh-wh+yo
# Resulting string
screen_geometry=str(WL) + "x" + str(WH) + "+" + str(int(WPx)) + "+" \ + str(int(WPy))
return screen_geometry
# Create a window
home=Tk()
home.title("Radio buttons test")
# Set the main window
home.geometry(win_pos(600,150))
lab1=Label(home)
lab1.grid(row=1,column=1)
fraym1=LabelFrame(home, bd=5, bg="red",relief=SUNKEN, text="Label frame text")
fraym1.grid(row=2,column=2)
laybl1=Label(fraym1, text="This is laybl1")
laybl1.grid(row=0, column=3)
var1=IntVar()
R1=Radiobutton(fraym1, text="Apple", variable=var1, value=1)
R1.grid(row=1, column=1)
R2=Radiobutton(fraym1, text="Asus", variable=var1, value=2)
R2.grid(row=1, column=2)
R3=Radiobutton(fraym1, text="HP", variable=var1, value=3)
R3.grid(row=1, column=3)
R4=Radiobutton(fraym1, text="Lenovo", variable=var1, value=4)
R4.grid(row=1, column=4)
R5=Radiobutton(fraym1, text="Toshiba", variable=var1, value=5)
R5.grid(row=1, column=5)
# Create function used later
def sel(var) :
selection="Manufacturer: "
if var.get() > 0 :
selection=selection + str(var.get())
lab1.config(text=selection)
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
mainloop()
I realise that there is room for improvement using classes/functions but I need to get this resolved in my head before I move on. As it can be hopefully seen, I'm not a complete novice to programming, but this is doing my head in.
Can a solution, and reasoning behind the solution, be given?
You can modify your label's text by assigning the same variable class object, var1 as its textvariable option as well but since lab1's text is slightly different, try removing:
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
and modify sel to:
def sel(*args) :
selection="Manufacturer: "
selection=selection + str(var1.get())
lab1.config(text=selection)
and then call var1.trace("w", sel) somewhere before mainloop as in:
...
var1.trace("w", sel)
mainloop()
Also for a simple example:
import tkinter as tk
root = tk.Tk()
manufacturers = ["man1", "man2", "man3", "man4", "man5"]
lbl = tk.Label(root, text="Please select a manufacturer.")
lbl.pack()
# create an empty dictionary to fill with Radiobutton widgets
man_select = dict()
# create a variable class to be manipulated by radiobuttons
man_var = tk.StringVar(value="type_default_value_here_if_wanted")
# fill radiobutton dictionary with keys from manufacturers list with Radiobutton
# values assigned to corresponding manufacturer name
for man in manufacturers:
man_select[man] = tk.Radiobutton(root, text=man, variable=man_var, value=man)
#display
man_select[man].pack()
def lbl_update(*args):
selection="Manufacturer: "
selection=selection + man_var.get()
lbl['text'] = selection
#run lbl_update function every time man_var's value changes
man_var.trace('w', lbl_update)
root.mainloop()
Example with label's identical to that of radiobutton's value:
import tkinter as tk
root = tk.Tk()
# radiobutton group will the button selected with the value=1
num = tk.IntVar(value=1)
lbl = tk.Label(root, textvariable=num)
zero = tk.Radiobutton(root, text="Zero", variable=num, value=0)
one = tk.Radiobutton(root, text="One", variable=num, value=1)
#display
lbl.pack()
zero.pack()
one.pack()
root.mainloop()

tkinter, button returns variable

I am trying to make a GUI text based adventure game in python. I want to be able to take text from a textinput box and store it as string variable.
I have 2 problems:
Making the python wait for the submit button to be pressed, before
processing the input and updating the game.
Getting the text variable out of the command, I would like to not
use global if possible.
Here is some of my code to better understand:
root = tk.Tk()
root.geometry('800x600+100+100')
root.title("my game")
textbox = tk.StringVar()
textboxentry = tk.Entry(root, textvariable=textbox, bd=5, width = "40", font=("times", 20))
textboxentry.pack(in_=bgImageLabel, side = "bottom")
def getInput():
textboxInput = textbox.get() #gets entry
lengthEntry = len(textbox.get())
textboxentry.delete(0,lengthEntry) #removes entry from widget
return textboxInput # I would like this return to work
submit = tk.Button(root, text ="Submit", command = (textboxInput = getInput()))
##I want the command function to use command = getInput and store the return on getInput as textboxInput. This will update the wait_variable down below, and give the inputs(textboxInput) a string to work with.
submit.pack(in_=bgImageLabel, side = "bottom")
while game == True:
root.update_idletasks()
root.update()
submit.wait_variable(textboxentry)
## I need it to wait before proceeding to this next line because i need the textboxInput from the entry widget.
actionInput, extraInput, texts = inputs(textboxInput)
Currently I can't figure a way to use command = (textboxInput = getInput), using lambda or anything else. I just want to store the return which comes off of the Entry as a string variable that can be used by the main function.
All help is appreciated!
Below code processes entry widget's text when Submit button is pressed.
import tkinter as tk
root = tk.Tk()
aVarOutside = 'asd'
def btn_cmd(obj):
#use global variable
global aVarOutside
#print its unmodified value
print("aVarOutside: " + aVarOutside)
#modify it with what's written in Entry widget
aVarOutside = obj.get()
#modify lblTextVar, which is essentially modifying Label's text as lblTextVar is its textvariable
lblTextVar.set(obj.get())
#print what's inside Entry
print("Entry: " + obj.get())
txt = tk.Entry(root)
txt.pack()
lblTextVar = tk.StringVar()
lbl = tk.Label(root, textvariable=lblTextVar)
lbl.pack()
btn = tk.Button(text="Submit", command=lambda obj = txt : btn_cmd(obj))
btn.pack()
root.mainloop()
When the button is pressed:
Value of a global variable, aVarOutside is printed.
Value of aVarOutside is modified to the value of Entry box's
(txt's) content.
Value of a textvariable used by a label (lbl) is modified. Which
means that the text of lbl is updated and can be seen on the GUI.
Finally Entry box, txt's content is printed.
I think you should use inputs() inside getInputs() and then button doesn't have to return any variables - and then you can use root.mainloop() instead of while loop.
import tkinter as tk
# --- functions ---
def inputs(text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input():
global action_input, extra_input, texts
text = textbox.get()
if text: # check if text is not empty
textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
action_input, extra_input, texts = inputs(text)
# --- main ---
root = tk.Tk()
textbox = tk.StringVar()
textbox_entry = tk.Entry(root, textvariable=textbox)
textbox_entry.pack()
submit = tk.Button(root, text="Submit", command=get_input)
submit.pack()
root.mainloop()
BTW: you could better organize code
all functions before main part (root = tk.Tk())
PEP8 suggests to use lower_case_names for functions and variables (instead of CamelCaseNames)
global is not prefered method but I think it is better solution than yours.
If you don't need global then you can use classes with self.
import tkinter as tk
# --- classes ---
class Game:
def __init__(self):
self.root = tk.Tk()
self.textbox = tk.StringVar()
self.textbox_entry = tk.Entry(self.root, textvariable=self.textbox)
self.textbox_entry.pack()
self.submit = tk.Button(self.root, text="Submit", command=self.get_input)
self.submit.pack()
def run(self):
self.root.mainloop()
def inputs(self, text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input(self):
text = self.textbox.get()
if text: # check if text is not empty
self.textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
self.action_input, self.extra_input, self.texts = self.inputs(text)
# --- functions ---
# empty
# --- main ---
app = Game()
app.run()

Resources