Python tkinter align buttons with labels problems - python

I want to align the second label(the blue text) under those two buttons(I aligned them on left side), I tried to use frames... or with grid but I still don't know how to do it..
Here is the image screenshot and here is the code:
from tkinter import *
root = Tk()
root.title("Tema 1")
root.geometry("550x600")
first_frame = Frame(root)
first_frame.pack(side=TOP)
first_label = Label(first_frame, text = "Exercitiul 1",font = "Times 15 bold")
button_ex1_1 = Button(first_frame, text = "Enunt", font = "Times 12 italic", command = lambda: btn_ex1_1(l1),height = 1, width = 20)
button_ex1_2 = Button(first_frame, text = "Rezolvare", font = "Times 12 italic", command = lambda: btn_ex1_2(l1),height = 1, width = 20)
l1 = Label(first_frame, font="Times 13 bold", fg="blue" , wraplength = 550, width=55)
first_label.pack(side=TOP)
button_ex1_1.pack(side=LEFT)
button_ex1_2.pack(side=LEFT)
l1.pack(side=BOTTOM)

The simplest solution is to pack the blue label before packing the buttons.
first_label.pack(side=TOP)
l1.pack(side=BOTTOM)
button_ex1_1.pack(side=LEFT)
button_ex1_2.pack(side=LEFT)
The packer works by aligning widgets to a side of existing empty space. When you put a widget on the left, the remaining empty space will be to the right of that widget. So, put the things on top first, followed by the things on the bottom, and then the things that go in the middle.

Related

Making a rectangle border around text in Textbox python tkinter

I want to have a rectangle border around certain text that is added to the text box from the end and will be placed at the center.
For example:
Unfortunately, I can't find a way to do that, because I
don't know how to place texts at the center of the line in the text box, and don't know how to surround a text with a rectangle.
You can wrap a Label with border between a space and newline with justify='center' in a Text widget.
Below is an example:
import tkinter as tk
root = tk.Tk()
textbox = tk.Text(root, width=30, height=10)
textbox.pack()
textbox.tag_config('center', justify='center')
def center_label(textbox, **kwargs):
textbox.insert('end', ' ', 'center')
lbl = tk.Label(textbox, bd=3, relief='solid', **kwargs)
textbox.window_create('end', window=lbl)
textbox.insert('end', '\n\n')
center_label(textbox, text='hello', width=10, font='Arial 12 bold')
center_label(textbox, text='............', width=20)
textbox.insert('end', '\nhello\n')
root.mainloop()
Result:
Try putting the text box into it's own frame.
Some thing like this:
from Tkinter import *
root = Tk()
labelframe = LabelFrame(root, text="LabelFrame")
labelframe.pack()
text = Label(labelframe, text="Text inside labelframe")
text.pack()
root.mainloop()
You can add the border to the Entry using relief = "solid", centre the text with outline and you can use grid to align the widgets the way you want.
import tkinter as tk
root = tk.Tk()
root.geometry("400x200")
root.grid_columnconfigure(0, weight = 1)
ent1 = tk.Entry(root, relief = "solid", justify = "center")
ent1.insert(0, "hello")
ent1.grid(row = 0, column = 0, pady = 10)
ent2 = tk.Entry(root, relief = "solid", justify = "center")
ent2.insert(0, ".......")
ent2.grid(row = 1, column = 0, pady = 10)
lab1 = tk.Label(root, text = "hello")
lab1.grid(row = 2, column = 0, sticky = "w")
lab2 = tk.Label(root, text = "hello")
lab2.grid(row = 3, column = 0, sticky = "w")
root.mainloop()
Most of this is straightforward, the root.grid_columnconfigure line makes the grid take up the full width of the root window by giving the first column a weight of 1. The result is very similar to your example:
You could create an Entry widget in the textbox using text.window_create(). You could customize the border of the Entry widget, and you would be able to type text inside it. To make it look more like part of the textbox, you should register events so when the user presses Right and the caret is one character left of the Entry, give the Entry focus using focus_set. You could do the same with the Left.

How to make a floating Frame in tkinter

For my tkinter app I want to make a frame that would on top of other widgets, not taking any space (like html position fixed).
The Frame will have to contain widgets, if Frame is not possible labels or buttons will do.
I have no idea how to do it so haven't tried anything yet. Please help!
Here is a demonstration of place manager.
Remarks in the code explain behaviour.
import tkinter as tk
root = tk.Tk()
root.geometry("868x131")
button = tk.Button(root, text = "A Button")
button.place(x = 2, y = 2)
Frame = tk.LabelFrame(root, text = "A LabelFrame using place", bg="cyan")
# Frame using place with x, y, width, height in absolute coordinates
Frame.place(x = 250, y = 20, width = 600, height = 70)
ButtonInFrame = tk.Button(Frame, text = "A Button IN LabelFrame", bg="white")
# Note: place x,y is referenced to the container (Frame)
# Note: place uses just x,y and allows Button to determine width and height
ButtonInFrame.place(x = 2, y = 2)
Label = tk.Label(root, text = "A Label on LabelFrame\nWith multiple lines\nOf Text.", bg="light green")
# Label sits on top of buttonFrame and Frame
# Note place uses just x,y and allows Label to determine width and height
Label.place(x = 330, y = 60)
root.mainloop()

Tkinter Label resize when packing a button

I am trying to put a single vertical tkinter lable at the left of my window.
FONT = ('helvetica', 18)
write = 'hello world'
label = tk.Label(
window, anchor = 's', background = BACKGROUNDGREY, borderwidth = 0, font = FONT, foreground = 'white',
justify = 'center', pady = 40, relief = 'flat', text = write, width = len(write) * 2
)
label.pack(side = 'left', fill = 'y')
Everything works just fine as shown here:
But now, when I add this code to put a button...
btn = tk.Button(
label, activebackground = BACKGROUNDGREY, borderwidth = 0, background = BACKGROUNDGREY, height = 70,
highlightcolor = 'white', width = 70
)
btn.pack()
This happen:
as you can see, i don't know why but the label's text is not readable anymore and it also resize the width and I want to keep my label of the width shown in the first image.
UPDATE: I see that some of us did not understand: i want exatly the button inside the label.
You have put the button inside the label. Also, you've requested that the button be 70 characters tall. pack will shrink or expand a parent to fit its children, so the label is shrinking to exactly fit the button, and the button has a higher stacking order so it obscures the text of the label.

tkinter useing grid on a frame doesn't seem to work

Im trying to get a tkinter gui that lets the user sign in im really new to tkinter. I made a frame and when i use grid to put another frame widget inside of the frame it does it based off of the root and not the inner_frame thats what I think is happening. In the code I made a grey box to demonstrate and I dont understand why it is below the blue frame and not inside the yellow frame under the "sign in" text. Thanks for the help.
from tkinter import *
root = Tk()
root.title("sighn in test")
#colors
background = "#273E47"
accent = "#d8973c"
red = "#bb4430"
white = "#edf2f4"
#this creates and places the background frame
main_buttons_frame = Frame(root, height = 500, width = 400, bg = background).grid(row = 0, column = 0)
#this creates and places the inner frame
inner_frame = Frame(main_buttons_frame, height = 450, width = 300, bg = accent).grid(row = 0, column = 0)
#this creates and places the "sighn in text"
top_text = Label(inner_frame, text = "sign in", font = ("helvitica", 30, "bold"), bg = accent, fg =
background).grid(row = 0, column = 0)
#this is a test to demonstrate
test_frame = Frame(inner_frame, bg = "grey", height = 100, width = 100).grid(row = 1, column = 0)
root.mainloop()
You have very common mistake of beginners
inner_frame = Frame(...).grid...()
It assigns None to inner_frame because grid()/pack()/place() gives None.
So later Frame(inner_frame, ..) means Frame(None, ..) and it adds to root
You have to do it in two steps
inner_frame = Frame(...)
inner_frame.grid(...)
And now you have Frame assigned to inner_frame
EDIT:
With correctly assigned widgets I get
and now gray box is inside yellow frame but image shows different problem - grid()/pack() automatically calculate position and size and external frame automatically change size to fit to child's size.
Using .grid_propagate(False) you can stop it
But it shows other problem - cells don't use full size of parent so yellow frame is moved to left top corner, not centered :) Empty cells have width = 0 and heigh = 0 so moving all to next row and next column will not change it - it will be still in left top corner :)
You need to assign weight to column and/or row which decide how to use free space. All columns/rows has weight=0 and when you set weight=1 then this row and/or column will use all free space - (this would need better explanation) - and then element inside cell will be centered.
main_buttons_frame.grid_columnconfigure(0, weight=1)
main_buttons_frame.grid_rowconfigure(0, weight=1)
import tkinter as tk # PEP8: `import *` is not preferred
# --- colors ---
background = "#273E47"
accent = "#d8973c"
red = "#bb4430"
white = "#edf2f4"
# --- main ---
root = tk.Tk()
root.title("sighn in test")
main_buttons_frame = tk.Frame(root, height=500, width=400, bg=background) # PEP8: without spaces around `=` inside `( )`
main_buttons_frame.grid(row=0, column=0)
#main_buttons_frame = None
main_buttons_frame.grid_propagate(False)
main_buttons_frame.grid_columnconfigure(0, weight=1)
main_buttons_frame.grid_rowconfigure(0, weight=1)
inner_frame = tk.Frame(main_buttons_frame, height=450, width=300, bg=accent)
inner_frame.grid(row=0, column=0)
#inner_frame = None
inner_frame.grid_propagate(False)
inner_frame.grid_columnconfigure(0, weight=1)
inner_frame.grid_rowconfigure(0, weight=1)
top_text = tk.Label(inner_frame, text="sign in", font=("helvitica", 30, "bold"), bg=accent, fg=background)
top_text.grid(row=0, column=0,)
#top_text = None
#top_text.grid_propagate(False)
#top_text.grid_columnconfigure(0, weight=1)
#top_text.grid_rowconfigure(0, weight=1)
test_frame = tk.Frame(inner_frame, bg="grey", height=100, width=100)
test_frame.grid(row=1, column=0)
#test_frame = None
#test_frame.grid_propagate(False)
#test_frame.grid_columnconfigure(1, weight=1)
#test_frame.grid_rowconfigure(0, weight=1)
root.mainloop()
BTW: PEP 8 -- Style Guide for Python Code

I want to print the entry text from textbox to console. Below is my code

I am trying to make a GUI using python tkinter.
I want to print the entry text from textbox to console after the analyzebutton is pressed.
here is my code
root = Tk()
root.title('Title')
MiddleFrame = Frame(root)
BottomFrame = Frame(root)
TopFrame.pack(side = TOP)
MiddleFrame.pack()
BottomFrame.pack(side = BOTTOM)
TextArea = Text()
ScrollBar = Scrollbar(root)
ScrollBar.config(command = TextArea.yview)
TextArea.config(height = 25, width = 70,
background = "white", yscrollcommand = ScrollBar.set)
TextArea.grid(padx = 18, pady = 18)
ScrollBar.pack(side = RIGHT, fill = Y)
padx = 10
pady = 10
TextArea.pack(padx = padx, pady = pady)
AnalyzeButton = Button(BottomFrame, text = "Analyze", fg = "white", bg = "blue", command = callback)
AnalyzeButton.pack(fill = X, padx = padx, pady = pady)
def callback():
text_input = Text.get()
print(text_input)
root.mainloop()
thanks in advance
Use get method of Text. Use the widget not the class-Text. Here is what you need to do:-
text_input = TextArea.get("1.0","end-1c")
You have several problems in your code. I will break it down so you understand what is going on here.
Fist I noticed you have tried to pack TopFrame but you have not actually defined TopFrame yet. So I added TopFrame = Frame(root) to your code.
Next we have a common mistake people encounter when trying to use grid() and pack() on the same window/frame. This is not allowed by the geometry manager. So you will need to decide on either grid() or pack() for all your needs in each window/frame. For now I changed TextArea.grid() to TextArea.pack() to get your code to work.
Next your button command was referencing a function that was after the command. This does not work outside of a class so you will need to move your callback() function above your AnalyzeButton.
Next we need to fix the indention on your callback() function. You must remember indention is very important in python and you should take care to keep your indention clean and consistent.
The last thing we needed to fix to get everything working as you were intending is to change:
text_input = Text.get()
To:
text_input = TextArea.get(1.0, END)
You were trying to call get() on the method that created the text widget and not the widget instance.
You also need to define from what part of the text widget you want to start reading data and how far you want to read through the text widget. this is done by applying 2 positions points with 1.0, END or "1.0", "end-1c" as tkinter allows for a few ways to apply these points. This will say 1.0 start at the first line at the first position on that line and END will say read until the last line of the textbox.
There may be other issues but I only fixed the problems preventing the code from working as intended. Your code modified to work below:
from tkinter import *
root = Tk()
root.title('Title')
TopFrame = Frame(root) # was missing from your code
MiddleFrame = Frame(root)
BottomFrame = Frame(root)
TopFrame.pack(side = TOP)
MiddleFrame.pack()
BottomFrame.pack(side = BOTTOM)
TextArea = Text()
ScrollBar = Scrollbar(root)
ScrollBar.config(command = TextArea.yview)
TextArea.config(height = 25, width = 70,
background = "white", yscrollcommand = ScrollBar.set)
TextArea.pack() # can't use pack and grid on the same window/frame. Changed this to pack()
ScrollBar.pack(side = RIGHT, fill = Y)
padx = 10
pady = 10
TextArea.pack(padx = padx, pady = pady)
# this function needs to be before the command that references it.
def callback():
# fixed indention
text_input = TextArea.get(1.0, END) # you need to reference that widget name not the tkinter method used to create the widget.
print(text_input)
AnalyzeButton = Button(BottomFrame, text = "Analyze", fg = "white", bg = "blue", command = callback)
AnalyzeButton.pack(fill = X, padx = padx, pady = pady)
root.mainloop()

Categories