2017-12-25 30 views
1

내 코드는 프레임, 프레임 안에 캔버스, 캔버스 안에 내부 프레임을 가지고 있습니다. Entry 위젯의 width 옵션을 사용하여 픽셀/글꼴 너비 변환을 피하기 위해 내부 프레임 안에 엔트리 박스를 넣고 내부 프레임에 맞춰야합니다. pack_propagate(0). 그러나 내부 프레임의 스크롤 기능이 손상됩니다. 나는 현재 pack(before=)을 사용하여 내부 프레임의 첫 번째 항목과 마지막 항목 위젯의 위와 아래에 동적으로 항목 위젯을 추가하려고합니다. 그래서 나는 가능하다면 포장자를 고수하고 싶습니다.왜 pack_propagate (0)을 선언 할 때 내부 프레임이있는 캔버스의 tkinter 스크롤 막대가 비활성화되어 있습니까?

어떻게하면 스크롤바가 다시 작동합니까?

import tkinter as tk 
import tkinter.ttk as ttk 

root = tk.Tk() 

myframe = ttk.Frame(root) 
myframe.pack() 
sb = ttk.Scrollbar(myframe) 
sb.pack(side=tk.RIGHT, fill=tk.Y, expand=1) 

canvas = tk.Canvas(myframe, width=200, height=300, 
        scrollregion=(0, 0, 200, 300), yscrollcommand=sb.set) 
canvas.pack() 
frame = ttk.Frame(canvas, width=200, height=300) # inner Frame 
canvas.create_window((0, 0), window=frame, anchor='nw') 
sb.config(command=canvas.yview) 

frame.bind("<Configure>", lambda event: canvas.configure(
    scrollregion=canvas.bbox(tk.ALL))) 
# frame.pack_propagate(0) # How to enable this and ensure scrollbar works? 

s = tk.StringVar() 
s.set("I'm a box") 
for _ in range(100): 
    eb = ttk.Entry(frame, textvariable=s) 
    eb.pack() 

root.mainloop() 

EDIT1 : StringVar()을 추가하고 내부 FrameCanvas에 크기를 조정하는 예제를 참조하십시오 eb.pack()

답변

0

eb.grid()을 변경 엔트리 위젯이 제대로 열 크기되지 않도록 다음과 같은 최소한의 작업 예 frame.pack_propagate(0)은, 주석있다 - 그것은

self._canvas.bind('<Configure>', self.inner_resize) 

를 사용하고있어서 내부 inner_resize()

,
self._canvas.itemconfig(self._window, width=event.width) 

전체 예를

import tkinter as tk 
import tkinter.ttk as ttk 

class ScrolledFrame(tk.Frame): 

    def __init__(self, parent, vertical=True, horizontal=False): 
     super().__init__(parent) 

     # canvas for inner frame 
     self._canvas = tk.Canvas(self, bg='red') 
     self._canvas.grid(row=0, column=0, sticky='news') # changed 

     # create right scrollbar and connect to canvas Y 
     self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview) 
     if vertical: 
      self._vertical_bar.grid(row=0, column=1, sticky='ns') 
     self._canvas.configure(yscrollcommand=self._vertical_bar.set) 

     # create bottom scrollbar and connect to canvas X 
     self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview) 
     if horizontal: 
      self._horizontal_bar.grid(row=1, column=0, sticky='we') 
     self._canvas.configure(xscrollcommand=self._horizontal_bar.set) 

     # inner frame for widgets 
     self.inner = tk.Frame(self._canvas) 
     self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw') 

     # autoresize inner frame 
     self.columnconfigure(0, weight=1) # changed 
     self.rowconfigure(0, weight=1) # changed 

     # resize when configure changed 
     self.inner.bind('<Configure>', self.resize) 

     # resize inner frame to canvas size 
     self.resize_width = False 
     self.resize_height = False 
     self._canvas.bind('<Configure>', self.inner_resize) 

    def resize(self, event=None): 
     self._canvas.configure(scrollregion=self._canvas.bbox('all')) 

    def inner_resize(self, event): 
     # resize inner frame to canvas size 
     if self.resize_width: 
      self._canvas.itemconfig(self._window, width=event.width) 
     if self.resize_height: 
      self._canvas.itemconfig(self._window, height=event.height) 

# --- main ---- 

root = tk.Tk() 

sf = ScrolledFrame(root) 
sf.resize_width = True # it will resize frame to canvas 
sf.pack(fill='both', expand=True) 

s = tk.StringVar() 
s.set("I'm a box") 

for _ in range(100): 
    eb = ttk.Entry(sf.inner, textvariable=s) 
    eb.pack(fill='x', expand=True) 

root.mainloop() 
+0

당신의 크리스마스 선물 주셔서 감사합니다! – Zhulu