Tkinter의 위젯 그룹에 스크롤바 추가
저는 Python을 사용하여 로그 파일에서 항목을 구문 분석하고 Tkinter를 사용하여 항목 내용을 표시하고 있으며 지금까지 훌륭했습니다. 출력은 레이블 위젯의 그리드이지만 때때로 화면에 표시 할 수있는 것보다 더 많은 행이 있습니다. 매우 쉬울 것 같은 스크롤바를 추가하고 싶지만 알아낼 수 없습니다.
문서는 목록, 텍스트 상자, 캔버스 및 항목 위젯 만 스크롤바 인터페이스를 지원함을 의미합니다. 이들 중 어느 것도 위젯 그리드를 표시하는 데 적합하지 않은 것 같습니다. Canvas 위젯에 임의의 위젯을 넣을 수 있지만 절대 좌표를 사용해야하는 것 같아서 그리드 레이아웃 관리자를 사용할 수 없습니까?
위젯 그리드를 프레임에 넣으려고했지만 스크롤바 인터페이스를 지원하지 않는 것 같아서 작동하지 않습니다.
mainframe = Frame(root, yscrollcommand=scrollbar.set)
누구든지이 제한에 대한 방법을 제안 할 수 있습니까? 스크롤바를 추가하기 위해 PyQt에서 다시 작성하고 실행 가능한 이미지 크기를 너무 많이 늘려야하는 것을 싫어합니다!
개요
스크롤바는 몇 개의 위젯 및 루트 위젯에만 연결할 수 있으며 해당 위젯 Frame
그룹의 일부가 아닙니다.
가장 일반적인 해결책은 캔버스 위젯을 만들고 스크롤바를 해당 위젯과 연결하는 것입니다. 그런 다음 해당 캔버스에 레이블 위젯이 포함 된 프레임을 임베드하십시오. 프레임의 너비 / 높이를 결정하고 scrollregion
스크롤 영역이 프레임의 크기와 정확히 일치하도록 캔버스 옵션에 공급합니다 .
캔버스에 직접 텍스트 항목을 그리는 것은 그리 어렵지 않으므로 프레임에 포함 된 캔버스 솔루션이 너무 복잡해 보이는 경우 해당 접근 방식을 재고 할 수 있습니다. 그리드를 생성하기 때문에 각 텍스트 항목의 좌표는 계산하기가 매우 쉽습니다. 특히 각 행이 동일한 높이 (단일 글꼴을 사용하는 경우) 인 경우 더욱 그렇습니다.
캔버스에 직접 그리려면 사용중인 글꼴의 선 높이를 알아 내면됩니다 (그에 대한 명령이 있습니다). 그런 다음 각 y 좌표는 row*(lineheight+spacing)
입니다. x 좌표는 각 열에서 가장 넓은 항목을 기준으로 고정 된 숫자입니다. 모든 항목에 해당 열에 대한 태그를 지정하면 단일 명령으로 열에있는 모든 항목의 x 좌표와 너비를 조정할 수 있습니다.
객체 지향 솔루션
다음은 객체 지향 접근 방식을 사용하는 캔버스에 프레임 포함 솔루션의 예입니다.
import tkinter as tk
class Example(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
self.frame = tk.Frame(self.canvas, background="#ffffff")
self.vsb = tk.Scrollbar(root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill="both", expand=True)
self.canvas.create_window((4,4), window=self.frame, anchor="nw",
tags="self.frame")
self.frame.bind("<Configure>", self.onFrameConfigure)
self.populate()
def populate(self):
'''Put in some fake data'''
for row in range(100):
tk.Label(self.frame, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0)
t="this is the second column for row %s" %row
tk.Label(self.frame, text=t).grid(row=row, column=1)
def onFrameConfigure(self, event):
'''Reset the scroll region to encompass the inner frame'''
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == "__main__":
root=tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()
절차 적 솔루션
다음은 객체를 사용하지 않는 솔루션입니다.
import tkinter as tk
def populate(frame):
'''Put in some fake data'''
for row in range(100):
tk.Label(frame, text="%s" % row, width=3, borderwidth="1",
relief="solid").grid(row=row, column=0)
t="this is the second column for row %s" %row
tk.Label(frame, text=t).grid(row=row, column=1)
def onFrameConfigure(canvas):
'''Reset the scroll region to encompass the inner frame'''
canvas.configure(scrollregion=canvas.bbox("all"))
root = tk.Tk()
canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
frame = tk.Frame(canvas, background="#ffffff")
vsb = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=vsb.set)
vsb.pack(side="right", fill="y")
canvas.pack(side="left", fill="both", expand=True)
canvas.create_window((4,4), window=frame, anchor="nw")
frame.bind("<Configure>", lambda event, canvas=canvas: onFrameConfigure(canvas))
populate(frame)
root.mainloop()
참고 : Python 2.x에서이 작업을 수행 하려면 import 문 Tkinter
대신 사용 tkinter
하십시오.
스크롤 가능하게 만들기
이 편리한 클래스를 사용하여 위젯이 포함 된 프레임을 스크롤 가능하게 만드십시오. 이 단계를 따르세요:
- 프레임 만들기
- 표시 (팩, 그리드 등)
- 스크롤 가능하게
- 그 안에 위젯 추가
- update () 메서드 호출
import tkinter as tk
from tkinter import ttk
class Scrollable(tk.Frame):
"""
Make a frame scrollable with scrollbar on the right.
After adding or removing widgets to the scrollable frame,
call the update() method to refresh the scrollable area.
"""
def __init__(self, frame, width=16):
scrollbar = tk.Scrollbar(frame, width=width)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=False)
self.canvas = tk.Canvas(frame, yscrollcommand=scrollbar.set)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=self.canvas.yview)
self.canvas.bind('<Configure>', self.__fill_canvas)
# base class initialization
tk.Frame.__init__(self, frame)
# assign this obj (the inner frame) to the windows item of the canvas
self.windows_item = self.canvas.create_window(0,0, window=self, anchor=tk.NW)
def __fill_canvas(self, event):
"Enlarge the windows item to the canvas width"
canvas_width = event.width
self.canvas.itemconfig(self.windows_item, width = canvas_width)
def update(self):
"Update the canvas and the scrollregion"
self.update_idletasks()
self.canvas.config(scrollregion=self.canvas.bbox(self.windows_item))
사용 예
root = tk.Tk()
header = ttk.Frame(root)
body = ttk.Frame(root)
footer = ttk.Frame(root)
header.pack()
body.pack()
footer.pack()
ttk.Label(header, text="The header").pack()
ttk.Label(footer, text="The Footer").pack()
scrollable_body = Scrollable(body, width=32)
for i in range(30):
ttk.Button(scrollable_body, text="I'm a button in the scrollable frame").grid()
scrollable_body.update()
root.mainloop()
참조 URL : https://stackoverflow.com/questions/3085696/adding-a-scrollbar-to-a-group-of-widgets-in-tkinter
'programing' 카테고리의 다른 글
별도의 파일 / 스크립트를 쓰거나 스레딩하지 않고 하위 프로세스에서 함수를 실행할 수 있습니까? (0) | 2021.01.07 |
---|---|
'System.Int32'형식의 식은 'System.Object'반환 형식에 사용할 수 없습니다. (0) | 2021.01.07 |
Java 빌더 패턴에 해당하는 Scala는 무엇입니까? (0) | 2021.01.07 |
gdb에서 바이너리 모드로 인쇄하는 방법은 무엇입니까? (0) | 2021.01.07 |
Meteor로 다중 페이지 응용 프로그램을 어떻게 생성합니까? (0) | 2021.01.07 |