Having frames next to each other in Tkinter - python

Basically I want to place a clock at one side of the screen and text at the other, I use frames. How can I do this. Here's a picture of what it looks like now:
I want to make it so the clock is in line with the text on the same row but seperate labels. Take a look at my code and see if you could help me in someway, please!
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.state("zoomed") #to make it full screen
root.title("Vehicle Window Fitting - Management System")
root.configure(bg="grey80")
Title = Frame(root, width=675, height=50, bd=4, relief="ridge")
Title.pack(side=TOP, anchor='w')
titleLabel = Label(Title, font=('arial', 12, 'bold'), text="Vehicle Window Fitting - Management System", bd=5, anchor='w')
titleLabel.grid(row=0, column=0)
clockFrame = Frame(root, width=675, height=50, bd=4, relief="ridge")
clockFrame.pack(side=TOP, anchor='e')
clockLabel = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor='e')
clockLabel.grid(row=0, column=1)
curtime = ""
def tick():
global curtime
newtime = time.strftime('%H:%M:%S')
if newtime != curtime:
curtime = newtime
clockLabel.config(text=curtime)
clockLabel.after(200, tick)
tick()
Bottom = Frame(root, width=1350, height=50, bd=4, relief="ridge")
Bottom.pack(side=TOP)
root.mainloop()

One issue is trying to mix the pack and grid layout managers as they don't play well together. Below is something that just uses pack. (Note you can use either one within a frame, just not both at the same time.)
To get the two items on the same "line", another Frame named topFrame has been added and the titleLabel and clockFrame widgets nested inside that. This grouping allows them both to be acted-upon as a single unit when moved or positioned — automatically affecting both of them but retaining their relative positions (LEFT and RIGHT) to one another.
I also removed the curtime global variable because it wasn't really necessary (as you can see by the modified tick() function).
from tkinter import *
from tkinter import ttk
import time
root = Tk()
root.state("zoomed") #to make it full screen
root.title("Vehicle Window Fitting - Management System")
root.configure(bg="grey80")
topFrame = Frame(root, width=1350, height=50) # Added "container" Frame.
topFrame.pack(side=TOP, fill=X, expand=1, anchor=N)
titleLabel = Label(topFrame, font=('arial', 12, 'bold'),
text="Vehicle Window Fitting - Management System",
bd=5, anchor=W)
titleLabel.pack(side=LEFT)
clockFrame = Frame(topFrame, width=100, height=50, bd=4, relief="ridge")
clockFrame.pack(side=RIGHT)
clockLabel = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor=E)
clockLabel.pack()
Bottom = Frame(root, width=1350, height=50, bd=4, relief="ridge")
Bottom.pack(side=BOTTOM, fill=X, expand=1, anchor=S)
def tick(curtime=''): #acts as a clock, changing the label when the time goes up
newtime = time.strftime('%H:%M:%S')
if newtime != curtime:
curtime = newtime
clockLabel.config(text=curtime)
clockLabel.after(200, tick, curtime)
tick() #start clock
root.mainloop()
Here's what it looks like running:

I would create a frame for the header, and use something like header.pack(side="top", fill="x"). Then, I would put the two labels in that frame, packing one to the left and one to the right.
I would then add a second frame to fill the rest of the GUI, and all other widgets would go in that space.

Use grid(row=x, column=y). It makes adjacent object placing much easier.
Also, consider using just one frame for something.
You also don't need to specify width, really (unless if you use pack/grid_propagate(0)).
frame_1 = Frame(root, width=675, height=50)
frame_1.pack(side=TOP)
title_lbl = Label(frame_1, text="Lol whateva", height=50, bd=4, font=('arial', 12, 'bold'), relief="ridge", anchor=wherever_you_need_this_to_be)
title_lbl.grid(row=n, column=n)
clock_lbl = Label(clockFrame, font=('arial', 12, 'bold'), bd=5, anchor=wherever_you_need_this_to_be)
clock_lbl.grid(row=n, column=n)
You also didn't need more than one frame, just one frame for each label. It's a bad idea, really and it also consumes more time and typing.

Related

How to make text show up in a specific location on a Tkinter window

please see the code below. Working on a 100 days of code project. How to I make text appear in a specific position (x=400, y=150) for example on a window.
Please see my code below.
from tkinter import *
from tkinter import messagebox
BACKGROUND_COLOR = "#B1DDC6"
window = Tk()
window.title('Flashy')
window.config(padx=50, pady=50, bg=BACKGROUND_COLOR)
# Todo. Center the front of the card.
canvas = Canvas(width=800, height=526, bg=BACKGROUND_COLOR, highlightthickness=0)
card_front = PhotoImage(file='images/card_front.png')
canvas.create_image(400, 263, image=card_front)
canvas.grid(row=0, column=1, columnspan=2)
# Placing text on the card.
text_1 = Label(text="French", bg='white', font=("Ariel", 40, "italic"), fg='black')
text_1.goto(x=400, y=150)
text_1.grid(row=0, column=0, columnspan=2)
# Buttons
check_mark = PhotoImage(file='images/right.png')
check_mark_button = Button(image=check_mark, highlightthickness=0)
check_mark_button.grid(row=1, column=2)
wrong_mark = PhotoImage(file='images/wrong.png')
wrong_mark_button = Button(image=wrong_mark, highlightthickness=0)
wrong_mark_button.grid(row=1, column=1)
window.mainloop()
I tried using .config to specify the location for the text but that doesn't work.
Use the place() geometry manager to place widgets at specific coordinates.
Instead of:
text_1.goto(x=400, y=150)
Try...
text_1.place(x=400, y=150)
And remove:
text_1.grid(row=0, column=0, columnspan=2)
since you should only use one geometry manager method (pack, grid, or place) on a given widget.

tkinter deforms my frames after inserting objects

So I want to insert some objects in a frame, but when I firstly added a button the frames where were they weren't suppoused to.
Before
After
And this is the code:
import tkinter as tk
root = tk.Tk()
root.geometry("1200x700")
# Main frames
frame1 = tk.Frame(root, width=1200, height=625)
frame2 = tk.Frame(root, width=1200, bg="black", height=75)
frame1.grid(row=1, column=1)
frame2.grid(row=2, column=1)
# Secondary frames
frame1browser = tk.Frame(frame1, height=625, width=850, bg="grey")
frame1a = tk.Frame(frame1,height=625, width=(1200-850))
frame1browser.grid(row=1, column=1)
frame1a.grid(row=1, column=2)
# Last frames
frame1aa = tk.Frame(frame1a, width=(1200-850),height=525, bg="green")
frame1ab = tk.Frame(frame1a, width=(1200-850),height=100, bg="yellow")
frame1aa.grid(row=1, column=1)
frame1ab.grid(row=2, column=1, sticky="nswe")
# Elements that are not frames
Button1 = tk.Button(frame1ab, text="ur mother")
Button1.grid(column=1, row=1)
root.mainloop()
The frame ignores the width/height explicitly given if there is a widget inside it, by default. AFAIK, It finds and uses the minimum size required to fit all the widgets, also accommodating to extra properties like sticky, expand and so on.
To override this behavior, you will have to use the <grid/pack>_propagate(False) depending on whether you use pack or grid on the items inside the frame. Now the frame will grow/shrink as much as the size you specify.
frame1ab.grid_propagate(False)

Only open 1 window when button clicked multiple times

I am trying to create a basic invoicing system. However i have encountered an issue as you can tell from my the title, is there any way to achieve this. I have been using a counter to determine if the window should open or not but i dont think it is right.
from tkinter import *
window = Tk()
count = 0
def openNewWindow():
global count
count = count + 1
if count == 1:
newWindow = Toplevel(window)
newWindow.title("New Window")
newWindow.geometry("800x800")
newWindow.title('test ©') # Frame title
newWindow.iconbitmap('icon4.ico') # Frame logo
if 'normal' == newWindow.state():
count = 2
else:
count = 0
width = window.winfo_screenwidth()
height = window.winfo_screenheight()
window.geometry("%dx%d" % (width, height))
bg = PhotoImage(file="bsor.gif")
label_image = Label(window, image=bg)
label_image.place(x=0, y=0)
title_label = Label(window, text="Job Management System", bg="black", fg="white")
title_label.config(font=("Courier", 70))
title_label.place(x=65, y=3)
customer_database_button = Button(window, text="Customer Database", width="23", height="2",
font=('Courier', 13, 'bold'), command=openNewWindow)
customer_database_button.grid(row=3, column=0, pady=185, padx=(110, 0))
employee_database_button = Button(window, text="Employee Database", width="23", height="2",
font=('Courier', 13, 'bold'))
employee_database_button.grid(row=3, column=1, pady=10, padx=(50, 0))
job_category_button = Button(window, text="Job Category (Pricing)", width="23", height="2",
font=('Courier', 13, 'bold'))
job_category_button.grid(row=3, column=2, pady=10, padx=(50, 0))
quote_sale_button = Button(window, text="Quotes / Sales", width="23", height="2", font=
('Courier', 13, 'bold'))
quote_sale_button.grid(row=3, column=3, pady=10, padx=(50, 0))
cash_management_button = Button(window, text="Cash Management", width="23", height="2", font=
('Courier', 13, 'bold'))
cash_management_button.grid(row=3, column=4, pady=10, padx=(50, 0))
analysis_mode_button = Button(window, text="Analysis Mode", width="23", height="2", font=
('Courier', 13, 'bold'))
analysis_mode_button.grid(row=3, column=5, pady=10, padx=(50, 0))
window.title('test') # Frame title
window.iconbitmap('icon4.ico') # Frame logo
window.mainloop()
Here is a minimal example on how to do it (works best with only one additional allowed window):
from tkinter import Tk, Toplevel, Button
def open_window(button):
button.config(state='disabled')
top = Toplevel(root)
top.transient(root)
top.focus_set()
top.bind('<Destroy>', lambda _: btn.config(state='normal'))
root = Tk()
root.geometry('300x200')
btn = Button(root, text='Open new window!', command=lambda: open_window(btn))
btn.pack(expand=True)
root.mainloop()
Just have the function disable the button and bind a <Destroy> event to the Toplevel to set the button's state back to normal. (Also you may want to use .transient on the Toplevel to make it appear above its master so that people don't forget that they haven't closed the window and wonder why they can't press the button (it will also not display additional icon in the taskbar))
Also:
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but have space around = if it is used for assigning a value (variable = 'some value'). Have space around operators (+-/ etc.: value = x + y(except here value += x + y)). Have two blank lines around function and class declarations.

Buttons and tables not visible in tkinter Python

I have tried to add a scrollbar through canvas and added a frame named frametwo in canvas. I am adding a few buttons and a table in that frame but nothing is visible. If I add all these things in the root then they become visible. I have tried different things but nothing worked.
Here is the code that I wrote
import myvariant
from tkinter import ttk
from tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from pandas import DataFrame
from PIL import ImageTk, Image
rsid_list=[8,9,5,5]
mv = myvariant.MyVariantInfo()
def main():
main_window = Tk()
app = info(main_window)
main_window.mainloop()
class info:
def __init__(self, root):
self.root = root
self.root.title('VCESS-ExAC')
self.root.geometry('1600x800+0+0')
self.root.configure(background='light grey')
main_frame = Frame(self.root)
main_frame.pack(fill=BOTH, expand=1, padx=0, pady=0)
main_frame.place(x=0, y=0, width=1600, height=800)
my_canvas = Canvas(main_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_scroll = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview)
my_scroll.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scroll.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.config(scrollregion=my_canvas.bbox(ALL)))
self.frametwo = Frame(my_canvas)
my_canvas.create_window((0, 0), window=self.frametwo, anchor='nw')
table1 = LabelFrame(self.root, text="Retreived Data") ################
table1.pack(fill="both", expand="yes", padx=0, pady=0) ###################
table1.place(x=40, y=250, width=250, height=380)
table = ttk.Treeview(table1, height="8") #################
table['columns'] = ['rsID']
table.column('#0', width=120, minwidth=25)
table.column('rsID', anchor=W, width=120)
table.heading('#0', text='Serial No.', anchor=W)
table.heading('rsID', text='rsID', anchor=W)
for i in range(len(rsid_list)):
table.insert(parent='', index='end', iid=i, text=i + 1,
values=(rsid_list[i]))
table.place(x=0, y=0) ##########################
# VERTICAL SCROLLBAR
yscrollbar = ttk.Scrollbar(table1, orient=VERTICAL, command=table.yview) #############
yscrollbar.pack(side=RIGHT, fill='y') ##################
# HORIZONTAL SCROLLBAR
xscrollbar = ttk.Scrollbar(table1, orient=HORIZONTAL, command=table.xview) ###################
xscrollbar.pack(side=BOTTOM, fill='x') #######################
table.configure(yscrollcommand=yscrollbar.set, xscrollcommand=xscrollbar.set) ##############
table.pack(side=LEFT)
btn_download = Button(self.frametwo, text='Save File',
font=("Times New Roman", 14, 'bold'), bd=3, relief=RIDGE,
cursor='hand2', bg='#154857', fg='white', activeforeground='white',
activebackground='#154857')
btn_download.place(x=190, y=640, width=120)
btn_graph = Button(self.frametwo, text='Graph',
font=("Times New Roman", 14, 'bold'), bd=3, relief=RIDGE,
cursor='hand2', bg='#154857', fg='white', activeforeground='white',
activebackground='#154857')
btn_graph.place(x=530, y=640, width=120)
if __name__ == '__main__':
main()
Looking forward for any possible solution.
You have created the buttons inside self.frametwo. You are using place, which means that the buttons don't affect the size of the frame. Since you don't give self.frametwo a size, it defaults to one pixel wide and one pixel tall. Therefore, the frame is essentially invisible and thus all buttons inside the frame are invisible.
You can easily see this by switching to using pack or grid for the buttons. When you use pack or grid, the parent frame by default will grow or shrink to fit its children. Thus, using either of these for the buttons will cause the frame to grow just big enough to show the buttons.
I am adding ... a table in that frame but nothing is visible.
You are not adding the table to the frame, you are adding it to the root window. If you want to add it to the frame, you must use the frame as its parent. And again, you should probably not use place. place is almost never the right choice unless you are prepared to do a lot of extra work to make sure widgets are visible and responsive to changes in widget size, font size, display resolution, etc.

Python Calculator results are not being displayed

so i was trying to make a python calculator, that opens like a window, but before the calculations i was trying to make it display the numbers that i clicked, everything was normal, the append, the list, everything was normal until it had to display the actual numbers, where it displays nothing, i tried to make change the label to "hi" for example to see if the problem is with the list, but nothing is being displayed, can someone help me get numbers to be displayed in the "results" area? here is my code:
root = tk.Tk()
color = '#263D42'
numbers = []
Background = tk.Canvas(root, height=600, width=601, bg=color)
Background.pack()
resultBack = tk.Canvas(root, height=150, width=400, bg="#E4E0E0")
resultBack.place(x=50, y=1)
root.title('Calculator')
root.iconphoto(False, tk.PhotoImage(file='plus.ico'))
root.resizable(width = False, height = False)
root.geometry("500x600")
for number in numbers:
label = tk.Label(root, text="hi", bg="black")
label.pack()
frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1) #frame
def addOne():
for widget in frame.winfo_children():
widget.destroy()
numbers.append('1')
for number in numbers:
print(number)
label = tk.Label(root, text=number, bg="black")
label.pack()
print(numbers)
one = tk.Button(root, text="1", padx=10, pady=5, fg="#000000", bg="#ffffff", command=addOne)
one.place(x=30, y=30)
root.mainloop()
You should not be creating and deleting your labels like that; you can just change them.
Maybe try something like this:
import tkinter as tk
root = tk.Tk()
numbers = []
root.title('Calculator')
root.resizable(width = False, height = False)
root.geometry("500x600")
label_text = tk.StringVar()
label_text.set('hi')
label = tk.Label(root, textvariable=label_text)
label.pack()
frame = tk.Frame(root, bg="white")
frame.place(relwidth=0.8, relheight=0.8, relx=0.1, rely=0.1) #frame
def addOne():
numbers.append(1)
work = ""
for i in numbers:
work+=str(i)
label_text.set(work)
one = tk.Button(root,
text="1",
padx=10,
pady=5,
fg="#000000",
bg="#ffffff",
command=addOne)
one.place(x=30, y=30)
root.mainloop()
That should get the numbers showing up. StringVars are your friend for these sorts of things. As you update them, tk automatically updates the widget they are attached to.
From here, you will probably want to move things around to look better etc. and you probably don't want to have to add a method for each button (addTwo, addThree, addFour etc.) Let us know if you need more help.

Categories

Resources