change size of tkinter messagebox - python

In python, I am attempting the change the width of the tkinter messagebox window so that text can fit on one line.
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
messagebox.showinfo("info","this information goes beyond the width of the messagebox")
root.mainloop()

It's not possible to adjust the size of messagebox.
When to use the Message Widget
The widget can be used to display short text messages, using a single font. You can often use a plain Label instead. If you need to display text in multiple fonts, use a Text widget. -effbot
Also see:
Can I adjust the size of message box created by tkMessagebox?

#CharleyPathak is correct. You either need to put a newline in the middle of the text, because message boxes can display multiple lines, or create a custom dialog box.

Heres another method that gets the effect youre looking for but doesnt use messagebox. it looks a lot longer but it just offers much more in terms of customization.
def popupmsg():
popup = tk.Tk()
def leavemini():
popup.destroy()
popup.wm_title("Coming Soon")
popup.wm_attributes('-topmost', True) # keeps popup above everything until closed.
popup.wm_attributes("-fullscreen", True) # I chose to make mine fullscreen with transparent effects.
popup.configure(background='#4a4a4a') # this is outter background colour
popup.wm_attributes("-alpha", 0.95) # level of transparency
popup.config(bd=2, relief=FLAT) # tk style
# this next label (tk.button) is the text field holding your message. i put it in a tk.button so the sizing matched the "close" button
# also want to note that my button is very big due to it being used on a touch screen application.
label = tk.Button(popup, text="""PUT MESSAGE HERE""", background="#3e3e3e", font=headerfont,
width=30, height=11, relief=FLAT, state=DISABLED, disabledforeground="#3dcc8e")
label.pack(pady=18)
close_button = tk.Button(popup, text="Close", font=headerfont, command=leavemini, width=30, height=6,
background="#4a4a4a", relief=GROOVE, activebackground="#323232", foreground="#3dcc8e",
activeforeground="#0f8954")
close_button.pack()

I managed to have a proper size for my
"tkMessageBox.showinfo(title="Help", message = str(readme))" this way:
I wanted to show a help file (readme.txt).
def helpfile(filetype):
if filetype==1:
with open("readme.txt") as f:
readme = f.read()
tkMessageBox.showinfo(title="Help", message = str(readme))
I opened the file readme.txt and EDITED IT so that the length of all lines did not exeed about 65 chars. That worked well for me. I think it is important NOT TO HAVE LONG LINES which include CR/LF in between. So format the txt file properly.

Related

How to make Text widgets adaptive in Tkinter?

Ok so let's say I've got a Text object. How can I make it so that it gets an extra line (or height + 1) whenever I fill in the current line? like when it starts hiding the left of the line to show you the end?
Edit: since the question wasn't clear, I'll describe it more carefully.
Take this code as reference:
from tkinter import *
root = Tk()
text = Text(root, width=50, height=1)
text.pack
What it does, is creating a new Text widget of 1 line, and packs it. You may ask: Why don't you use the Entry widget? Because I want it to add more lines, instead of hiding what you already wrote to make some room for what you're writing, as shown below:
from tkinter import *
from threading import Thread
def adjustheight():
while True:
#check if whatever it's written takes more than a line to show
if takesmorethan1line == True:
text.config(height=(text.cget("height") + 1)
root = Tk()
text = Text(root, width=50, height=1)
text.pack
Thread(target = adjustheight).start()
root.mainloop()
I couldn't understand your question very well, But I assume that you have problem with wrapping a text. For instance when you reduce the window size, the text should break into multi lines. Here is as example:
import tkinter as tk
class MainWindow(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.my_label = tk.Label(
self, text="Helllllooooooooooooooooooooooooo")
self.my_label.bind('<Configure>',
lambda e: self.my_label.config(
wraplength=self.my_label.winfo_width()
))
self.my_label.pack()
self.mainloop()
if __name__ == '__main__':
window = MainWindow()
Line breaking, also known as word wrapping, is breaking a section of text into lines so that it will fit into the available width of a page, window or other display area, Read more.
Solution
Tkinter's Text widget have this feature already built in. wrap is the option that will do it.
From the docs:
This option controls the display of lines that are too wide.
With the default behavior, wrap=tk.CHAR, any line that gets too long will be broken at any character.
Set wrap=tk.WORD and it will break the line after the last word that will fit.
Example
import tkinter as tk
root = tk.Tk()
text = tk.Text(root, wrap=tk.WORD)
text.pack(fill=tk.BOTH, expand=1)
root.mainloop()

How do I change the size of a tkinter canvas through a new window?

So I have one Tkinter screen that has a canvas. I want to change the size of the canvas by creating a new window that has entry widgets. So I created a new screen and added 2 entry widgets. I want to get the value from those widgets and based on that...it should change the size of the canvas. I tried to do this for an hour, but no luck. Please assist me.
Here is my code
from tkinter import *
# create root window
root = Tk()
# Create Canvas
canvas = Canvas(root, width=50, height=50)
# Create an additional window (the one that is used to enter the new geometry)
dialog = Toplevel(root)
# Add entry widgets for width and height to the new window
width_entry = tk.Entry(dialog)
height_entry = tk.Entry(dialog)
# Add a button to the new window that applies the given width and height
apply_button = Button(dialog, text = 'Apply geometry', command = lambda: canvas.geometry(width_entry.get()+'x'+height_entry.get()))
# Its not possible to get the geometry of a canvas in tkinter...so how do I change the size.
# display the entry boxes and button
width_entry.pack()
height_entry.pack()
apply_button.pack()
# start the tk mainloop
root.mainloop()
Please Assist me
The command you are looking for is canvas.config
Here, I have adjusted the given code:
import tkinter as tk
# create root window
root = tk.Tk()
# Create Canvas
canvas = tk.Canvas(root, width=50, height=50)
canvas.pack()
# Create an additional window (the one that is used to enter the new geometry)
dialog = tk.Toplevel(root)
# Add entry widgets for width and height to the new window
width_entry = tk.Entry(dialog)
height_entry = tk.Entry(dialog)
# Add a button to the new window that applies the given width and height
apply_button = tk.Button(dialog, text = 'Apply geometry', command = lambda: canvas.config(width=width_entry.get(), height=height_entry.get()))
# display the entry boxes and button
width_entry.pack()
height_entry.pack()
apply_button.pack()
# start the tk mainloop
root.mainloop()
I also changed a couple other things:
You imported * from tkinter, but for some items you still led with tk.; I changed them all to match that and switched the import to match as well. (You could still use *, but then just don't have the leading tk.s.)
The canvas was never packed so you could never see what was going on there.
One more suggestion, that line where you make the button is really long. Maybe make a function that does what the lambda does and assign its command to that function instead of a lambda. You can probably see that a line that long is even hard to read here much less if someone (maybe a future version of yourself) was to try to read your code, and edit it or make sense of it. Generally, try to keep all lines down to 80 characters.
Let us know if you have any more questions etc.

Tkinter: I can't highlight text in text widget

So I made a text editor using tkinter and I used tag_config to highlight the syntax.
CODE
#Importing modules
from tkinter import *
#Main Window
Window = Tk()
Window.minsize(400, 550)
##Main Script
#Defs
#Main frame
main = Frame(Window)
#Main text widget
text = Text(main, bd=0, highlightthickness=0, borderwidth=0, bg="#323232", fg="white")
#Configs
text.config(width=55, height=35)
main.config(width=55, height=35)
#Tag config for coloring syntax
text.tag_configure("import", foreground="yellow")
Window.update()
#Packs and places
#main.place(anchor="c", rely=.5, relx=.5)
main.pack(expand=True, fill=BOTH, side="right")
text.pack(expand=True, fill=BOTH)
#Update window
Window.update()
#Window.mainloop()
Window.mainloop()
PROBLEM
The tag_configure is not working in line 23
text.tag_configure("import", foreground="yellow")
QUESTION
Is there a way to fix that? or Is there any way to highlighting text in tkinter?
EDIT
I add
def check_syntax(event):
text.tag_add('import', 1.0, END)
text.bind("<Return>", check_syntax)
on the code but there are 1 problem, when i run the code and type
import tkinter in the text widget for test and press enter the "tkinter" is highlighted too
How to fix that?
I believe the reason is that you need to actually add a tag first using the tag_add function. You should read this other question with a similar problem. I tried out the code myself and it works. (You'll have to press enter after completing a line)
How to use tkinter tag_config? Python 3.7.3
tag_configure only configures a tag, it doesn't apply the tag to a range of text. To use the tag you need to call tag_add and give it a start and end index. That, or add the tag when calling insert.
For example, this shows how to insert some text, and then apply highlighting to a few characters:
text.insert("end", "import foo\nimport bar\n")
text.tag_add("import", "1.0", "1.6")
text.tag_add("import", "2.0", "2.6")

Tkinter: disable text widget content auto resize (newline), when user resize window

Advice: i'm working on Windows 8.1, with Python and Tkinter at last version; i wrote from tkinter import * to post less code here, i know that it is a bad practice, use for example import tkinter as tk instead.
I'm coding my first text editor, and i have a problem when i resize the main windows. When i run the program it display on screen a window with dimension 750x500 pixel. So far, all ok, i can write text without problem (note that menu_bar and other features are work-in progress, but we dont care about them). Problem is with Text widget when user tries to resize window with cursor. The content of the text practically adapts to the size of the window (the length of each string is reduced or increased based on the width of the window). But i don't want that this happen. I want that Text widget changes his width automatically in base of window size, but the content mustn't be adapted. I hope that you understand my question, if not, i will try to explain better.
I have searched on online reference if there's a parameter to set this option, but i haven't found anything.
How to solve the problems concerning the Text widget and resizing the window?
from tkinter import *
root = Tk()
root.geometry("750x500")
content_text = Text(root, wrap=WORD, bg="grey25", undo=True, cursor="",
insertbackground="red", foreground="white", font="courier 12")
content_text.pack(fill=BOTH, expand=True)
scroll_bar = Scrollbar(content_text)
content_text.configure(yscrollcommand=scroll_bar.set, selectbackground="dodgerblue")
scroll_bar.configure(command=content_text.yview)
scroll_bar.pack(side=RIGHT, fill=Y)
if __name__ == '__main__':
root.mainloop()
You can't do what you want. If you have wrapping turned on, text will always wrap at the edge of the window. When you change the width of the window, the text will re-wrap to the new width. There is no configuration option to tell the widget to wrap at any other place.

Create resizable/multiline Tkinter/ttk Labels with word wrap

Is it possible to create a multi-line label with word wrap that resizes in sync with the width of its parent? In other words the wordwrap behavior of Notepad as you change the width of the NotePad window.
The use case is a dialog that needs to present a block of multi-line text (instructions) in its entirety without having the text clipped or resorting to scrollbars. The parent container will have enough vertical space to accomodate narrow widths.
I've been experimenting with Tkinter Label and Message widgets and the ttk Label widget without success. It seems that I need to hard code a pixel wraplength value vs. have these controls auto wordwrap when their text reaches the right edge of their containers. Certainly Tkinters geometry managers can help me auto-resize my labels and update their wraplength values accordingly?
Should I be looking at the Text widget instead? If so, is it possible to hide the border of a Text widget so I can use it as a multi-line label with wordwrap?
Here's a prototype of how one might do what I described above. It was inspired by Bryan Oakley's tip to use the Text widget and the following post on Stackoverflow:
In python's tkinter, how can I make a Label such that you can select the text with the mouse?
from Tkinter import *
master = Tk()
text = """
If tkinter is 8.5 or above you'll want the selection background to appear like it does when the widget is activated. Comment this out for older versions of Tkinter.
This is even more text.
The final line of our auto-wrapping label that supports clipboard copy.
""".strip()
frameLabel = Frame( master, padx=20, pady=20 )
frameLabel.pack()
w = Text( frameLabel, wrap='word', font='Arial 12 italic' )
w.insert( 1.0, text )
w.pack()
# - have selection background appear like it does when the widget is activated (Tkinter 8.5+)
# - have label background color match its parent background color via .cget('bg')
# - set relief='flat' to hide Text control borders
# - set state='disabled' to block changes to text (while still allowing selection/clipboard copy)
w.configure( bg=master.cget('bg'), relief='flat', state='disabled' )
mainloop()
Use Message widget:
The Message widget is a variant of the Label, designed to display multiline messages. The message widget can wrap text, and adjust its width to maintain a given aspect ratio.
No, there is no feature built-in to Tk to auto-word-wrap labels. However, it's doable by binding to the <Configure> event of the label and adjusting the wrap length then. This binding will fire every time the label widget is resized.
The other option, as you suggest, is to use a text widget. It is possible to entirely turn off the border if you so desire. This has always been my choice when I want word-wrapped instructional text.
Here is the code:
entry = Label(self, text=text,
anchor=NW, justify=LEFT,
relief=RIDGE, bd=2)
def y(event, entry=entry):
# FIXME: make this a global method, to prevent function object creation
# for every label.
pad = 0
pad += int(str(entry['bd']))
pad += int(str(entry['padx']))
pad *= 2
entry.configure(wraplength = event.width - pad)
entry.bind("<Configure>", y )
The tkinter.Message widget suggested by some people does NOT use TTK styling, which means that it's gonna look like garbage inside a TTK (themed) interface.
You could manually apply the background and foreground colors from your TTK theme to the tkinter.Message (by instantiating ttk.Style() and requesting the active themes' TLabel foreground and background colors from that style object), but it's not worth it... because the ancient Message widget has ZERO advantages over TTK's regular ttk.Label.
The tkinter.Message widget has an "aspect ratio" property that defines how many pixels until it wraps.
The ttk.Label instead has a wraplength= property which determines how many pixels until the words wrap. You should also use its anchor= and justify= properties to customize it to your exact desires. With these properties you can make your Label behave as the old Message widget did.
Example: ttk.Label(root, text="foo", wraplength=220, anchor=tkinter.NW, justify=tkinter.LEFT). Creates a beautifully styled label which permanently wraps its text after 220 pixels wide.
As for automatically updating the wraplength? Well, you should attach to the <Configure> event as people have said... However, if you have a completely fluid window (which resizes itself to fit all content), or a grid/frame that is fluid and contains the label, then you can't automatically calculate it that way, because the parent WINDOW/CONTAINER itself will EXPAND whenever the label grows too wide. Which means that the label will always resize itself to the maximum width it would need to fit all text. So, updating wraplength automatically is only possible if the label itself has some constraints on how wide it can grow (either via its parent container being a fixed size/maxsize, or itself being a fixed size/maxsize). In that case, sure, you can use configure to calculate new wrapping numbers to make sure the text always wraps... However, the example code by t7ko is broken and not valid anymore, just fyi.

Categories