带网格的 tkinter 画布滚动条? [英] tkinter Canvas Scrollbar with Grid?

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

问题描述

Tkinter 和 Python 相对较新.所以请多多包涵.

我正在尝试显示以下 GUI,并希望在 Frame2 中有一个滚动条,以便一次仅显示 5x5 按钮.看起来 Tkinter 框架不支持滚动条,因此在父框架FMas"中添加了一个画布(框架嵌入其中)和一个滚动条.但出于某种原因,滚动条转到屏幕的右端并且不进行任何滚动.

画布不应该在Frame2的边缘结束,滚动条就在它旁边吗?此外,我尝试 rowspan 增加滚动条的高度以匹配 5x5 按钮的高度.这也行不通.

代码(使用 Python3.2):

from tkinter import *将 tkinter.ttk 导入为 ttkmGui = Tk()mGui.geometry("630x600")mGui.configure(背景=灰色")mGui.columnconfigure(0, weight=1)mGui.rowconfigure(0, weight=1)FMas = Frame(mGui, bg="Gray")FMas.grid(粘性=(N,E,S,W))FMas.columnconfigure(0, weight=1)L1 = Label(FMas, text="第一帧内容")L1.grid(row=0, column=0, pady=5,sticky=(N,W))F1 = Frame(FMas, bg="Green", bd=2, 浮雕=GROOVE)F1.grid(row=1, column=0,sticky=(N,W))ChkBox1=IntVar()CB1 = Checkbutton(F1, text="StartCheckBox", variable=ChkBox1)CB1.grid(row=0,column=0,padx=2)L2 = Label(FMas, text="第 2 帧内容")L2.grid(row=2, column=0, pady=5,sticky=(N,W))Can1 = Canvas(FMas, bg="Yellow")Can1.grid(row=3, column=0,sticky=(N,W))F2 = Frame(Can1, bg="Blue", bd=2, 浮雕=GROOVE)F2.grid(row=0, column=0,sticky=(N,W))行 = 10对于范围内的我(1,行):对于范围内的 j(1,6):button = Button(F2, padx=7, pady=7, text="[%d,%d]" % (i,j))button.grid(row=i, column=j,sticky='news')vsbar = Scrollbar(FMas, orient="vertical", command=Can1.yview)vsbar.grid(row=3, column=1)Can1.configure(yscrollcommand=vsbar.set, scrollregion=Can1.bbox("all"))L3 = Label(FMas, text="第 3 帧内容")L3.grid(row=4, column=0, pady=5,sticky=(N,W))F3 = Frame(FMas, bg="Red", bd=2, 浮雕=GROOVE)F3.grid(row=5, column=0,sticky=(N,W))ChkBox2=IntVar()CB2 = Checkbutton(F3, text="EndCheckBox", variable=ChkBox2)CB2.grid(row=0,column=0,padx=2)mGui.mainloop()系统退出()

解决方案

滚动条的高度与按钮框架高度不匹配,因为你没有告诉它坚持南北 .grid(...,sticky='ns')

然后,这里描述了你想要实现的滚动行为:

将 tkinter 导入为 tk根 = tk.Tk()root.grid_rowconfigure(0, weight=1)root.columnconfigure(0, weight=1)frame_main = tk.Frame(root, bg=灰色")frame_main.grid(sticky='news')label1 = tk.Label(frame_main, text="Label 1", fg="green")label1.grid(row=0, column=0, pady=(5, 0), sticky='nw')label2 = tk.Label(frame_main, text="Label 2", fg="blue")label2.grid(row=1, column=0, pady=(5, 0), sticky='nw')label3 = tk.Label(frame_main, text="Label 3", fg="red")label3.grid(row=3, column=0, pady=5,sticky='nw')# 为画布创建一个具有非零行和列权重的框架frame_canvas = tk.Frame(frame_main)frame_canvas.grid(row=2, column=0, pady=(5, 0), sticky='nw')frame_canvas.grid_rowconfigure(0, weight=1)frame_canvas.grid_columnconfigure(0, weight=1)# 将 grid_propagate 设置为 False 以允许 5×5 按钮稍后调整大小frame_canvas.grid_propagate(假)# 在该框架中添加一个画布canvas = tk.Canvas(frame_canvas, bg=黄色")canvas.grid(row=0, column=0,sticky=新闻")# 将滚动条链接到画布vsb = tk.Scrollbar(frame_canvas, orient=vertical", command=canvas.yview)vsb.grid(row=0, column=1,sticky='ns')canvas.configure(yscrollcommand=vsb.set)# 创建一个包含按钮的框架frame_buttons = tk.Frame(canvas, bg=blue")canvas.create_window((0, 0), window=frame_buttons, anchor='nw')# 向框架添加 9×5 按钮行数 = 9列 = 5按钮 = [[tk.Button() for j in range(columns)] for i in range(rows)]对于范围内的 i(0,行):对于范围内的 j(0,列):按钮[i][j] = tk.Button(frame_buttons, text=(%d,%d"% (i+1, j+1)))button[i][j].grid(row=i, column=j,sticky='news')# 更新按钮帧空闲任务让 tkinter 计算按钮大小frame_buttons.update_idletasks()# 调整画布框架的大小以准确显示 5×5 按钮和滚动条first5columns_width = sum([buttons[0][j].winfo_width() for j in range(0, 5)])first5rows_height = sum([buttons[i][0].winfo_height() for i in range(0, 5)])frame_canvas.config(width=first5columns_width + vsb.winfo_width(),高度=first5rows_height)# 设置画布滚动区域canvas.config(scrollregion=canvas.bbox(all"))# 启动图形界面root.mainloop()

Relatively new to Tkinter and Python. So kindly bear with me.

I am trying to display the following GUI and want to have a scrollbar in Frame2 to display only 5x5 buttons at a time. Looks like Tkinter Frames don't support scrollbar and hence added a canvas (within which the frame is embedded) and a scrollbar in the parent frame 'FMas'. But for some reason the scroll bar goes to the right end of the screen and doesn't do any scrolling.

Shouldn't the canvas end at the edge of the Frame2 and the scroll bar be right next to it? Also, I tried rowspan to increase the height of the scrollbar to match the height of 5x5 buttons. That too doesn't work.

CODE (Using Python3.2):

from tkinter import *
import tkinter.ttk as ttk

mGui = Tk()

mGui.geometry("630x600")
mGui.configure(background="Gray")

mGui.columnconfigure(0, weight=1)
mGui.rowconfigure(0, weight=1)

FMas = Frame(mGui, bg="Gray")
FMas.grid(sticky=(N,E,S,W))

FMas.columnconfigure(0, weight=1)

L1 = Label(FMas, text="Frame 1 Contents")
L1.grid(row=0, column=0, pady=5, sticky=(N,W))

F1 = Frame(FMas, bg="Green", bd=2, relief=GROOVE)
F1.grid(row=1, column=0, sticky=(N,W))

ChkBox1=IntVar()
CB1 = Checkbutton(F1, text="StartCheckBox", variable=ChkBox1)
CB1.grid(row=0,column=0,padx=2)

L2 = Label(FMas, text="Frame 2 Contents")
L2.grid(row=2, column=0, pady=5, sticky=(N,W))

Can1 = Canvas(FMas, bg="Yellow")
Can1.grid(row=3, column=0, sticky=(N,W))

F2 = Frame(Can1, bg="Blue", bd=2, relief=GROOVE)
F2.grid(row=0, column=0, sticky=(N,W))

rows = 10
for i in range(1,rows):
    for j in range(1,6):
        button = Button(F2, padx=7, pady=7, text="[%d,%d]" % (i,j))
        button.grid(row=i, column=j, sticky='news')

vsbar = Scrollbar(FMas, orient="vertical", command=Can1.yview)
vsbar.grid(row=3, column=1)

Can1.configure(yscrollcommand=vsbar.set, scrollregion=Can1.bbox("all"))

L3 = Label(FMas, text="Frame 3 Contents")
L3.grid(row=4, column=0, pady=5, sticky=(N,W))

F3 = Frame(FMas, bg="Red", bd=2, relief=GROOVE)
F3.grid(row=5, column=0, sticky=(N,W))

ChkBox2=IntVar()
CB2 = Checkbutton(F3, text="EndCheckBox", variable=ChkBox2)
CB2.grid(row=0,column=0,padx=2)

mGui.mainloop()
sys.exit()

解决方案

The height of your scrollbar didn't match the buttons frame height because you did't tell it to stick North and South .grid(..., sticky='ns')

Then, the scrolling behavior you want to achieve is described here: Adding a Scrollbar to a group of widgets

See also @martineau's answer for a more general object-oriented solution with 2D scrolling (horizontal & vertical)

import tkinter as tk

root = tk.Tk()
root.grid_rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)

frame_main = tk.Frame(root, bg="gray")
frame_main.grid(sticky='news')

label1 = tk.Label(frame_main, text="Label 1", fg="green")
label1.grid(row=0, column=0, pady=(5, 0), sticky='nw')

label2 = tk.Label(frame_main, text="Label 2", fg="blue")
label2.grid(row=1, column=0, pady=(5, 0), sticky='nw')

label3 = tk.Label(frame_main, text="Label 3", fg="red")
label3.grid(row=3, column=0, pady=5, sticky='nw')

# Create a frame for the canvas with non-zero row&column weights
frame_canvas = tk.Frame(frame_main)
frame_canvas.grid(row=2, column=0, pady=(5, 0), sticky='nw')
frame_canvas.grid_rowconfigure(0, weight=1)
frame_canvas.grid_columnconfigure(0, weight=1)
# Set grid_propagate to False to allow 5-by-5 buttons resizing later
frame_canvas.grid_propagate(False)

# Add a canvas in that frame
canvas = tk.Canvas(frame_canvas, bg="yellow")
canvas.grid(row=0, column=0, sticky="news")

# Link a scrollbar to the canvas
vsb = tk.Scrollbar(frame_canvas, orient="vertical", command=canvas.yview)
vsb.grid(row=0, column=1, sticky='ns')
canvas.configure(yscrollcommand=vsb.set)

# Create a frame to contain the buttons
frame_buttons = tk.Frame(canvas, bg="blue")
canvas.create_window((0, 0), window=frame_buttons, anchor='nw')

# Add 9-by-5 buttons to the frame
rows = 9
columns = 5
buttons = [[tk.Button() for j in range(columns)] for i in range(rows)]
for i in range(0, rows):
    for j in range(0, columns):
        buttons[i][j] = tk.Button(frame_buttons, text=("%d,%d" % (i+1, j+1)))
        buttons[i][j].grid(row=i, column=j, sticky='news')

# Update buttons frames idle tasks to let tkinter calculate buttons sizes
frame_buttons.update_idletasks()

# Resize the canvas frame to show exactly 5-by-5 buttons and the scrollbar
first5columns_width = sum([buttons[0][j].winfo_width() for j in range(0, 5)])
first5rows_height = sum([buttons[i][0].winfo_height() for i in range(0, 5)])
frame_canvas.config(width=first5columns_width + vsb.winfo_width(),
                    height=first5rows_height)

# Set the canvas scrolling region
canvas.config(scrollregion=canvas.bbox("all"))

# Launch the GUI
root.mainloop()

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

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