Creating GUI with multiple function buttons - python

I am trying to create a GUI as shown in the attached picture
I wrote the following code which does the job but not the way I need it to.
try:
import Tkinter as tk
import tkMessageBox as mb
except ImportError:
import tkinter as tk
import tkinter.messagebox as mb
root = tk.Tk()
root.geometry("500x300")
tk.Label(root, text="Python First GUI Template", bg="goldenrod", font="bold").pack()
tk.Label(root, text="").pack()
def addFn():
a = int(input('enter first number'))
b = int(input('enter second number'))
mb.showinfo('showinfo', a+b)
def subtractFn():
a = int(input('enter first number'))
b = int(input('enter second number'))
mb.showinfo('showinfo', a - b)
tk.Button(root, text="Add Function", bg="SkyBlue1", command=addFn).pack()
tk.Label(root, text="").pack()
tk.Button(root, text="Subtract Function", bg="SkyBlue1", command=subtractFn).pack()
root.mainloop()
So, I have the following problems:
(1) I am not able to create the design as I want in the attached picture in terms of relative color and relative location of "add" and "subtract" buttons.
(2) When I hit the buttons to activate "add" or "subtract" functions, the inputs are required on the console. I need a pop up with input box and drop down for two numbers I want to add. I am looking for following format for "add" function.
(3) I want to add a "quit" button to close the console when I am done

I'm new to this myself, and unfortunately can't answer most of your questions, but regarding the quit button, I'm thinking you can write a function that calls quit(), just like you would type in order to exit the Python interactive interpreter. Then you link that function to a button just as you did for the first two buttons. This is the same idea with a lambda expression:
from tkinter import *
root =Tk()
root.geometry("500x300")
Button(root,text="QUIT",bg='Red',command=lambda:(quit())).pack(side=BOTTOM)
root.mainloop()
This here is a TKinter frame that gives you a red quit button at the bottom whose sole reason for existence is to quit the frame it's in.
Regarding the layout, I think the pack method requires you to indicate where pack should prefer to put the widget, but doesn't give you much absolute control. Wouldn't grid method allow for better alignment?
Why do your input boxes have to pop out? Why can't they be embedded into the app frame? I would think that would eliminate some difficulty with the issue, no?
Sorry this isn't the most helpful answer ever... but I hope it gives you something to work with until someone more knowledgeable happens by. Cheers.

There are a couple of ways you could do this, the simplest being using .grid() instead of .pack():
from tkinter import *
root = Tk()
title = Label(root, text="Python First GUI Template")
add = Button(root, text="Add")
subtract = Button(root, text="Subtract")
_quit = Button(root, text="Quit")
title.grid(row=0, column=1, padx=5, pady=5)
add.grid(row=1, column=0, padx=5, pady=5)
subtract.grid(row=1, column=2, padx=5, pady=5)
_quit.grid(row=2, column=3, padx=5, pady=5)
root.mainloop()
.grid() allows you to place widgets on the window in a grid fashion, imagine there are cells which you are placing each widget into, whereas .pack() by default will place items stacked on top of eachother unless certain attributes are given values.
You could also use .place() which allows you to place the widgets based on coordinates but this requires a lot more effort make responsive to window size changes or adding new widgets and the like.
On a side note, Stack Overflow is not a free programming resource, we will not write programs for you based on a list of demands. There are plenty of freelance programmers who are happy to do that in exchange for money. I would recommend in future that rather than asking a question about an incredibly well documented library with over 17000 questions on Stack Overflow, a large number of which are about the difference in the three geometry managers you instead find a tutorial or ask a colleague, schoolmate, teacher or friend for help.

Related

How to create a ListBox widget on Customtkinter

I have an app that I would like to restyle using Customtkinter. I originally used Tkinter.
However I have a ListBox widget connected to a scrollbar and when I run the code it says that Customtkinter does not have CTkListBox as attribute, or that ListBox is not defined.
I have tried o look for the issue online and it seems that other people have asked to the person who created he module if he could add ListBox widgets (the link below).
https://github.com/TomSchimansky/CustomTkinter/issues/69
He did answer, but as I am new to coding, I do not feel very confident with the code attached.
I hope someone can help.
Thank you
This is my original code:
# create listbox and put it on screen
list1 = Listbox(window, height=6, width=35)
list1.grid(row=2, column=0, rowspan=6, columnspan=2)
#create scrollbar and put it on screen
sb1 = Scrollbar(window)
sb1.grid(row=2, column=2, rowspan=6)
# apply configure methods to make list and scrollbar work together
list1.configure(yscrollcommand = sb1.set)
sb1.configure(command=list1.yview)
# bind method takes two args: type of event and function.
list1.bind("<<ListboxSelect>>", get_selected_row)

How can I change the colour of a button when clicked at runtime? [duplicate]

This question already has answers here:
List of All Tkinter Events
(3 answers)
Closed 2 years ago.
button1=Button(root,text="A1",width=8).grid(row=0,column=0)
button2=Button(root,text="A2",width=8).grid(row=0,column=1)
label1=Label(root,text=" ",padx=20).grid(row=0,column=2)
button22=Button(root,text="A3",width=8).grid(row=0,column=3,sticky='E')
button23=Button(root,text="A4",width=8).grid(row=0,column=4,sticky='E')
I'm trying to make seat arrangement system for a school project. I have an issue: how can I change the colour of the button once it is clicked? I want to change the colour of the booked and available seats once I click on that button.
If you just wish to change the color of a button when clicked, you need to use the .config() method on that button widget.
for example, if a button is defined like
aButton = tk.Button(root, text='change my color').pack()
then to change the color (or pretty much everything related to that widget like text, command or whatever) call the method
aButton.configure(bg='#f0f', fg='#fff') # change to your required colors, bg is background, fg is foreground.
OR .config() can be also be used (these 2 methods do exactly the same)
aButton.config(bg='#f0f', fg='#fff')
Now how will you know when a button is clicked or not. The simplest and intuitive way is to define functions and connect (or bind) them to buttons. Now how you wanna do that is totally up to the user's preferences. Some prefer to create separate different functions for all buttons, some only like to create one.
For your case though, as you don't need to do anything additional than changing colors then single function is enough.
Important In the example code below, I have used lambda functions, a special type of functions, which don't need to be defined separately. That however, by no means, is necessary
Working example for you
from tkinter import * # I don't recommend using global import. better use "import tkinter as tk"
root = Tk()
button1=Button(root,text="A1",width=8, command=lambda: button1.config(bg='#f00'))
button1.grid(row=0,column=0)
button2=Button(root,text="A2",width=8, command=lambda: button2.config(bg='#f00'))
button2.grid(row=0,column=1)
Label(root,text=" ",padx=20).grid(row=0,column=2)
button22=Button(root,text="A3",width=8, command=lambda: button22.config(bg='#f00'))
button22.grid(row=0,column=3,sticky='E')
button23=Button(root,text="A4",width=8, command=lambda: button23.config(bg='#f00'))
button23.grid(row=0,column=4,sticky='E')
root.mainloop()
Using functions
from tkinter import * # I don't recommend using global import. better use "import tkinter as tk"
def changeColor(btn):
# Use your own highlight background argument here instead of bg
btn.configure(bg='#f00')
root = Tk()
button1=Button(root,text="A1",width=8, command=lambda: changeColor(button1))
button1.grid(row=0,column=0)
button2=Button(root,text="A2",width=8, command=lambda: changeColor(button2))
button2.grid(row=0,column=1)
Label(root,text=" ",padx=20).grid(row=0,column=2)
button22=Button(root,text="A3",width=8, command=lambda: changeColor(button22))
button22.grid(row=0,column=3,sticky='E')
button23=Button(root,text="A4",width=8, command=lambda: changeColor(button23))
button23.grid(row=0,column=4,sticky='E')
root.mainloop()

Python - is there any way to expand the resolution ratio for existing Tkinter Tk() and Toplevel() widget? (zooming-in)

I just made an app using python and tkinter widgets.
There are Labels, Frames, Buttons, etc in the Tk and Toplevel widgets.
However, it includes thousands of codes and its really annoying to resize every widgets when I support multiple resolutions.
Is there any way to expand the resolution ratio for existing Tkinter Tk() and Toplevel() widget and their child widgets? (zooming-in)
If not, what would be the best approach to support multiple resolutions of a python app with the same ratio?
Any help would be much appreciated, sorry for bad English.
Yes, this is possible however it depends on the geometry manager you have used in your program.
For the .pack() method (which is arguably the simplest geometry method for "intelligent" GUI designs) you can use a range of attributes on when you declare .pack() on the widget. These attributes include (but are not limited to) fill, expand, anchor, padx, pady, etc.
The below shows an example of a set of three buttons which will automatically expand to fit the window if it changes or is initialised to a different size than was used during development.
from tkinter import *
root = Tk()
btn1 = Button(root, text="btn1")
btn2 = Button(root, text="btn2")
btn3 = Button(root, text="btn3")
btn1.pack(fill="both", expand=True)
btn2.pack(fill="both", expand=True)
btn3.pack(fill="both", expand=True)
root.mainloop()
For the .grid() method you will need to make use of the functions Grid.columnconfigure() and Grid.rowconfigure. Both of these have the attribute weight which determines which rows and columns should be given priority for assignment of extra space if more becomes available in the window. Setting all rows and columns to have a weight of 1 means they will all be given space equally. You will also need to use the sticky attribute when declaring .grid() on the widgets.
The below shows an example of a set of three buttons which will automatically expand to fit the window if it changes or is initialised to a different size than was used during development.
from tkinter import *
root = Tk()
for column in range(3):
Grid.columnconfigure(root, column, weight=1)
for row in range(1):
Grid.rowconfigure(root, row, weight=1)
btn1 = Button(root, text="btn1")
btn2 = Button(root, text="btn2")
btn3 = Button(root, text="btn3")
btn1.grid(column=0, row=0, sticky=N+S+E+W)
btn2.grid(column=1, row=0, sticky=N+S+E+W)
btn3.grid(column=2, row=0, sticky=N+S+E+W)
root.mainloop()
Using .place() would be a lot more difficult, you would need to have a function setup which would trigger on every window resize event which would calculate the size that the buttons need to expand to.
This would look something like the below:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.button = Button(self.root, text="Button")
self.button.place(relx=0.5, rely=0.5, anchor="center")
self.root.bind("<Configure>", self.resize)
def resize(self, *args):
self.button.configure(width=self.root.winfo_width(), height=self.root.winfo_height())
root = Tk()
App(root)
root.mainloop()
Subjectively speaking, .pack() tends to be easier, however this all comes down to how much effort you're willing to put in to implement this with your current program.
Can't comment so I add a short tip to the detailed Ethan answer. You can design most of the GUIs in tkinter with either pack, grid or a combination of both (by placing frames on a window with one of them, and using either grid or pack inside of each frame, to "place" the widgets). You can tune the configurations for proper location and size when the window resizes. Keep placer use for special cases (like overlaying some widget on the top of others)

Multiple tkinter forms?

I have a GUI that I created with python and tkinter.
My code looks something like:
from Tkinter import *
from PIL import Image, ImageTk
master = Tk()
def f1():
print "Change to form A"
def f2():
print "Change to form B"
title = Label(text="Swithing Menus or Forms")
title.grid(row=0, column=1)
blank = Label(text="\n")
blank.grid(row=1, column=1)
b = Button(master, text="Submenu A", command=f1)
b.grid(row=2, column=1)
b2 = Button(master, text="Submenu B", command=f2)
b2.grid(row=2, column=2)
mainloop()
Buttons in the GUI allow me to call functions on click.
I know it is possible to make components inactive, but is it possible to pull up another form upon clicking a button?
Make all components disappear and bring up new ones?
personally to do this I would build each form inside a frame, that way to change forms would be as simple as:
(using pack)
frame1.pack_forget()
frame2.pack()
(using grid)
frame1.grid_forget()
frame2.grid()
and if it was to be a one way thing (ie you cannot reload the first form)
then you can call:
frame.destroy()
James
Ok, firstly James has given a good answer but i'd like to add a couple things:
You can use grid.remove() this will remember where a widget was etc. so you can .grid() it again and get it back with the same specs. This is probably slightly better than pack/grid.forget() as they 'forget' about the widget.
Also to answer the lower part of the question, yes you can bring up new forms, you can create more or different widgets, more windows and even another module can be called within a function.
I think this has answered your question, but if there's anything more just ask.

tkinter puts WAY too much space between checkbuttons

I can't figure out how to get tkinter to put checkbuttons and radiobuttons closer together. Even specifying pady=0 anyplace it seems valid has no effect. The vertical distance between the buttons is unnaturally large, ugly, and just wastes space. In order to make a set of buttons appear as a group separate from other controls requires that I add extra space elsewhere, which just gets out of control.
Here's a working example I extracted:
from Tkinter import *
def rbtest(frame):
group = LabelFrame( frame, text="Target", padx=0, pady=0)
btnVal = StringVar(frame,' ')
for b in ( "option1", "another option", "Someth Else", "go away"):
rb=Radiobutton( group, text=b, value=b, variable=btnVal)
rb.pack( anchor=W, pady=2)
boardname = StringVar()
Label( group, text="Name").pack( anchor=W)
Entry( group, text=boardname).pack()
group.pack( side=LEFT, fill=Y, padx=0, pady=0)
tk = Tk()
rbtest(tk)
tk.mainloop()
[Well, I can't post an image showing what it produces because I don't have enough reputation, so sorry about that... I tried.]
Edit: I'm using Python 2.6.6 and Windows 7.
Considering how closely together it packs other elements, I'm surprised this is normal behavior, but all the examples I've found on the web look similar...
I ran your code on a Mac and on a windows box, and in both cases it looked about right to me. If you want them literally as close as possible, set the borderwidth to zero and the pady option to zero.
To eek out another two pixels between each button, set the highlightthickness to zero, though that affects the user experience when they are using keyboard traversal.
It looks pretty normal to me:
If it really needs to be made super-compact, there are ways of doing so, but I suspect your system is rendering the window differently.

Categories

Resources