Make a Tkinter element on top of the others in Python - python

I'm searching for a way to put one element of Tkinter on top of the others in Python.
In the example below, what I tried to do is to put the yellow label on top of the white one - so when we change the size of the window the first label that will disappear is the white one, and only when its no longer visible the yellow one will start to shrink.
How can I realize this idea? Thanks in advance! (;
The code:
import tkinter as tk
root = tk.Tk()
root.config(background='black')
regularlabel = tk.Label(root, width=20, height=10, text='label')
regularlabel.pack()
bottomlabel = tk.Label(root, text='bottom label', bg='yellow')
bottomlabel.pack(side='bottom', fill='both')
root.mainloop()

Tkinter will shrink widgets in the reverse order of which they were added. Pack the bottom window first to solve your problem.
Since the layout of widgets tends to be changed more than the actual widgets during development, I find the code easier to understand and easier to maintain when layout is separate from widget creation. In the following example I've grouped the two layout statements together.
import tkinter as tk
root = tk.Tk()
root.config(background='black')
regularlabel = tk.Label(root, width=20, height=10, text='label')
bottomlabel = tk.Label(root, text='bottom label', bg='yellow')
bottomlabel.pack(side='bottom', fill='both')
regularlabel.pack()
root.mainloop()

Related

How to hide scrollbar when Text widget is not scrollable in tkinter

I am writing a program in python in which I want the Text widget in tkinter to have a scrollbar .
this is a part of my code -
import tkinter as tk
import tkinter.font as tkfont
window = tk.Tk()
display_text = "START\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nEND"
font_1 = tkfont.Font(family='Helvetica', size=22, weight='bold')
my_label_1 = tk.Text(window, wrap=tk.WORD, bd=0, fg="white", bg="black", font=font_1, width=76, height=21,)
_scrollbar = tk.Scrollbar(window, command=my_label_1.yview)
my_label_1.configure(yscrollcommand=_scrollbar.set)
my_label_1.tag_configure("center", justify='center')
my_label_1.insert(1.0, display_text)
_scrollbar.pack(side=tk.RIGHT, ipadx=3, ipady=500, pady=(0, 48))
my_label_1.pack()
window.mainloop()
But I have 500 strings which I import from a csv file, when I put the strings in this code the strings go in disply_text variable, this works fine.
But for some of those strings the text widget is big enough and the scrollbar is not needed as the text widget is not scrollable for those. but the scrollbar still shows up it is disabled though but I don't want it to be there.
I know pack_forget() or grid_forget() can do this job, But Then what parameter should I put so I know that this iteration of text is not scrollable on the Text widget.
And my window is of fixed size i.e. window.resizable(False, False).

My title impacts the button on my tkinker gui

Here is my code
from tkinter import *
root = Tk()
root.geometry('500x500')
btn = Button(root, text = 'Play', height=5,width=30, command = root.destroy)
btn.place(x=140, y=200)
w = Label(root, text ='Lost', font=("Courier", 50), height=4)
w.pack()
root.mainloop()#
The button is meant to say play on it
This is a side effect of several things. What's happening here is that the text in your label is being centered vertically in a box with room for 4 lines. That text has opaque background, so the bottom of text box is sitting over the top of your button and hiding the text. If you remove height=4, you'll see that it works just fine.
The other problem here is mixing the placement tools. You are mixing place and pack, and that is going to cause trouble. You may need to think about the layout issues some more.

Prevent scrolledtext from taking up entire parent window disallowing other widgets from showing up

So I am actually writing a simple GUI program which makes use of ScrolledText widget from tkinter.scrolledtext module.
The problem is this ScrolledText widget seems to take up the complete space available in the parent window. It disallows me from putting in any other widget in the same parent window. I have tried using both grid and pack GeoManagers (i know place isn't very useful in all cases), but the other widgets won't show up (neither above the scrolledtext widget nor below it).
HERE IS THE CODE--
import tkinter as tk
import tkinter.scrolledtext as sct
win2 = tk.Tk()
win2.geometry('1150x680')
win2.wm_geometry('+80+20')
txtbox = sct.ScrolledText(win2, width=500, height=350, bg='#fff', fg='#00f')
txtbox.grid(row=0, column=0)
txt = '<ABOUT 60 Lines TEXT HERE>'
txtbox.insert(1.0, txt)
txtbox.configure(state=tk.DISABLED)
tk.Button(win2, text='Got It', command=win2.destroy).grid(row=1, column=0)
This code is actually a part of a static method (i don't think makes a difference). When this is run the only thing visible on the screen is the scrolledtext widget with those 60 lines (i have tried it with 2 lines as well - still doesn't work).
The same happens when using pack().
To my surprise the only thing i could find in documentation is this::
ScrolledText Documentation
I don't know what I am missing here so please suggest me a way around this.
Thanks You :)
Solution with grid
The problem is the configuration of the grid: by default, the grid cells expand to fit the content. In your case the text widget is so big that the button in the row below is out of the screen. To fix that, you need to configure the first row and column to stretch with the GUI:
win2.rowconfigure(0, weight=1)
win2.columnconfigure(0, weight=1)
and make the text widget fill the cell, using the sticky option:
txtbox.grid(row=0, column=0, sticky='ewns')
This way the text widget will adapt to the window size and not the other way around.
Full code:
import tkinter as tk
import tkinter.scrolledtext as sct
win2 = tk.Tk()
win2.geometry('1150x680')
win2.wm_geometry('+80+20')
win2.rowconfigure(0, weight=1)
win2.columnconfigure(0, weight=1)
txtbox = sct.ScrolledText(win2, width=500, height=350, bg='#fff', fg='#00f')
txtbox.grid(row=0, column=0, sticky='ewns')
txt = '<ABOUT 60 Lines TEXT HERE>'
txtbox.insert(1.0, txt)
txtbox.configure(state=tk.DISABLED)
tk.Button(win2, text='Got It', command=win2.destroy).grid(row=1, column=0)
Alternative method, using pack
You can use pack with the options fill='both' and expand=True to achieve the same result as with grid. In this case, the additional trick is to pack the button first to ensure that it has enough space to show in the window. Code:
import tkinter as tk
import tkinter.scrolledtext as sct
win2 = tk.Tk()
win2.geometry('1150x680')
win2.wm_geometry('+80+20')
tk.Button(win2, text='Got It', command=win2.destroy).pack(side='bottom')
txtbox = sct.ScrolledText(win2, width=500, height=350, bg='#fff', fg='#00f')
txtbox.pack(fill='both', expand=True)
txt = '<ABOUT 60 Lines TEXT HERE>'
txtbox.insert(1.0, txt)
txtbox.configure(state=tk.DISABLED)

Frame-size does not show up anymore after using grid_forget() - Python tkinter

I was testing a method to hide and show frames by pressing a button (the buttons will be a menu bar later). So I created this code:
import tkinter as tk
from tkinter import *
win = Tk()
win.geometry("275x350")
win.title("MyProgram")
win.configure(background="white")
frame1 = Frame(win, width=200, height=200)
frame1.grid_propagate(False)
frame2 = Frame(win, width=200, height=200)
frame2.grid_propagate(False)
Label(frame1, text="Hello world", font="20").grid()
Label(frame2, text="Zweiter frame", font="20").grid()
def runGrid(run, destroy):
run.grid(row=1, column=2)
destroy.grid_forget()
def run2nd(run, destroy):
run.grid(row=1, column=2)
destroy.grid_forget()
Button(win, text="Run", command=lambda:runGrid(frame1, frame2)).grid(row=0, column=0)
Button(win, text="Run 2nd", command=lambda:run2nd(frame2, frame1)).grid(row=0, column=1)
win.mainloop()
So here is the problem...
After pressing the first button, the first frame comes up in his wanted size. After pressing the 2nd button, the 2nd frame comes up in his wanted size. But when you press the first button again (after pressing both buttons once before) then the frame is just showing up like grid_propagate was removed from the code (the frame is just as big as the label in it). Can someone explain me the fault in my code which is causing the problem?
Thanks a lot ;)
I found an other way to get what I want:
By simply using grid_remove() instead of using grid_forget() it is working.
But I still hope someone can answer my question because it really should work with grid_forget() as well I think.

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)

Categories

Resources