прокрутка Python / Tkinter - PullRequest
       11

прокрутка Python / Tkinter

0 голосов
/ 13 июня 2019

У меня есть скрипт Python, который создает окно, отображающее сетку чисел с вертикальной полосой прокрутки. У меня проблема в том, что прокрутка прерывистая, а не плавная. Есть ли способ преодолеть это? Пример теста:

import tkinter as tk

class list_window(tk.Toplevel):

  def __init__(self, title, *args, **kwargs):
    tk.Toplevel.__init__(self, None, *args, **kwargs)
    self.title(title)

    self.geometry('1500x600')

    self.outer_frame=tk.Frame(self)

    canvas=tk.Canvas(self.outer_frame)
    self.list_frame=tk.Frame(canvas)
    scrollbar = tk.Scrollbar (self.outer_frame,orient="vertical",command=canvas.yview)
    canvas.configure(yscrollcommand=scrollbar.set, yscrollincrement=10)

    def scrollhelper(event):
      canvas.configure(scrollregion=canvas.bbox("all"))
    self.list_frame.bind("<Configure>",scrollhelper)

    self.outer_frame.pack(side="top",fill="both",expand=1)
    scrollbar.pack(side="right",fill="y")
    canvas.pack(side="left",fill="both",expand=1)
    canvas.create_window((0,0),window=self.list_frame,anchor='nw')

    #Fill with a bunch of widgets, for example
    import random
    for i in range(1000):
      for j in range(10):
        tk.Label(self.list_frame, text=str(random.random())).grid(row=i, column=j)

def spawn_list_window():
  win = list_window("My list window")

root = tk.Tk()
win = list_window("My List")
root.mainloop()

1 Ответ

2 голосов
/ 13 июня 2019
import tkinter as tk

from tkinter import ttk    

class Treeview(ttk.Treeview):
    def __init__(self, master, headings: list, col_widths: list = None, binds: dict = None):
        super().__init__(master=master, columns=headings, show="headings")

        self.col_widths = [] if col_widths is None else col_widths

        self.scroll = ttk.Scrollbar(self)

        self.configure(yscrollcommand=self.scroll.set)
        self.scroll.configure(command=self.yview)

        # Bind events to commands
        if isinstance(binds, dict):
            for k, v in binds.items():
                try:
                    self.bind(f"<{k}>", v)
                except tk.TclError:
                    self.bind(f"{k}", v)

        self.reset()

        self.scroll.pack(side=tk.RIGHT, fill=tk.Y)

    # Append rows to the treeview
    def populate(self, data, top_down=False):
        for i, d in enumerate(data):
            self.insert("", 0 if top_down else "end", values = d)

    # Clears the entire tree
    def clear(self):
        self.delete(*self.get_children())

    def reset(self):           
        for i, col in enumerate(self["columns"]):
            self.heading(col, text=col)

            if i < len(self.col_widths):
                self.column(col, minwidth=self.col_widths[i], width=self.col_widths[i], stretch=tk.NO)

    # Returns the first value which was selected
    def one(self):
        try:
            item = self.item(self.selection()[0])["values"]
        except IndexError:  # Normally this happens if the item selected is the column header
            return None
        else:
            return item

То, что вы пытаетесь сделать, проще всего сделать с помощью ttk.Treeview. Приведенный выше класс является оберткой вокруг него, которую я использую всякий раз, когда мне это нужно.

Приведенный ниже код является примером использования.

root = tk.Tk()

tree = Treeview(root, [f"Heading {i+1}" for i in range(10)])

data = []
for i in range(1000):
    data.append([])
    for j in range(10):
        data[-1].append(random.random())

tree.populate(data)   

tree.pack(expand=True, fill=tk.BOTH)

root.mainloop()
...