Tkinter: Show./Hide Specific Text in a Textbox - python

DESCRIPTION:
I have a textbox with text in it. See the image below.
QUESTION:
I want the highlighted text to hide when I click the "Hide" button. And then show the text, when I click the Show button (not there in the picture).
Similar to pack() and pack_forget(), but this time, for text and not widget.

You can add a tag to a region of text, and configure the tag with elide=True to hide the text, and set it to elide=False to show it.
Here's a little example:
import tkinter as tk
def hide():
text.tag_add("hidden", "sel.first", "sel.last")
def show_all():
text.tag_remove("hidden", "1.0", "end")
root = tk.Tk()
toolbar = tk.Frame(root)
hide_button = tk.Button(toolbar, text="Hide selected text", command=hide)
show_button = tk.Button(toolbar, text="Show all", command=show_all)
hide_button.pack(side="left")
show_button.pack(side="left")
text = tk.Text(root)
text.tag_configure("hidden", elide=True, background="red")
with open(__file__, "r") as f:
text.insert("end", f.read())
toolbar.pack(side="top", fill="x")
text.pack(side="top", fill="both", expand=True)
text.tag_add("sel", "3.0", "8.0")
root.mainloop()

Related

Unable to display buttons on the right hand side of the tkinter GUI

I'm trying to create a 800x800 GUI where on left hand side I need a treeview to later display data from MySQL, and on right hand side, I am struggling to display five buttons "Read Excel", "Invoice Per Order", "Save PDF", and "Close". Treeview is showing but no one button is visible at the moment. What should I do?
Here is my code:
import tkinter as tk
from tkinter import ttk
# Create the root window
root = tk.Tk()
root.geometry("800x800")
# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)
# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel")
invoice_per_order_button = tk.Button(root, text="Invoice per Order")
save_pdf_button = tk.Button(root, text="Save PDF")
close_button = tk.Button(root, text="Close")
# Place the buttons in a frame and pack the frame to the right of the root window
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack(side="top", in_=button_frame)
invoice_per_order_button.pack(side="top", in_=button_frame)
save_pdf_button.pack(side="top", in_=button_frame)
close_button.pack(side="top", in_=button_frame)
# Run the Tkinter event loop
root.mainloop()
You are using duplicated between line 18-25. You don't needed frame for pack()
Easier for you:
import tkinter as tk
from tkinter import ttk
# Create the root window
root = tk.Tk()
root.geometry("800x800")
# Create the treeview
treeview = ttk.Treeview(root)
treeview.pack(side="left", fill="both", expand=True)
# Create the buttons
read_excel_button = tk.Button(root, text="Read Excel").pack()
invoice_per_order_button = tk.Button(root, text="Invoice per Order").pack()
save_pdf_button = tk.Button(root, text="Save PDF").pack()
close_button = tk.Button(root, text="Close").pack()
# Run the Tkinter event loop
root.mainloop()
Output:
it works by removing parameters from .pack() methods on each button.
button_frame = tk.Frame(root)
button_frame.pack(side="right", fill="both")
read_excel_button.pack()
invoice_per_order_button.pack()
save_pdf_button.pack()
close_button.pack()

how to set value in Text widget in tkinter?

My problem: I can't display the value to Text widget when I select a row.
how can I display a value inside the Text widget from the selected row?
I tried using textvariable attribute in Text widget but its not working.
Use insert method of the Text widget. Minimal example:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
def add_text():
# text.delete(1.0, tk.END) # Uncomment if you need to replace text instead of adding
text.insert(tk.END, f"Some text\n")
tk.Button(root, text="Add text", command=add_text).pack()
root.mainloop()

Python Tkinter how can I place background text in a textbox?

I am trying to place a greyed out background text inside a textbox, that disappears when someone begins to type. I have tried overlaying a label onto the textbox, but I could not get it to work. Here is some code I am running for the text box
root = tk.Tk()
S = tk.Scrollbar(root)
T = tk.Text(root, height=70, width=50)
S.pack(side=tk.RIGHT, fill=tk.Y)
T.pack(side=tk.LEFT, fill=tk.Y)
S.config(command=T.yview)
T.config(yscrollcommand=S.set)
root.protocol("WM_DELETE_WINDOW", stop)
tk.mainloop()
How can I put in the background text?
Using a callback function you can remove the default text and change the foreground colour
import tkinter as tk
root = tk.Tk()
e = tk.Entry(root, fg='grey')
e.insert(0, "some text")
def some_callback(event): # must include event
e.delete(0, "end")
e['foreground'] = 'black'
# e.unbind("<Button-1>")
e.unbind("<FocusIn>")
return None
# e.bind("<Button-1>", some_callback)
e.bind("<FocusIn>", some_callback)
e.pack()
root.mainloop()
You are probably talking about placeholders , tkinter does not have placeholder attribute for Text widget, but you do something similar with Entry widget . You have to do it manually, by binding an event with the Text widget.
text = tk.StringVar()
text.set('Placeholder text')
T = tk.Entry(root, height=70, width=50, textvariable = text)
def erasePlaceholder(event):
if text.get() == 'Placeholder text':
text.set('')
T.bind('<Button-1>', erasePlaceholder)
Try to ask if you face any issues.

How to custom button and text box using Python GUI?

I would like to ask how to make a custom button and custom text box by using Python?
A custom button should has: transparent feature with only border, round corner, shadow feature, icon need to be placed, animate feature like color changed when click and hover on it.
A custom text box should has: no border but only underline, round corner, transparent feature, icon need to be placed, animate feature like underline becomes thicker when click on it.
Below is my code:
frame = tk.Frame(root, bg='#000000', bd=0)
frame.place(relx=0.5, rely=0.1, relwidth=0.75, relheight=0.1, anchor='n')
entry = tk.Entry(frame, font=60, relief='flat')
entry.place(relwidth=0.65, relheight=1)
button = tk.Button(frame, text="Run", relief='flat', font=40, command=lambda: get_weather(entry.get()))
button.place(relx=0.7, relheight=1, relwidth=0.3)
Here is the reference image design that I prefer:
Any help would be appreciated, thanks!
Tkinter comes with the module ttk which stands for themed tk. It provides a way to create widget themes.
How to do it is under-documented, but tkdocs.com has a good discussion of the fundamentals.
At the end of this question is code which can create frames that have rounded corners, a shadow, and a unique color to represent focus, to serve as an example of what you can do. Answering all your questions is a bit beyond the scope of what stackoverflow is for, but hopefully, this is enough to show that what you want is possible.
import tkinter as tk
from tkinter import ttk
focusBorderImageData = '''
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
Ry/99NIz//oGrZpUUEAAOw==
'''
borderImageData = '''
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
'''
root = tk.Tk()
style = ttk.Style()
borderImage = tk.PhotoImage("borderImage", data=borderImageData)
focusBorderImage = tk.PhotoImage("focusBorderImage", data=focusBorderImageData)
style.element_create("RoundedFrame",
"image", borderImage,
("focus", focusBorderImage),
border=16, sticky="nsew")
style.layout("RoundedFrame",
[("RoundedFrame", {"sticky": "nsew"})])
frame1 = ttk.Frame(style="RoundedFrame", padding=10)
text1 = tk.Text(frame1, borderwidth=0, highlightthickness=0, wrap="word",
width=40, height=4)
text1.pack(fill="both", expand=True)
text1.bind("<FocusIn>", lambda event: frame1.state(["focus"]))
text1.bind("<FocusOut>", lambda event: frame1.state(["!focus"]))
text1.insert("end", "This widget has the focus")
frame2 = ttk.Frame(style="RoundedFrame", padding=10)
text2 = tk.Text(frame2, borderwidth=0, highlightthickness=0, wrap="word",
width=40, height=4)
text2.pack(fill="both", expand=True)
text2.bind("<FocusIn>", lambda event: frame2.state(["focus"]))
text2.bind("<FocusOut>", lambda event: frame2.state(["!focus"]))
text2.insert("end", "This widget does not have the focus")
root.configure(background="white")
frame1.pack(side="top", fill="both", expand=True, padx=20, pady=20)
frame2.pack(side="top", fill="both", expand=True, padx=20, pady=20)
frame1.focus_set()
root.mainloop()
This code was originally posted as an answer to the question Tkinter: How to make a rounded corner text widget?. The original version of this code was written in Tcl in 2007, before stackoverflow existed.

Vertical scrollbar for frame in Tkinter, Python

My aim is to have a scrollbar that stays at the right-side of a full-screen window, allowing the user to scroll up and down through various different widgets (such as labels & buttons).
From other answers I've seen on this site, I've come to the conclusion that a scrollbar has to be assigned to a canvas in order for it to function properly, which I have tried to include in my code but have not had much success with.
The below code shows a simplified version of what I've managed to accomplish so far:
from tkinter import *
root = Tk()
root.state("zoomed")
root.title("Vertical Scrollbar")
frame = Frame(root)
canvas = Canvas(frame)
Label(canvas, text = "Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font = "-size 100").pack()
scrollbar = Scrollbar(frame)
scrollbar.pack(side = RIGHT, fill = Y)
canvas.configure(yscrollcommand = scrollbar.set)
canvas.pack()
frame.pack()
root.mainloop()
I'm facing two issues when running this code:
One is that the scrollbar is inactive, and doesn't allow for the user to scroll down to view the rest of the text.
The other is that the scrollbar is attached to the right-side of the text, rather than the right-side of the window.
So far, none of the other answers I've found on this site have enabled me to amend my code to support a fully-functioning scrollbar for my program. I'd be very grateful for any help anyone reading this could provide.
See again link: https://stackoverflow.com/a/3092341/7432
It shows how to create scrolled frame - and then you can add all widgets in this frame.
import tkinter as tk
def on_configure(event):
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.configure(scrollregion=canvas.bbox('all'))
root = tk.Tk()
# --- create canvas with scrollbar ---
canvas = tk.Canvas(root)
canvas.pack(side=tk.LEFT)
scrollbar = tk.Scrollbar(root, command=canvas.yview)
scrollbar.pack(side=tk.LEFT, fill='y')
canvas.configure(yscrollcommand = scrollbar.set)
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.bind('<Configure>', on_configure)
# --- put frame in canvas ---
frame = tk.Frame(canvas)
canvas.create_window((0,0), window=frame, anchor='nw')
# --- add widgets in frame ---
l = tk.Label(frame, text="Hello", font="-size 50")
l.pack()
l = tk.Label(frame, text="World", font="-size 50")
l.pack()
l = tk.Label(frame, text="Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font="-size 20")
l.pack()
# --- start program ---
root.mainloop()
I would recommend using tkScrolledFrame
https://pypi.org/project/tkScrolledFrame/
They have a great little example on the website too. So easy to use and works great for me.
Below is a quick example:
from tkscrolledframe import ScrolledFrame
import tkinter as tk
# Create a root window
root = tk.Tk()
frame_top = tk.Frame(root, width=400, height=250)
frame_top.pack(side="top", expand=1, fill="both")
# Create a ScrolledFrame widget
sf = ScrolledFrame(frame_top, width=380, height=240)
sf.pack(side="top", expand=1, fill="both")
# Bind the arrow keys and scroll wheel
sf.bind_arrow_keys(frame_top)
sf.bind_scroll_wheel(frame_top)
frame = sf.display_widget(tk.Frame)
l = tk.Label(frame, text="Test text 1\nTest text 2\nTest text 3\nTest text 4\nTest text 5\nTest text 6\nTest text 7\nTest text 8\nTest text 9", font="-size 20")
l.pack()
root.mainloop()

Categories