This is my current Python code:
from tkinter import *
import glob
import os
from PIL import Image, ImageTk
import tkinter as tk
root = tk.Tk()
root.title("SIGN OFF")
root.minsize(840, 800)
# Add a grid
mainframe = tk.Frame(root)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
mainframe.pack(pady=100, padx=100)
# Create a Tkinter variable
tkvar = tk.StringVar(root)
directory = "C:/Users/eduards/Desktop/work/data/to-do"
choices = glob.glob(os.path.join(directory, "*.jpg"))
tkvar.set('...To Sign Off...') # set the default option
popupMenu = tk.OptionMenu(mainframe, tkvar, *choices)
tk.Label(mainframe, text="Choose your sign off here:").grid(row=1, column=1)
popupMenu.grid(row=2, column=1)
label2 = tk.Label(mainframe, image=None)
label2.grid(row=4, column=0)
# On change dropdown callback.
def change_dropdown(*args):
""" Updates label2 image. """
imgpath = tkvar.get()
img = Image.open(imgpath)
img = img.resize((240,250))
photo = ImageTk.PhotoImage(img)
label2.image = photo
label2.configure(image=photo)
tk.Button(mainframe, text="Open", command=change_dropdown).grid(row=3, column=1)
var1 = IntVar()
Checkbutton(mainframe, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(column = 2, row=1, sticky=W)
var2 = IntVar()
Checkbutton(mainframe, text="May Contain Statement.", variable=var2).grid(column = 2, row=2, sticky=W)
var3 = IntVar()
Checkbutton(mainframe, text="Cocoa Content (%).", variable=var3).grid(column = 2, row=3, sticky=W)
var4 = IntVar()
Checkbutton(mainframe, text="Vegetable fat in addition to Cocoa butter", variable=var4).grid(column = 2, row=4, sticky=W)
var5 = IntVar()
Checkbutton(mainframe, text="Instructions for Use.", variable=var5).grid(column = 2, row=5, sticky=W)
var6 = IntVar()
Checkbutton(mainframe, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6).grid(column = 2, row=6, sticky=W)
var7 = IntVar()
Checkbutton(mainframe, text="Nutritional Information Visible", variable=var7).grid(column = 2, row=7, sticky=W)
var8 = IntVar()
Checkbutton(mainframe, text="Storage Conditions", variable=var8).grid(column = 2, row=8, sticky=W)
var9 = IntVar()
Checkbutton(mainframe, text="Best Before & Batch Information", variable=var9).grid(column = 2, row=9, sticky=W)
var10 = IntVar()
Checkbutton(mainframe, text="Net Weight & Correct Font Size.", variable=var10).grid(column = 2, row=10, sticky=W)
var11 = IntVar()
Checkbutton(mainframe, text="Barcode - Inner", variable=var11).grid(column = 2, row=11, sticky=W)
var12 = IntVar()
Checkbutton(mainframe, text="Address & contact details correct", variable=var12).grid(column = 2, row=12, sticky=W)
root.mainloop()
gives me the output of this:
The problem I am having is, when I choose a directory, open the image it stretches out all other content, I am wondering, how can I place the image next to the check-boxes and not move the check-boxes content?
Here is the output:
this is the output I am intending to get (used paint to edit):
You need to add rowspan option to your label2 variable, as follows:
label2.grid(row = 4, column = 0, rowspan = 10)
Edit the rowspan value to get the desired result
Looks like your window is supposed to consist of two independent columns. You can do this by nesting Frame objects. Starting with your main frame, put two frames side by side, like so:
mainframe = tk.Frame(root)
# configure your main frame here
leftframe = tk.Frame(mainframe)
leftframe.grid(row=0, column=0)
rightframe = tk.Frame(mainframe)
rightframe.grid(row=0, column=1)
And now you can proceed to place your widgets around. For instance:
# menu and label are supposed to be in the left column
tk.Label(leftframe, text="Choose your sign off here:").grid(row=0, column=0)
popupMenu = tk.OptionMenu(leftframe, tkvar, *choices)
# ...
# but you want the checkboxes on the right
var1 = IntVar()
Checkbutton(rightframe, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(row=0, column=0, sticky=W)
# ...
Please note the changes I made to row and column arguments. And of course, read the docs for the Grid Geometry Manual, as Eduard mentioned.
Related
I have a simple label and entry field that would:
1) Create a static label and clear the entry field after confirmation button click
2) Clear static label after reset button click
Is there any way to overwrite the entry field with a static label of the user input on the confirmation click instead of creating a new static label? And overwriting the static label with an empty entry field on the reset click?
Thank you for the help in advance.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
set_cname.destroy()
cbtn['state'] = NORMAL
def confirm():
global set_cname
text1="Customer Name: " + entry1.get()
set_cname = Label(frame1, text=text1)
set_cname.grid(row=3, column=0, columnspan=1)
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ").grid(padx=5, pady=5, columnspan=2, sticky=W)
entry1 = Entry(frame1)
entry1.grid(row=0, column=2, padx=5)
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=4, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=4, padx=5, pady=5)
root.mainloop()
You can replace the Entry with a Label by first creating both and then using pack() to switch between them. The trick is to not let their different sizes affect the application layout, which can be accomplished by disabling size propagation.
In my example I create a new frame (entry_frame) with a fixed size and then disable size propagation (.pack_propagate(False)). Then I use this new frame to contain the Entry/Label. Im giving the entry_frame the bg color khaki to let you see exactly where it is.
I fiddled a bit with the column numbers also.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
text_label.pack_forget()
entry1.pack()
cbtn['state'] = NORMAL
def confirm():
global set_cname
entry1.pack_forget()
text_label.config(text=entry1.get())
text_label.pack(side='left')
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ")
cname.grid(row=0, column=0, padx=5, pady=5, sticky=W)
entry_frame = Frame(frame1, width=130, height=20, bg='khaki')
entry_frame.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
entry_frame.pack_propagate(False) # Disable size propagation
entry1 = Entry(entry_frame) # Customer name entry
entry1.pack()
text_label = Label(entry_frame) # Label to hold customer name
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=2, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=2, padx=5, pady=5)
root.mainloop()
Be aware that this solution will be sensitive to font size changes.
I am trying to create an example program for my high school class. The idea of the program is you can select a game (a basic version of Steam) from a selection of radiobuttons. The radiobuttons are linked to a IntVar stored in self.library_game. When you select a radiobutton I want to use the value that the radiobutton assigns the Intvar to take a name out of a list and display the name of the game in a label. I want to do this so I can use the IntVar to access other lists. The other lists will show things like the games installed status. if the game is not currently "installed" you will be able to click on a button to update the status to "install" the game so it can be "launched".
The problem i am encountering is: When I try and use the IntVar to access the libraryGames list I get the following error:"list indices must be integers or slices, not method". I have tried to store the value from the IntVar as a regular integer with "test=self.library_game.get" and used "test" to access the list, self.game_selection_label.configure(text = "You have chosen: " + str(libraryGames[test]),fg="#01fc07"), but it doesn't work.
I am not the strongest programmer and am really pushing my ceiling with this stuff, so any help would be amazing.
from tkinter import*
# Variables and Lists
#Classes
libraryGames=["The Witcher 3: Wild Hunt GOTE", "Jurassic World: Evolution", "Red Dead Redemption 2","Mass Effect Trilogy","Subnautica"]
libraryGamesInstall=[True,False, False, False, False]
class SteamGUI:
def __init__(self, parent):
#variables
global libraryGames
global libraryGamesInstall
WD=800
self.header =PhotoImage(file = "header.gif")
self.library_game = IntVar()
self.library_game.set = ()
Title=Label(parent, image = self.header, width=WD, anchor=N)
Title.grid(row=0, column=0,columnspan=2, sticky=N,padx=2, pady=2)
#User Library Menu
frame1=Frame(bg="#000000",)
frame1.grid(row=1, column=0, sticky = 'w')
library_label=Label(frame1, text="User Library",bg="#000000",fg="#01fc07",font=("Eras Demi ITC","40"), anchor=N)
library_label.grid(row=0, column=0,columnspan=2, sticky=N,padx=2, pady=2)
radio1 = Radiobutton(frame1, variable = self.library_game, value = 0,text =libraryGames[0],
bg="#000000",fg="#ffffff",font=("Calibri","20"), command = self.library_choice)
radio1.grid(row=1, column=0, columnspan=2, sticky = 'w')
radio2 = Radiobutton(frame1, variable = self.library_game, value =1,text =libraryGames[1],
bg="#000000",fg="#ffffff",font=("Calibri","20"), command = self.library_choice)
radio2.grid(row=2, column=0, columnspan=2, sticky = 'w')
radio3 = Radiobutton(frame1, variable = self.library_game, value =2,text =libraryGames[2],
bg="#000000",fg="#ffffff",font=("Calibri","20"),command = self.library_choice)
radio3.grid(row=3, column=0, columnspan=2, sticky = 'w')
radio4 = Radiobutton(frame1, variable = self.library_game, value =3,text =libraryGames[3],
bg="#000000",fg="#ffffff",font=("Calibri","20"),command = self.library_choice)
radio4.grid(row=4, column=0, columnspan=2, sticky = 'w')
radio5 = Radiobutton(frame1, variable = self.library_game, value =4,text =libraryGames[4],
bg="#000000",fg="#ffffff",font=("Calibri","20"),command = self.library_choice)
radio5.grid(row=5, column=0, columnspan=2, sticky = 'w')
self.game_selection_label=Label(frame1, text="No game selected", bg="#000000", fg="#ffffff", width="50",)
self.game_selection_label.grid(row=6, column=0, columnspan=2, sticky='w')
self.game_install_status_label=Label(frame1, text="Install Status", bg="#000000", fg="#ffffff", width="50",)
self.game_install_status_label.grid(row=7, column=0, sticky='w', pady=10)
self.playLabel =Label(frame1,text="Game Status", bg="#000000", fg="#ffffff", width="50", pady=10)
self.playLabel.grid(row=9, column=0, sticky='w')
installButton=Button(frame1, text="Install", width = 20, font=("Eras Demi ITC","10"), pady=10)
installButton.grid(row=8, column=0, sticky = 'sw',)
playButton=Button(frame1, text="Play", width = 20,font=("Eras Demi ITC","10"), pady=10)
playButton.grid(row=8, column=0, sticky = 'se',)
frame2=Frame(bg="#ffffff",)
frame2.grid(row=1, column=1)
def library_choice(self):
test=0
test=self.library_game.get
print("hi", self.library_game.get)
self.game_selection_label.configure(text = "You have chosen: " + str(libraryGames[test]),fg="#01fc07")
#self.game_selection_label.configure(text = "You have chosen: The witcher 3!!!!!",fg="#01fc07")
#Main Routine
root=Tk()
window = SteamGUI(root)
root.geometry("800x700+0+0")
root.title("Steam Basic")
root.mainloop()
I need a bit off help..
In the example below I have two optionsMenus, two entries, and some labels.
What I'm trying to do, is to divide my input from the entry by the labels value, choosen from the optionsMenu, and then show the new value in the next column. But I'm a bit stuck now and can't get it to work.
from tkinter import *
class App(Frame):
def __init__(self, root=None):
Frame.__init__(self, root)
self.materialPrice = {'Brick': 70, 'Rockwool': 50, 'Concrete': 20}
materialvariable1 = StringVar(self, root)
materialvariable1.set("Choose material")
materialvariable2 = StringVar(self, root)
materialvariable2.set("Choose materiale")
self.w1 = OptionMenu(root, materialvariable1, *self.materialPrice, command=self.displayPrice).grid(row=2,
column=0,
columnspan=1,
sticky='WE')
self.w2 = OptionMenu(root, materialvariable2, *self.materialPrice, command=self.displayPrice2).grid(row=3,
column=0,
columnspan=1,
sticky='WE')
self.var = IntVar()
self.var.set(float(0.00))
self.var2 = IntVar()
self.var2.set(float(0.00))
self.entry1 = Entry(root, textvariable=self.var).grid(row=2, column=1)
self.entry2 = Entry(root, textvariable=self.var2).grid(row=3, column=1)
self.priceVarLabel1 = IntVar()
self.priceVarLabel1.set(float(0.00))
self.priceVarLabel2 = IntVar()
self.priceVarLabel2.set(float(0.00))
self.priceVarValue1 = Label(root, textvariable=self.priceVarLabel1, relief='sunken').grid(row=2,
column=2,
columnspan=1,
sticky='WE')
self.priceVarValue2 = Label(root, textvariable=self.priceVarLabel2, relief='sunken').grid(row=3,
column=2,
columnspan=1,
sticky='WE')
self.label1 = Label(root, textvariable=self.displayResult).grid(row=2, column=3)
self.label2 = Label(root, textvariable=self.displayResult2).grid(row=3, column=3)
def displayPrice(self, value):
self.priceVarLabel1.set(self.materialPrice[value])
def displayPrice2(self, value):
self.priceVarLabel2.set(self.materialPrice[value])
def displayResult(self):
self.label1.set(self.entry1 / self.priceVarValue1)
def displayResult2(self):
self.label1.set(self.entry1 / self.priceVarValue1)
root = Tk()
app = App(root)
root.title("help")
root.mainloop()
Just add the division to your function:
def displayPrice(self, value):
self.priceVarLabel1.set(self.materialPrice[value] / self.var.get())
You may want to change the starting value to 1 so that you don't get a ZeroDivisionError right off the bat.
BTW, initializing a widget and laying it out on the same line is a well known bug source. Always use 2 lines.
# very bad:
self.entry1 = Entry(root, textvariable=self.var).grid(row=2, column=1)
# good:
self.entry1 = Entry(root, textvariable=self.var)
self.entry1.grid(row=2, column=1)
I am designing a simple GUI in Python 2.7 Tkinter, but I can't get things to spread out as I want them. I have managed to get my various widgets roughly where I want them, however I can't seem to force spacing out and things are a little bunched up.
I have also tried to draw 3 LabelFrames to separate the window out, but widgets seem to fall over the LabelFrames. I am wondering how I can space this out a little better. The grid system seems to allow things to bunch up and ignores blank rows and columns as far as I can see.
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog, tkMessageBox
class FileZap():
def __init__(self, root):
root.title("TestGUI")
root.geometry("860x450")
self.topFrame = LabelFrame(root, text="Top Area")
self.topFrame.grid(row=1, column=1, rowspan=6, columnspan=7, padx=5, pady = 5, sticky="NSEW")
self.listbox1 = Listbox(root, width=50, selectmode="multiple")
self.listbox1.grid(row=3, column=2)
self.scrollbar = Scrollbar(orient=VERTICAL, command=self.listbox1.yview)
self.listbox1.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.grid(row=3, column=3, sticky="ns")
self.listbox2 = Listbox(root, width=50)
self.listbox2.grid(row=3, column=4)
self.selectLabel = Label(root, text="Select a folder: ")
self.selectLabel.grid(row=3, column=1)
self.user1 = Entry(root, width="50")
self.user1.grid(row=2, column=2)
self.browse = Button(root, text="Browse")
self.browse.grid(row=2, column=3)
self.addItems = Button(root, text="Add to Selection")
self.addItems.grid(row=4, column=2)
self.clearItems = Button(root, text="Clear Selection")
self.clearItems.grid(row=4, column=4)
self.leftFrame = LabelFrame(root, text="Left Area")
self.leftFrame.grid(row=5, column=1, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.replaceInLable = Label(root, text="String to replace: ")
self.replaceOutLable = Label(root, text="New string: ")
self.replaceInLable.grid(row=7, column=1)
self.replaceOutLable.grid(row=7, column=2)
self.replaceIn = Entry(root, width="20")
self.replaceOut = Entry(root, width="20")
self.replaceIn.grid(row=8, column=1)
self.replaceOut.grid(row=8, column=2)
self.replace = Button(root, text="Replace")
self.replace.grid(row=8,column=3)
self.rightFrame = LabelFrame(root, text="Right Area")
self.rightFrame.grid(row=5, column=4, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.quit = Button(root, text="Exit", command=root.quit)
self.quit.grid(row=9, column=6)
root = Tkinter.Tk()
file_zap = FileZap(root)
root.mainloop()
I have tried various alterations but can't nail it! Any help would be much appreciated.
First, the columns / row adapt to there content so an empty one as a zero height/width. If you want to put space between your widgets use the padx and pady options in the .grid method. They can take either one number which will give the padding on both sides or a couple of numbers giving the padding on each side.
Secondly, if you want your widgets to be inside a LabelFrame, you need to create them with this LabelFrame as master instead of the main window.
from Tkinter import LabelFrame, Tk, Button, Label
root = Tk()
# make row 0 resize with the window
root.rowconfigure(0, weight=1)
# make column 0 and 1 resize with the window
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
# create LabelFrames
top_frame = LabelFrame(root, text="top")
left_frame = LabelFrame(root, text="left")
right_frame = LabelFrame(root, text="right")
top_frame.grid(row=0, column=0, columnspan=2, padx=10, pady=(10,4), sticky="nsew")
left_frame.grid(row=1, column=0, padx=(10,4), pady=4, sticky="nsew")
right_frame.grid(row=1, column=1, padx=(4,10), pady=4, sticky="nsew")
#create widgets inside top_frame
Label(top_frame, text="I'm inside top_frame").pack()
Button(top_frame, text="Top").pack()
#create widgets inside left_frame
Label(left_frame, text="I'm inside left_frame").pack()
Button(left_frame, text="Left").pack()
#create widgets inside top_frame
Label(right_frame, text="I'm inside right_frame").pack()
Button(right_frame, text="Right").pack()
Button(root, text="Quit", command=root.destroy).grid(row=2, column=0,
columnspan=2, pady=10)
root.mainloop()
I want my labels and entry widgets and different rows but they automatically move to the top. What do I do to do that? Is there a simple function I could use?
from tkinter import *
root = Tk()
root.resizable(width = False, height = False)
label_1 = Label(root, text="Text")
label_2 = Label(root, text="Text2")
entry1 = Entry(root)
entry2 = Entry(root)
label_1.grid(row=4, column=2, sticky=E)
label_2.grid(row=5, column=2, sticky=E)
entry1.grid(row=4, column=3, sticky=E)
entry2.grid(row=5, column=3, sticky=E)
checkbox = Checkbutton(root, text="Check me")
checkbox.grid(columnspan=2)
Also do you know how to add sub frames? I searched but the examples were all with classes and I was left confused. I of course also want it to be in a specific column and row without automatically getting moved somewhere else.
Empty rows and columns have size 0. Blank labels can be used to create blank space.
from tkinter import *
root = Tk()
dummy = Label(root, text='\n')
label_1 = Label(root, text="Text")
label_2 = Label(root, text="Text2")
entry1 = Entry(root)
entry2 = Entry(root)
dummy.grid()
label_1.grid(row=4, column=2, sticky=E)
label_2.grid(row=5, column=2, sticky=E)
entry1.grid(row=4, column=3, sticky=E)
entry2.grid(row=5, column=3, sticky=E)
checkbox = Checkbutton(root, text="Check me")
checkbox.grid(columnspan=2)