目的
左側に「行番号専用 Treeview」、右側に「データ用 Treeview」を置き、縦スクロールを同期させます。
コード(抜粋・最小版)
import tkinter as tk
from tkinter import ttk, filedialog
import csv
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("CSV Viewer")
self.geometry("1000x600")
wrap = ttk.Frame(self)
wrap.pack(fill=tk.BOTH, expand=True)
self.vscroll = ttk.Scrollbar(wrap, orient="vertical")
self.hscroll = ttk.Scrollbar(wrap, orient="horizontal")
self.left = ttk.Treeview(wrap, columns=("#",), show="headings", selectmode="none",
yscrollcommand=self.vscroll.set)
self.left.heading("#", text="#")
self.left.column("#", width=60, anchor="e", stretch=False)
self.right = ttk.Treeview(wrap, columns=(), show="headings",
yscrollcommand=self._on_right_yset,
xscrollcommand=self.hscroll.set)
self.left.grid(row=0, column=0, sticky="ns")
self.right.grid(row=0, column=1, sticky="nsew")
self.vscroll.grid(row=0, column=2, sticky="ns")
self.hscroll.grid(row=1, column=1, sticky="ew")
wrap.columnconfigure(1, weight=1)
wrap.rowconfigure(0, weight=1)
self.vscroll.config(command=self._on_yview)
self.hscroll.config(command=self.right.xview)
ttk.Button(self, text="Open CSV", command=self.open_csv).pack()
def _on_right_yset(self, first, last):
self.left.yview_moveto(first)
self.vscroll.set(first, last)
def _on_yview(self, *args):
self.left.yview(*args)
self.right.yview(*args)
def open_csv(self):
path = filedialog.askopenfilename(filetypes=[("CSV","*.csv")])
if not path: return
with open(path, newline="", encoding="utf-8") as f:
rows = list(csv.reader(f))
headers, data = rows[0], rows[1:]
self.right["columns"] = headers
for h in headers:
self.right.heading(h, text=h)
self.right.column(h, width=120, anchor="w", stretch=False)
self.left.delete(*self.left.get_children())
self.right.delete(*self.right.get_children())
for i, row in enumerate(data, start=1):
self.left.insert("", "end", values=(i,))
self.right.insert("", "end", values=row)
if __name__ == "__main__":
App().mainloop()
解説
- 行番号は別 Treeviewにすることで「横スクロールの影響を受けない固定列」になる
yview
を互いに呼ぶことで縦スクロール同期
前へ → 第2章
次へ → 第4章:列の表示/非表示(右サイドバー)