首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何拥有多个可拖动的画布部件?

如何拥有多个可拖动的画布部件?
EN

Stack Overflow用户
提问于 2020-05-28 20:46:05
回答 1查看 216关注 0票数 1

到目前为止,我已经:

  1. 拖放图像对象重新定位代码,允许多个自定义小部件可拖放。
  2. 重新定位代码进行得很好,除了尝试强制可拖小部件仅在画布维度中移动之外。
  3. 如果将单个小部件添加到画布中,则小部件是可拖动的,并绑定到画布维度。
  4. 问题:如果任何数量超过一个的小部件被添加到画布中,那么只有最后添加的小部件是可拖放的,并绑定到画布尺寸。由于鼠标运动回调中的逻辑,所有其他小部件都无法移动,其中检测到的鼠标运动异常大。
  5. 可拖动的小部件是面向对象的,因此使单个可拖动小部件的逻辑与同一小部件类型的多个其他实例化完全相同。
  6. 到目前为止,我所掌握的被操纵代码是:
代码语言:javascript
复制
import os
import tkinter as tk

APP_TITLE = "Drag & Drop Tk Canvas Images"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 300
APP_HEIGHT = 200

class CreateCanvasObject(object):    

    def __init__(self, canvas, block_name):
        self.canvas = canvas

        self.block_width = 250
        self.block_height = 250

        self.name = block_name

        self.max_speed = 30

        self.win_width = self.canvas.winfo_width()
        self.win_height = self.canvas.winfo_height()

        self.block_main = tk.Frame(self.canvas, bd=10, relief=tk.RAISED)
        self.block_main.pack(side=tk.TOP, fill=tk.BOTH, expand=False, padx=0, pady=0)

        self.block_name = tk.Label(self.block_main, text=block_name, anchor=tk.CENTER, font='Helvetica 10 bold', cursor='fleur')
        self.block_name.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        self.image_obj = self.canvas.create_window( (0, 0), window=self.block_main, anchor="nw", width=self.block_width, height=self.block_height)

        self.block_name.bind( '<Button1-Motion>', self.move)
        self.block_name.bind( '<ButtonRelease-1>', self.release)
        self.move_flag = False    

        self.canvas.bind("<Configure>", self.configure)


    def configure(self, event):
        self.win_width = event.width
        self.win_height = event.height        


    def move(self, event):

        print('Moving [%s]'%self.name)
        print(event)

        if self.move_flag:

            dx, dy = event.x, event.y

            abs_coord_x, abs_coord_y = self.canvas.coords( self.image_obj )

            cond_1 = abs_coord_x + dx >= 0
            cond_2 = abs_coord_y + dy >= 0
            cond_3 = (abs_coord_x + self.block_width + dx) <= self.win_width
            cond_4 = (abs_coord_y + self.block_height + dy) <= self.win_height

            print('abs_coord_x = %3.2f ; abs_coord_y = %3.2f'%(abs_coord_x, abs_coord_y))
            print('dx = %3.2f ; dy = %3.2f'%(dx, dy))
            print('self.block_width = %3.2f'%(self.block_width))
            print('self.block_height = %3.2f'%(self.block_height))
            print('Cond 1 = %s; Cond 2 = %s; Cond 3 = %s; Cond 4 = %s\n\n'%(cond_1, cond_2, cond_3, cond_4))

            if cond_1 and cond_2 and cond_3 and cond_4:
                self.canvas.move(self.image_obj, dx, dy)

        else:
            self.move_flag = True
            self.canvas.tag_raise(self.image_obj)


    def release(self, event):
        self.move_flag = False



class Application(tk.Frame):

    def __init__(self, master):
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.close)
        tk.Frame.__init__(self, master)

        self.canvas = tk.Canvas(self, width=800, height=800, bg='steelblue', highlightthickness=0)
        self.canvas.pack(fill=tk.BOTH, expand=True)

        self.block_1 = CreateCanvasObject(canvas=self.canvas, block_name='Thing 1')
        self.block_2 = CreateCanvasObject(canvas=self.canvas, block_name='Thing 2')

    def close(self):
        print("Application-Shutdown")
        self.master.destroy()

def main():
    app_win = tk.Tk()
    app_win.title(APP_TITLE)
    app_win.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))

    Application(app_win).pack(fill='both', expand=True)

    app_win.mainloop()


if __name__ == '__main__':
    main()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-29 00:17:07

问题的根源在于这一行代码:

代码语言:javascript
复制
self.canvas.bind("<Configure>", self.configure)

每当您调用self.canvas.bind时,都会替换小部件上的任何以前绑定。因此,当绑定被触发时,只有最后一个CreateCanvasObject将看到该事件,因为它将替换由以前的CreateCanvasObject对象创建的绑定。

因此,您只更新最后创建的对象的self.win_widthself.win_height。而且,由于使用这些值计算self.cond3self.cond4,这些条件始终是假的,因此对象永远不会移动。

一个简单的解决方案是删除绑定和删除configure方法,而不是计算move函数中的宽度和高度。这样,或者创建self.win_widthself.win_height类变量,所以当您更新一个变量时,您会更新所有变量。这些不是解决问题的唯一方法,但它们是最简单的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62074235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档