gpt4 book ai didi

python - 使 tkinter Canvas 内的小部件/框架可调整大小

转载 作者:行者123 更新时间:2023-12-01 06:04:43 26 4
gpt4 key购买 nike

我有许多文本小部件漂浮在可滚动 Canvas 小部件上。我希望允许用户通过拖动边缘和/或角来调整它们的大小,如果拖动左上角边缘或角,则可能会移动它们。我愿意将它们制作成带有文本小部件的框架,因为无论如何我都可能会这样做。

我想如果我能让它显示调整大小句柄,我就可以手动处理事件。我需要自己捕获鼠标悬停和单击边框吗?

正如人们所期望的那样,添加“ ”事件绑定(bind)不会执行任何操作。据称 ttk.Sizegrip 仅适用于顶级窗口。有很多资源可以防止调整大小,但很少有资源可以促进调整大小,而且它们似乎都是针对顶级窗口的。

最佳答案

我最终在小部件周围制作了一个带有粗边框的框架,捕获鼠标事件,并自己处理所有脏的调整大小逻辑。

我必须记录单击位置的初始位置和每次连续鼠标移动的位置,并分别将它们用于上/左和下/右调整大小。

编辑:这是一个方便的(相对)封装的实现。

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)

关于python - 使 tkinter Canvas 内的小部件/框架可调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8735668/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com