2012-01-04 153 views
1

我有一些浮動在可滾動畫布小部件上的文本小部件。我想讓用戶通過拖動它們的邊緣和/或邊角來調整它們的大小,如果它們拖動左上角或邊角,可能會移動它們。我願意將它們變成帶有文本小部件的框架,因爲無論如何我都可以這樣做。在tkinter畫布內部製作小部件/框架可調整大小

我想我可以手動處理事件,如果我可以讓它顯示調整大小手柄。我需要捕捉鼠標懸停並自己點擊邊框嗎?

添加一個「<配置>」事件綁定什麼都不做,正如人們所期望的。據稱ttk.Sizegrip只能在頂層窗口中運行。有很多資源可以用來防止調整大小,但爲了方便調整它們卻很少,而且它們似乎都適用於頂級窗口。

回答

2

我最終圍繞小部件製作了一個帶有胖邊框的框架,捕捉鼠標事件以及自己處理所有髒調整大小邏輯。

我必須記錄點擊位置的初始位置和每個連續鼠標移動的位置,並分別用它們來分別調整頂部/左側和底部/右側的大小。

編輯:這是一個方便(相對)封裝的實現。

from Tkinter import * 

class ResizableCanvasFrame(Frame): 
    ''' 
    Class that handles creating resizable frames on a canvas. 
    Don't pack it. 

    Set save_callback to whatever you want to happen when the mouse 
    lets up on the border. You can catch <Configure> too, but at least 
    in my case I didn't want to save the new position on every mouse move. 
    ''' 
    def __init__(self, master, x, y, w, h, *args, **kwargs): 
     # master should be a Canvas 
     self.frame_thickness = 5 
     Frame.__init__(
      self, 
      master, 
      *args, 
      borderwidth = self.frame_thickness, 
      cursor = 'fleur', 
      **kwargs 
     ) 
     self.canvas = master 
     self.resize_state = None 
     self.bind('<Button-1>', self.mousedown) 
     self.bind('<B1-Motion>', self.mousemove) 
     self.bind('<ButtonRelease-1>', self.mouseup) 
     self.bind('<Destroy>', self.delete_item) 
     # add self to canvas 
     self.itemid = self.canvas.create_window(
      x, 
      y, 
      window=self, 
      anchor="nw", 
      width=w, 
      height=h 
     ) 
     self.save_callback = None 

    def canvas_coords(self): 
     return map(int, self.canvas.coords(self.itemid)) 

    def move(self, dx, dy): 
     # strictly, this is out of the range of RCF, 
     # but it helps with the law of demeter 
     self.canvas.move(self.itemid, dx, dy) 

    def mousedown(self, event): 
     window_width = self.winfo_width() 
     window_height = self.winfo_height() 
     self.resize_state = { 
      'start_coords': (event.x, event.y), 
      'last_coords': (event.x, event.y), 
      'left_edge': (0 <= event.x < self.frame_thickness), 
      'right_edge': (window_width - self.frame_thickness <= event.x < window_width), 
      'top_edge': (0 <= event.y < self.frame_thickness), 
      'bottom_edge': (window_height - self.frame_thickness <= event.y < window_height), 
     }    

    def mousemove(self, event): 
     if self.resize_state: 
      resize = self.resize_state # debug var 
      event_x = event.x 
      event_y = event.y 
      # distance of cursor from original position of window 
      delta = map(int, (event.x - self.resize_state['start_coords'][0], 
           event.y - self.resize_state['start_coords'][1])) 
      # load current pos, size 
      new_x, new_y = self.canvas_coords() 
      new_width = int(self.canvas.itemcget(self.itemid, 'width')) 
      new_height = int(self.canvas.itemcget(self.itemid, 'height')) 
      # handle x resize/move 
      if self.resize_state['left_edge']: 
       # must move pos and resize 
       new_x += delta[0] 
       new_width -= delta[0] 
      elif self.resize_state['right_edge']: 
       new_width += (event.x - self.resize_state['last_coords'][0]) 
      # handle y resize/move 
      if self.resize_state['top_edge']: 
       new_y += delta[1] 
       new_height -= delta[1] 
      elif self.resize_state['bottom_edge']: 
       new_height += (event.y - self.resize_state['last_coords'][1]) 
      # save new settings in item, not card yet 
      self.resize_state['last_coords'] = (event.x, event.y) 
      self.canvas.coords(self.itemid, new_x, new_y) 
      self.canvas.itemconfig(self.itemid, width=new_width, height=new_height) 

    def mouseup(self, event): 
     if self.resize_state: 
      self.resize_state = None 
      if self.save_callback: 
       self.save_callback() 

    def delete_item(self, event): 
     self.canvas.delete(self.itemid) 
0

你可以使用PanedWindow小部件,或者你的畫布裏面他們幾個的組合。他們旨在做到這一點。儘管如此,讓PanedWindow像畫布中的「粘性」命令一樣拉伸是一個未知數。

這就是我偶然發現這篇文章時所尋找的。

+0

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/panedwindow.html – Sam 2014-01-19 07:56:39

+0

http://effbot.org/tkinterbook/panedwindow.htm – Sam 2014-01-19 07:57:23