I am currently developping an application using tkinter and I struggle with a cosmetic issue. When adding an entry to a canvas, tkinter displays a selection cursor around the entry and the canvas. I would like to avoid this behavior for the canvas because I am using it to create a scrollable frame which create a very unpleasant effect, the selection being displayed only on the sides because the rest of the canvas is out of the screen.
I created a small code sample to experiment with this.
Here is the display without selection: without selection
Here is the display with the selection: with the selection
I would like to avoid having the dark grey rectangle around the canvas, would you please know how to do it?
Here is my code sample:
###########
# Imports #
###########
import tkinter as tk
from tkinter import ttk
#########
# Class #
#########
class ScrollableFrame(ttk.Frame):
def __init__(self, container, *args, **kwargs):
super().__init__(container, *args, **kwargs)
canvas = tk.Canvas(self, takefocus=0)
self.canvas = canvas
scrollbar = ttk.Scrollbar(self, orient="vertical", command=canvas.yview)
self.scrollable_frame = ttk.Frame(canvas, takefocus=0)
self.scrollable_frame.columnconfigure(index=0, weight=1)
self.scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
self.scrollable_frame_id = canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
self.canvas.bind('<Configure>', self.on_width_change)
canvas.pack(side="left", fill="both", expand=True)
scrollbar.pack(side="right", fill="y")
def on_mousewheel(self, event):
shift = (event.state & 0x1) != 0
scroll = -1 if event.delta > 0 else 1
if shift:
self.canvas.xview_scroll(scroll, "units")
else:
self.canvas.yview_scroll(scroll, "units")
def on_width_change(self, event):
canvas_width = event.width
self.canvas.itemconfig(self.scrollable_frame_id, width=canvas_width * 0.99)
def bind_tree(self, event, callback, widget=None):
"""
Binds an event to a widget and all its descendants.
"""
if widget is None:
widget = self
if isinstance(widget, ttk.Combobox):
return
widget.bind(event, callback, "")
for child in widget.children.values():
self.bind_tree(widget=child, event=event, callback=callback)
def bind_list(self, widgets, event, callback):
for widget in widgets:
self.bind_tree(widget=widget, event=event, callback=callback)
def set_mouse_scroll_on_list(self, widgets):
self.bind_list(widgets, "<MouseWheel>", self.on_mousewheel)
###########
# Process #
###########
root = tk.Tk()
frame = ScrollableFrame(root)
frame.grid(row=0,column=0,sticky="nsew")
entry = ttk.Entry(frame.scrollable_frame)
entry.pack()
root.mainloop()
It is caused by highlightthickness
not setting to zero. Set it to zero to fix it:
canvas = tk.Canvas(self, takefocus=0, highlightthickness=0)