如何实现 tkinter 滚动条? [英] How to implement tkinter scrollbars?

查看:103
本文介绍了如何实现 tkinter 滚动条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力使用我的代码来实现水平和垂直滚动条以显示数据框的值.我有两个框架/画布,第一个用于标题,第二个用于值.

I'm struggling with my code to implement horizontal and vertical scrollbars to display the values of a dataframe. I have two frames/canvas, the first for the headers, the second for the values.

到目前为止,我的代码显示了数据框,但我无法正确完成滚动条.此外,我希望我的水平滚动条同时影响两个 Canevas,以便我的值和标题一起滚动.但显然标题不能随垂直滚动条滚动(标题应始终保持可见).

So far, my code displays the dataframe but I can't finalize the scrollbars properly. Also, I would like my horizontal scrollbar to effect both canevas, so that my values and headers scroll together. But obviously the headers must not scroll with the vertical scrollbar (headers shall always remain visible).

顺便说一句:如果有一个比 tkinter 更好的库来实现一个完全可操作的网格,以及它周围的所有常用功能,我很感兴趣:)

Btw : if there's a better library than tkinter to implement a fully operational grid, with all the usual features around it, I'm interested :)

这是我的代码:

import tkinter as tk
import pandas as pd

df = pd.DataFrame(columns=["header_"+str(i+1) for i in range(10)],
                  data=[["value_"+str(j*10+i+1) for i in range(10)] for j in range(10)])

root = tk.Tk()
root.geometry("1000x500+300+300")

label = tk.Label(root, text="My Label")
label.grid(row=0, column=0, padx=2, sticky=tk.NW)

frame1 = tk.Frame(root)
frame1.grid(row=1, column=0, sticky=tk.NW)

frame2 = tk.Frame(root)
frame2.grid(row=2, column=0, sticky=tk.NW)

canvas1 = tk.Canvas(frame1)
canvas1.grid(row=0, column=0)

canvas2 = tk.Canvas(frame2)
canvas2.grid(row=0, column=0)

# Headers in canvas1
for i in range(df.shape[1]):
    label = tk.Label(canvas1, padx=7, pady=7, borderwidth=1, relief=tk.SOLID, width=10, height=2, text=df.columns[i])
    label.grid(row=0, column=i, sticky='news')

# Values in canvas2
for i in range(df.shape[0]):
    for j in range(df.shape[1]):
        label = tk.Label(canvas2, padx=7, pady=7, borderwidth=1, relief=tk.SOLID, width=10, height=2, text=df.iloc[i, j])
        label.grid(row=i, column=j, sticky='news')

# Create a horizontal scrollbar linked to canvas2
hsbar = tk.Scrollbar(canvas2, orient=tk.HORIZONTAL, command=canvas2.xview)
hsbar.grid(row=1, column=0, sticky=tk.EW)
canvas2.configure(xscrollcommand=hsbar.set)

# Create a vertical scrollbar linked to canvas2
vsbar = tk.Scrollbar(canvas2, orient=tk.VERTICAL, command=canvas2.yview)
vsbar.grid(row=0, column=1, sticky=tk.NS)
canvas2.configure(yscrollcommand=vsbar.set)

root.mainloop()

我取得了一些进展.tk.Scrollbar的第一个参数有错误(canvas2代替frame2,固定两行)我还在代码中添加了最后一块,用canvas2窗口管理和bbox.它正在工作,但我需要更多时间&解释以完全理解它.欢迎对代码的最后一部分提出任何意见.

EDIT : I made some progress. There was a mistake in the first parameter of tk.Scrollbar (canvas2 instead of frame2, two lines fixed) and I also added the last block in the code, with the canvas2 window management and bbox. It's working but I need some more time & explanations to understand it fully. Any comment on this last part of the code would be welcome.

代码现在是:

import tkinter as tk
import pandas as pd

df = pd.DataFrame(columns=["header_"+str(i+1) for i in range(10)],
                  data=[["value_"+str(j*10+i+1) for i in range(10)] for j in range(10)])

root = tk.Tk()
root.geometry("1000x500+300+300")
root.title("Scrollable Canvas")

label = tk.Label(root, text="My Label")
label.grid(row=0, column=0, padx=2, sticky=tk.NW)

frame1 = tk.Frame(root)
frame1.grid(row=1, column=0, sticky=tk.NW)

canvas1 = tk.Canvas(frame1)
canvas1.grid(row=0, column=0)

# Headers in canvas1
for i in range(df.shape[1]):
    label = tk.Label(canvas1, padx=7, pady=7, borderwidth=1, relief=tk.SOLID, width=10, height=2, text=df.columns[i])
    label.grid(row=0, column=i, sticky='news')

# Create a frame for the canvas2 and scrollbars
frame2 = tk.Frame(root)
frame2.grid(row=2, column=0, sticky=tk.NW)

# Add a canvas2 in that frame
canvas2 = tk.Canvas(frame2)
canvas2.grid(row=0, column=0)

# Create a vertical scrollbar linked to canvas2
vsbar = tk.Scrollbar(frame2, orient=tk.VERTICAL, command=canvas2.yview)
vsbar.grid(row=0, column=1, sticky=tk.NS)
canvas2.configure(yscrollcommand=vsbar.set)

# Create a horizontal scrollbar linked to canvas2
hsbar = tk.Scrollbar(frame2, orient=tk.HORIZONTAL, command=canvas2.xview)
hsbar.grid(row=1, column=0, sticky=tk.EW)
canvas2.configure(xscrollcommand=hsbar.set)

# Create a frame on canvas2 to contain the labels
labels_frame = tk.Frame(canvas2)

# Add the labels to this frame
for i in range(df.shape[0]):
    for j in range(df.shape[1]):
        label = tk.Label(labels_frame, padx=7, pady=7, borderwidth=1, relief=tk.SOLID, width=10, height=2, text=df.iloc[i, j])
        label.grid(row=i, column=j, sticky='news')

# Create canvas2 window to hold the label_frame
canvas2.create_window((0,0), window=labels_frame, anchor=tk.NW)

labels_frame.update_idletasks()  # Needed to make bbox info available
bbox = canvas2.bbox(tk.ALL)  # Get bounding box of canvas2
w, h = bbox[2]-bbox[1], bbox[3]-bbox[1]
canvas2.configure(scrollregion=bbox, width=min(800, w), height=min(400, h))

root.mainloop()

推荐答案

我终于想出了一个全新的解决方案,树视图.代码并不完美,但它可以运行并且非常有前途:

I finally came up with a brand new solution, with treeview. The code is not perfect but it runs and is very promising :

import tkinter as tk
import pandas as pd

df = pd.DataFrame(columns=["header_"+str(i+1) for i in range(20)],
                  data=[["value_"+str(j*20+i+1) for i in range(20)] for j in range(100)])

win = tk.Tk()
win.geometry("1000x500+300+300")

frame = tk.Frame()
frame.pack(fill='both', expand=True)

# Create a Treeview with dual Scrollbars
tree = tk.ttk.Treeview(frame, show="headings", columns=df.columns)
hsb = tk.Scrollbar(frame, orient="horizontal", command=tree.xview)
vsb = tk.Scrollbar(frame, orient="vertical", command=tree.yview)
tree.configure(xscrollcommand=hsb.set, yscrollcommand=vsb.set)
tree.grid(column=0, row=0, sticky=tk.NSEW)
vsb.grid(column=1, row=0, sticky=tk.NS)
hsb.grid(column=0, row=1, sticky=tk.EW)
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)

for i, header in enumerate(df.columns):
    tree.column(i, width=100, anchor='center')
    tree.heading(i, text=header)
for row in range(df.shape[0]):
    tree.insert('', 'end', values=list(df.iloc[row]))

win.mainloop()

这篇关于如何实现 tkinter 滚动条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆