Я делаю кубический таймер, и я хочу сделать таблицу, в которой вы можете видеть все свое время, включая его скремблирование, дату и другую информацию, используя текстовый виджет. Если вы вставляете пару раз, все работает нормально, но когда вы вставляете больше 50, вы не можете видеть в некоторых случаях. Итак, я использую полосу прокрутки на холсте. Я пытаюсь прокрутить холст вниз, когда вы используете полосу прокрутки, но, похоже, это не работает. Вот мой код.
class TimeTable(tk.Canvas):
"""Creates a time table using a tk.Canvas"""
def __init__(self, times, *args, **kwargs):
"""
:param times: list[CubeUtils.Time]
"""
# Initialize super class and define attributes
super().__init__(*args, **kwargs)
self.TIME_ATTRS = ["Time", "Scramble", "Date", "DNF"]
self.ScrollbarY = None
self.fullscreen = False
self.times = times
self.frame = self.nametowidget(self.winfo_parent())
self.parent = self.frame.nametowidget(self.frame)
self.config(height=len(self.times)*15)
self.frame.config(height=len(self.times)*15)
# Insert time attributes in entries
for column, attr in enumerate(self.TIME_ATTRS):
text = tk.Text(self, font=("Arial", 15, "bold"), width=50, height=1)
text.insert("0.0", attr)
text.config(state=tk.DISABLED)
text.grid(row=0, column=column+1, sticky=tk.E)
# Insert times
for time_count, time in enumerate(self.times):
time_info = [time_count+1, time.time, time.scramble, time.date, time.DNF]
if time_info[0] > 49 and self.ScrollbarY is None:
self.add_scrollbar()
time_info_font = ("Arial", 15, "bold")
for column, info in enumerate(time_info):
if isinstance(info, int) and not isinstance(info, bool):
text = tk.Text(self, font=time_info_font, width=2 if len(str(info)) <= 2 else len(str(info)), height=1, fg="#ff5000")
else:
text = tk.Text(self, font=time_info_font, width=50, height=1, fg="#ff5000")
text.insert("0.0", str(info))
text.grid(row=time_count + 1, column=column, sticky=tk.E)
text.config(state=tk.DISABLED)
# Bindings
self.parent.bind("<F11>", lambda key: self.toggle_fullscreen())
self.parent.bind("<Escape>", lambda key: self.exit_fullscreen())
self.parent.bind_all("<MouseWheel>", self.on_mousewheel)
Прокрутка
def on_mousewheel(self, event):
"""Scrolls the canvas using the mouse wheel"""
self.yview_scroll(int(-1 * (event.delta / 120)), "units")
def add_scrollbar(self):
"""Adds a scrollbar to the frame"""
self.config(scrollregion=self.bbox("all"))
self.ScrollbarY = tk.Scrollbar(self.frame)
self.config(yscrollcommand=self.ScrollbarY.set)
self.ScrollbarY.config(command=self.yview)
self.ScrollbarY.pack(side=tk.RIGHT, expand=True, fill=tk.BOTH)
Полный экран
def toggle_fullscreen(self):
"""Toggles fullscreen on and off"""
self.fullscreen = not self.fullscreen
self.parent.attributes("-fullscreen", self.fullscreen)
def exit_fullscreen(self):
"""Exists fullscreen"""
self.fullscreen = False
self.parent.attributes("-fullscreen", self.fullscreen)
Кстати, аргумент times должен быть списком с элементами типа Time, вот код для этого класса.
class Time:
"""Creates a time object that stores its time, scramble, date and whether or not it is a DNF"""
def __init__(self, time, scramble, date, DNF=False):
"""
:param time: float
:param scramble: str
:param date: datetime.datetime
:param DNF: bool
"""
if not isinstance(date, datetime.datetime):
raise TypeError("date parameter must be of type datetime.datetime")
if not isinstance(time, float):
raise TypeError("time parameter must be of type float")
if not isinstance(scramble, str):
raise TypeError("scramble parameter must be of type str")
if not isinstance(DNF, bool):
raise TypeError("DNF parameter must be of type bool")
self.time = time
self.scramble = scramble
self.date = datetime.datetime.strftime(date, "%Y-%m-%d-%I:%M %p")
self.DNF = DNF
Я пробовал читать веб-страницы на effbot.com и других сайтах о размещении полосы прокрутки на холсте, но ни один из них у меня не работает.
Edit: Благодаря acw1668 я закончил свой класс TimeTable, вот готовый код для этого
class TimeTable(tk.Frame):
"""Creates a time table using a tk.Canvas"""
def __init__(self, parent, times, *args, **kwargs):
"""
:param parent: tk.Tk()
:param times: list[CubeUtils.Time]
"""
# Initialize super class and define attributes
super().__init__(*args, **kwargs)
self.TIME_ATTRS = ["Time", "Scramble", "Date", "DNF"]
self.fullscreen = False
self.times = times
self.canvas = tk.Canvas(self)
self.frame = tk.Frame(self.canvas)
self.parent = parent
self.canvas.pack(fill=tk.BOTH, expand=True)
self.canvas.create_window(2, 2, window=self.frame, anchor="nw")
self.frame.bind("<Configure>", self.on_config)
self.parent.bind("<MouseWheel>", self.on_mousewheel)
self.parent.bind("<F11>", lambda event: self.toggle_fullscreen())
self.parent.bind("<Escape>", lambda event: self.exit_fullscreen())
self.populate()
def populate(self):
"""Populates the frame with the times"""
# Insert time attributes in text widgets
for column, attr in enumerate(self.TIME_ATTRS):
text = tk.Text(self.frame, font=("Arial", 15, "bold"), width=50, height=1)
text.insert("0.0", attr)
text.config(state=tk.DISABLED)
column += 4
text.grid(row=0, column=column)
# Insert times in text widgets
for time_count, time in enumerate(self.times):
time_info = [time_count + 1, time.time, time.scramble, time.date, time.DNF]
time_info_font = ("Arial", 15, "bold")
for column, info in enumerate(time_info):
if isinstance(info, int) and not isinstance(info, bool):
text = tk.Text(self.frame, font=time_info_font, width=2 if len(str(info)) <= 2 else len(str(info)),
height=1, fg="#ff5000")
else:
text = tk.Text(self.frame, font=time_info_font, width=50, height=1, fg="#ff5000")
text.insert("0.0", str(info))
row = time_count + 1
column += 3
text.grid(row=row, column=column, sticky=tk.E)
text.config(state=tk.DISABLED)
def on_config(self, event):
"""Reset the scroll region to encompass the inner frame"""
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def on_mousewheel(self, event):
"""Scrolls the canvas using the mouse wheel"""
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
def toggle_fullscreen(self):
"""Toggles fullscreen on and off"""
self.fullscreen = not self.fullscreen
self.parent.attributes("-fullscreen", self.fullscreen)
def exit_fullscreen(self):
"""Exists fullscreen"""
self.fullscreen = False
self.parent.attributes("-fullscreen", self.fullscreen)