2013-05-13 152 views
3

我正在寻找一种方法,使Tkinter的框架的行为有点像这样在调整大小:调整大小的Tkinter框架固定纵横比

from Tkinter import * 
w = Tk() 
w.aspect(1,1,1,1) 
w.mainloop() 

所以我想这个代码在这里:

import Tkinter as tk 
from Tkconstants import * 
r=tk.Tk() 
content_frame=tk.Frame(r,borderwidth=5,relief=GROOVE) 
content_frame.grid(row=0,column=0,sticky=(N,S,E,W)) 
tk.Label(content_frame,text='content').pack() 
pad_frame=tk.Frame(r,borderwidth=5,relief=GROOVE) 
pad_frame.grid(row=1,column=0,sticky=(N,S,E,W)) 
tk.Label(pad_frame,text='-pad-').pack() 
r.rowconfigure(0, weight=1) 
r.rowconfigure(1, weight=1) 
r.columnconfigure(0, weight=1) 
r.mainloop() 

它基本上创建了2个框架,其中一个应该包含一些内容(在我的应用程序中,此框架包含可调整大小的mathplotlib图形),另一个仅用于填充。

要表现在调整大小遵循以下规则:

  • 与固定纵横比内容框架调整大小(假设它总是需要是正方形)
  • 垫架占据了剩余的(垂直)空间

任何想法?我一直在阅读手册一段时间,似乎无法找到合适的东西。

-Daniel

+0

你为什么不移除填充并只使用'aspect'? – 2013-05-13 14:04:30

+0

这是我真正想要的简化案例。整个事情是嵌入在一个更大的接口,所以我不能使用Windows /顶级/ ... 和框架没有.aspect()方法。 – 2013-05-14 09:28:10

回答

4

至少有一对夫妇的方式来解决这个问题。最简单的IMO就是让您的填充小部件成为您的内容小部件的容器,然后使用place明确设置内容小部件的宽度和高度。这是其中place优于gridpack的其中一种边缘情况。

在下面的例子中,我创建了一个函数,可以传入内容框架,填充框架和高宽比。然后通过容器的高宽比和大小来限制内容框的大小。它会使内容窗口填充X维中的容器,然后适当地设置高度。如果生成的窗口太高而不可见,则将最大高度设置为容器的高度,然后调整宽度。

我试图保持大部分代码不受问题的影响,尽管这不完全是我通常选择编码的方式。我已经给出了不同的颜色,所以很容易看到发生了什么。

import Tkinter as tk 
from Tkconstants import * 
r=tk.Tk() 

def set_aspect(content_frame, pad_frame, aspect_ratio): 
    # a function which places a frame within a containing frame, and 
    # then forces the inner frame to keep a specific aspect ratio 

    def enforce_aspect_ratio(event): 
     # when the pad window resizes, fit the content into it, 
     # either by fixing the width or the height and then 
     # adjusting the height or width based on the aspect ratio. 

     # start by using the width as the controlling dimension 
     desired_width = event.width 
     desired_height = int(event.width/aspect_ratio) 

     # if the window is too tall to fit, use the height as 
     # the controlling dimension 
     if desired_height > event.height: 
      desired_height = event.height 
      desired_width = int(event.height * aspect_ratio) 

     # place the window, giving it an explicit size 
     content_frame.place(in_=pad_frame, x=0, y=0, 
      width=desired_width, height=desired_height) 

    pad_frame.bind("<Configure>", enforce_aspect_ratio) 

pad_frame = tk.Frame(borderwidth=0, background="bisque", width=200, height=200) 
pad_frame.grid(row=0, column=0, sticky="nsew", padx=10, pady=20) 
content_frame=tk.Frame(r,borderwidth=5,relief=GROOVE, background="blue") 
tk.Label(content_frame,text='content').pack() 
set_aspect(content_frame, pad_frame, aspect_ratio=2.0/1.0) 
r.rowconfigure(0, weight=1) 
r.columnconfigure(0, weight=1) 

r.mainloop() 

如果包含的小部件的容易调整容器的大小,这将工作最好。如果内部有复杂的小部件布局,则当窗口缩小到自然尺寸以下时,如果不适合,某些小部件可能会被切断。

+0

工程就像一个魅力。非常有用,谢谢你。如果我在Tkinter的GUI编程方面有更多的经验,我可能也会做得不一样,但我对整个事情都比较陌生。再次感谢伟大的代码。 – 2013-05-17 09:55:21

2

你可以绑定到<Configure>事件函数包含的内容和填充帧Frame。调整窗口大小时将触发<Configure>事件。通过更新行和列的权重,使用事件的宽度和高度属性来修复内容框架的大小:rowconfigurecolumnconfigure

您需要在容器框架中有两行和两列才能有方形内容框架。有了一个高大的窗户,你需要在第二行填充。而且,如果窗口很宽,则需要在第二列填充。

工作的示例:

import Tkinter as tk 
from Tkconstants import * 


class Application(tk.Frame): 
    def __init__(self, master, width, height): 
     tk.Frame.__init__(self, master) 
     self.grid(sticky=N + S + E + W) 
     master.rowconfigure(0, weight=1) 
     master.columnconfigure(0, weight=1) 
     self._create_widgets() 
     self.bind('<Configure>', self._resize) 
     self.winfo_toplevel().minsize(150, 150) 

    def _create_widgets(self): 
     self.content = tk.Frame(self, bg='blue') 
     self.content.grid(row=0, column=0, sticky=N + S + E + W) 

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

    def _resize(self, event): 
     '''Modify padding when window is resized.''' 
     w, h = event.width, event.height 
     w1, h1 = self.content.winfo_width(), self.content.winfo_height() 
     print w1, h1 # should be equal 
     if w > h: 
      self.rowconfigure(0, weight=1) 
      self.rowconfigure(1, weight=0) 
      self.columnconfigure(0, weight=h) 
      self.columnconfigure(1, weight=w - h) 
     elif w < h: 
      self.rowconfigure(0, weight=w) 
      self.rowconfigure(1, weight=h - w) 
      self.columnconfigure(0, weight=1) 
      self.columnconfigure(1, weight=0) 
     else: 
      # width = height 
      self.rowconfigure(0, weight=1) 
      self.rowconfigure(1, weight=0) 
      self.rowconfigure(0, weight=1) 
      self.columnconfigure(1, weight=0) 

root = tk.Tk() 
app = Application(master=root, width=100, height=100) 
app.mainloop() 
+0

也完美的作品。也会接受你的答案,但我只能接受一个...对此抱歉。 不过,非常感谢。 – 2013-05-17 09:56:45

+0

谢谢,Bryan的答案好多了。 – 2013-05-17 10:21:18

相关问题