2017-12-07 10 views
2

윈도우의 공간이 다 떨어질 때까지 첫 번째 행을 채우는 그리드가있는 그리드 레이아웃을 만들고 싶습니다. 아래 행에 항목을 동적으로 옮깁니다 (텍스트 줄 바꿈과 같이) . 창 너비가 조정되면 눈금이 맞게 조정됩니다. 크기를 조정하는 상자가 필요하지 않습니다. 각 작은 상자의 크기를 유지하려고하지만 레이아웃이 각 상자를 놓는 위치를 변경하십시오.Tkinter Grid 동적 레이아웃

프레임의 너비를 측정하여이 기능을 사용할 수 있다고 상상해보십시오. 상자의 수 * (각 상자의 너비)가 너비를 초과하면 다음 행으로 이동하십시오. 나는 내가 이해하지 못한다는 점에서 더 나은 방법이 만들어 졌는지 궁금했다.

위의 옵션 만있는 경우이를 업데이트하는 가장 좋은 방법은 무엇입니까? 창 크기 조정 등의 이벤트를 설정해야합니까? 레이아웃 관리자를 다시 고쳐야 할 필요가없는 것처럼 보입니다. 비슷한 기능이 이미 내장되어 있는지 확인하고 싶습니다. Grid는 강력한 레이아웃 관리자처럼 보이지만 그 옵션을 찾을 수 없었습니다.

아래 사진은 그리드 레이아웃을 사용하여 단일 프레임에 6 세트의 동일한 세트를 사용하여 원하는 동작을 설명합니다.

창은 여섯 개의 상자를 모두 수용 할 수있을 정도로 넓어서 행 1에 모두 맞습니다. 그런 다음 창 크기가 변경되면서 조정됩니다. 그것을 가지고 있기 때문에 enter image description here enter image description here

+1

tkinter에는 옵션이 없습니다. 당신이 말한 바로는해야 할 것입니다 : 창 크기를 모니터하고 필요에 따라 다시 레이아웃하십시오. 할 일이별로 없다. – Novel

+0

변경 사항에 대한 창 크기를 어떻게 모니터링해야합니까? 이 일에 어떤 부정적인 점이 있습니까? 권장되지 않는 경우 (내장되어 있지 않기 때문에), 다른 해결책을 찾을 수 있습니다. 그러나 이와 같은 일을하는 것이 상당히 표준적인 방법이라면 확실히 알 수 있습니다. – Tarm

+1

""이벤트를 사용하십시오. – Novel

답변

5

당신이 균일 한 크기로 각 상자를 강제하려는 경우 enter image description here

는, 가장 간단한 해결책은 컨테이너로 텍스트 위젯을 사용하는 것입니다 내장 된 포장 할 수있는 능력.

다음은 작동하는 예제입니다. 상자를 추가하려면 "추가"버튼을 클릭하십시오. 창 크기를 조정하여 창 크기가 커지고 축소 될 때 자동으로 감싸는 지 확인하십시오.

import Tkinter as tk 
import random 

class DynamicGrid(tk.Frame): 
    def __init__(self, parent, *args, **kwargs): 
     tk.Frame.__init__(self, parent, *args, **kwargs) 
     self.text = tk.Text(self, wrap="char", borderwidth=0, highlightthickness=0, 
          state="disabled") 
     self.text.pack(fill="both", expand=True) 
     self.boxes = [] 

    def add_box(self, color=None): 
     bg = color if color else random.choice(("red", "orange", "green", "blue", "violet")) 
     box = tk.Frame(self.text, bd=1, relief="sunken", background=bg, 
         width=100, height=100) 
     self.boxes.append(box) 
     self.text.configure(state="normal") 
     self.text.window_create("end", window=box) 
     self.text.configure(state="disabled") 

class Example(object): 
    def __init__(self): 
     self.root = tk.Tk() 
     self.dg = DynamicGrid(self.root, width=500, height=200) 
     add_button = tk.Button(self.root, text="Add", command=self.dg.add_box) 

     add_button.pack() 
     self.dg.pack(side="top", fill="both", expand=True) 

     # add a few boxes to start 
     for i in range(10): 
      self.dg.add_box() 

    def start(self): 
     self.root.mainloop() 

Example().start() 
+1

좋은 해결책. 실제로 불균등하게 크기가 조정 된 위젯이 최적으로 포장되는 것을 좋아합니다. – Novel

+0

나는이 해결책을 정말로 좋아한다! 매우 우아하고 단순합니다. 분명히 내가 원하는 것을 나에게 줄 수 있으며, 두려운 폭 측정을 피하기 때문에 이것을 해결책으로 표시 할 것입니다. 또한 @Novel이 언급했듯이, 크기가 불균일 한 상자도 똑같이 처리합니다 (미적으로는 그렇지는 않지만). 이쪽은 완벽합니다. 고마워요. – Tarm

4

여기에 동작하는 예제입니다 :

import Tkinter as tk 

class AutoGrid(tk.Frame): 
    def __init__(self, master=None, **kwargs): 
     tk.Frame.__init__(self, master, **kwargs) 
     self.columns = None 
     self.bind('<Configure>', self.regrid) 

    def regrid(self, event=None): 
     width = self.winfo_width() 
     slaves = self.grid_slaves() 
     max_width = max(slave.winfo_width() for slave in slaves) 
     cols = width // max_width 
     if cols == self.columns: # if the column number has not changed, abort 
      return 
     for i, slave in enumerate(slaves): 
      slave.grid_forget() 
      slave.grid(row=i//cols, column=i%cols) 
     self.columns = cols 

class TestFrame(tk.Frame): 
    def __init__(self, master=None, **kwargs): 
     tk.Frame.__init__(self, master, bd=5, relief=tk.RAISED, **kwargs) 

     tk.Label(self, text="name").pack(pady=10) 
     tk.Label(self, text=" info ........ info ").pack(pady=10) 
     tk.Label(self, text="data\n"*5).pack(pady=10) 

def main(): 
    root = tk.Tk() 
    frame = AutoGrid(root) 
    frame.pack(fill=tk.BOTH, expand=True) 

    TestFrame(frame).grid() # use normal grid parameters to set up initial layout 
    TestFrame(frame).grid(column=1) 
    TestFrame(frame).grid(column=2) 
    TestFrame(frame).grid() 
    TestFrame(frame).grid() 
    TestFrame(frame).grid() 
    root.mainloop() 

if __name__ == '__main__': 
    main() 

참고이는 ROWSPAN 그리드 관리자의 columnspan 기능을 파괴 할 것이다.

+0

코드를 테스트 한 결과 코드가 올바르게 작동하며 유효한 솔루션입니다. 나는 이것을 upvoted하고 앞으로 이것을 사용할 수도 있지만 아래의 Bryan의 대답은 너비 측정을 피하고 단순히 레이아웃 관리자에게 자신의 일을시키는 대신 더 나은 해결책입니다. 그래도 좋은 답변을 주셔서 감사합니다! – Tarm