Specifying the dimensions of a Tkinter Text Widget in pixels? - python

I'm trying to create a text widget in Tkinter (for Python) whose font size can change, but when this happens I don't want the widget to resize itself. All of the text in the widget is the same font style. What I've got so far:
root = Tk()
t = Toplevel(root)
fnt = tkFont.Font(family="Helvetica",size=36,weight="bold",underline=1)
txt = Text(t, font=fnt, width=20, height=6)
txt.grid(row=0,column=0)
b = Button(t, text="click", command=change)
b.grid(row=1, column=0)
txt.insert(END, "This is text!")
Where change is defined as:
def change():
txt.delete(1.0, END)
fnt.config(size=100)
txt.insert(END, "This is text!")
Now, when I click on the button, the text does indeed get bigger, but the entire widget resizes itself to compensate! I assume that this is because the size of the widget is specified in terms of "lines" and "characters", instead of pixels. How can I stop the widget from resizing?
I've tried not changing the font of the widget, but instead just inserting text with a tag that specifies a new font, which works, but then the problem is that when I manually type new text to the left and right of the inserted text, it is the default style and not the size I want.

I found the answer to my question on this page: How to stop Tkinter Text widget resize on font change?
The key is to build a Frame to put the text widget in, to specify the Frame size in pixels, and to call grid_propagate(False) on the Frame to prevent it from resizing when the text widget wants to resize.

Related

Adaptive resizing for a tkinter Text widget

I have been attempting to create a application that contains two Text() widgets, both of which can dynamically resize when the window size is changed. Before I have always used the root.pack() manager, with fill='both' and expand=True.
While this works for LabelFrames and most other widgets, it does not work when a Text widget is resized smaller then its original dimensions. Is there a way to have dynamically resizing Text widgets?
Ex.
import tkinter as tk
window = tk.Tk()
editor = tk.Text(bg='red')
editor.pack(side='top',fill='both',expand=True)
output = tk.Text(bg='green')
output.pack(side='top',fill='both',expand=True)
window.mainloop()
Tkinter will try to honor the requested size of a text widget. Since you didn't specify a size, the text widget will request a size of 80x24. When you resize the window smaller, pack tries to make room for everything at its requested size, and it does so in stacking order.
As the window shrinks, there's room for all of the first text widget but not enough for both. Because there's not enough room, it has to subtract space from the remaining widgets. Thus, it starts chopping off the last text widget.
To combat this, you can set the requested size of the text widgets to a small value that will fit in almost any window size, and then force them to grow by setting the size of the window as a whole. This way, pack will first allocate enough space for each small window, and then expand them equally when there's extra space.
For example:
import tkinter as tk
window = tk.Tk()
window.geometry("400x400")
editor = tk.Text(bg='red', width=1, height=1)
output = tk.Text(bg='green', width=1, height=1)
editor.pack(side='top',fill='both',expand=True)
output.pack(side='top',fill='both',expand=True)
window.mainloop()
The other solution is to use grid which lets you specify that rows and columns should be of uniform size.
import tkinter as tk
window = tk.Tk()
editor = tk.Text(bg='red')
output = tk.Text(bg='green')
editor.grid(row=0, column=0, sticky="nsew")
output.grid(row=1, column=0, sticky="nsew")
window.grid_columnconfigure(0, weight=1)
window.grid_rowconfigure((0,1), weight=1, uniform=1)
window.mainloop()

Is there a way to change the size of the contents of a GUI when the GUI is resized by the user?

I've made a GUI using Tkinter. For the time being, I set the geometry to '962x652' and made it so the user can't resize it by using .resizable(0, 0). I'm now looking for a way to make it so when the GUI is resized, all the elements change size as well along side it, preferably with the aspect ratio locked.
Is there a way to achieve this whilst making it so only the element change size visibly without changing actually changing size? For example, if my GUI contains a scrolledtext box, if the user was to resize the GUI, the scrolledtext will also increase in size, but so will the text and each line of text in it will stay in the same line. I hope that makes sense.
I've add some code down below to show what I'm working with. This should have a similar effect to what I currently have:
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
TrialGUI = Tk()
TrialGUI.title('Resize GUI')
TrialGUI.geometry('962x652+0+0')
#Remove the following so you can resize the GUI
TrialGUI.resizable(0, 0)
#These are the two frames. I've changed their colour so they are visible when they are resized.
ABC1b = Frame(TrialGUI, bg='lightpink', bd=20, width=900, height=600)
ABC1b.grid(row=0, column=0)
ABC2 = Frame(TrialGUI, bg='lightblue', bd=20, width=452, height=600)
ABC2.grid(row=0, column=1)
#This is the text box
txtQuestion = scrolledtext.ScrolledText(ABC1b, wrap=tk.WORD, width=42, height=10, font=(14))
txtQuestion.grid(row=0, column=0, columnspan=4, pady=3)
#This inserts text into it. I made it insert which line the text should be in so it is easier to check if it is still in the same line when it is resized.
txtQuestion.insert(tk.INSERT, 'This should be in the first line.----------------------------------- This should be in the second line.------------------------------ This should be in the third line.----------------------------------')
TrialGUI.mainloop()
If anyone decides to play around with this code, remember to remove TrialGUI.resizable(0, 0) so it can be resized.

python tkinter Can I make a widget in pixel? with text?

I want to make a text widget in pixel size. But always set on font size.
Here is my code:
import tkinter as tk
root = tk.Tk()
test_btn = tk.Button(root, text="test", height=10, width=10)
test_btn.pack()
root.mainloop()
I want to use pixel, but i can't so, I am using "place" method, so my code looks dirty.
I want to change them to "pixel size" and pack.
The width attribute is in units of characters if the button has text, but is in units of pixels if the button has an image. So, you can add a small transparent image to the button and set the compound option to allow both text and image at the same time. When you do that, width will be interpreted as pixels.
Example:
image = tk.PhotoImage(width=1, height=1)
button = tk.Button(root, image=image, text="Hello, world", compound="center",width=300)

How to scale the text with the rest of the widget, when rescaling a widget with Python tkinter?

When rescaling a widget, I'd like the text to scale with the rest of the widget.
Here is some code that scales the widget with a click-n-drag. That is working fine, but the text doesn't scale.
import tkinter as tk
#Create & Configure root
root = tk.Tk()
Grid.rowconfigure(root, 0, weight=1)
Grid.columnconfigure(root, 0, weight=1)
#Create & Configure frame
frame=tk.Frame(root)
frame.grid(row=0, column=0, sticky=N+S+E+W)
#Create a 5x10 (rows x columns) grid of labels inside the frame
for row_index in range(5):
Grid.rowconfigure(frame, row_index, weight=1)
for col_index in range(10):
Grid.columnconfigure(frame, col_index, weight=1)
btn = tk.Label(frame, text="Row %s: Col %s" % (row_index, col_index),
background = "#F8FC10") #create a label inside frame
btn.grid(row=row_index, column=col_index, sticky=N+S+E+W)
root.mainloop()
I want the text to scale with the rest of the widget. The widget scales fine, but the text does not. Is it possible to have the text scale with a widget that is scaling with a click-n-drag?
Yes, it is possible to scale the text, but it does take a little bit of work. I had to do something very similar, and the way I did it was via font size. When you create a Text widget, by default the Text widget gets a default font, 'TkFixedFont'. That named font is essentially 'Courier 10' or so. You can manually set the Text font via Text.config(font=...). The trick is to change the size of the font according to the relative size of the Text widget. So, you would use some sort of scaling function to translate the size of the Text widget to the size of the font you want, then update the font of the Text widget with your new font based on the font size that you calculated. Do this inside the '<Configure>' event handler which you define, which gets invoked when the Text widget (or whole app) gets resized.
In my app, I have buttons for zooming in and out, and I do this by changing the font size as described above. Works like a charm.
Rereading your post, I see that you're looking to change the text of some Labels. Create a new named font and assign it as the font for all your Labels. Then, in your '<Configure>' handler, just update the named font with the new font size, and it will propagate to all the widgets that use that named font. This goes for Labels, Buttons, Text widgets, etc.
Also, as a side note, as you scale the text on the Labels and other widgets, those widgets will adjust in size to the text they are displaying.

3.4 Python changing image position tkinter

I am making a small pop up to a text game I am making. I just want a small frame to pop up with some text and a picture to the far left but in a custom size and position. How would I do this? How do I insert text and change the image position and size, this is my current code, it works as in there are no errors and the image shows.
from tkinter import *
import time, sys
root = Tk()
root.configure(background='#16e116')
root.title('Pop Up')
root.geometry('300x200')
photo = PhotoImage(file='file.gif')
w = Label(root, image=photo)
w.pack()
root.mainloop()
If you want your image to be a different size (without it being deformed by resizing the widget) you have to make it the desired size in your image editor.
If you want to change the image position then use grid() where pack() has very limited placement options.
If you want text on a label, then use: text = Label(root, text="Hello world!"). This also comes with various options and styles such as font and it's size.
If you want the text over the image then use grid() and place it in the middle of the image by using rows and columns.
import tkinter
from tkinter import *
root = tkinter.Tk()
root.configure(background='#16e116')
root.title('Pop Up')
root.geometry('300x200')
photo = PhotoImage(file='file.gif')
w = Label(root, image=photo)
text = Label(root, text="Hello world!")
w.grid(row=3, column=3)
text.grid(row=3, column=3)
root.mainloop()
Although, the label will still have the background around it but you change the background colour using widgetname.config(bg="Colour")to make it suit your standards.
Now of course, I can't be sure the above will work because I don't have file.gif but you should also read tutorials before jumping straight into code to avoid confusion.

Categories

Resources