드래그 가능한 캔버스 위젯을 여러 개 사용하는 방법은 무엇입니까?

토니 A

지금까지 :

  1. 드래그 앤 드롭 이미지 객체의 용도가 변경 되어 여러 사용자 정의 위젯을 드래그 할 수 있습니다.

  2. 드래그 가능한 위젯이 캔버스 차원 내에서만 이동하도록 강제하는 것을 제외하고 코드 용도 변경은 잘 진행되었습니다.

  3. 단일 위젯이 캔버스에 추가되면 위젯을 드래그 할 수 있으며 캔버스 크기에 바인딩됩니다.

  4. 문제 : 하나 이상의 위젯이 캔버스에 추가되면 마지막으로 추가 된 위젯 만 드래그 할 수 있고 캔버스 크기에 바인딩됩니다. 다른 모든 위젯은 감지 된 마우스 모션이 비정상적으로 큰 마우스 모션 콜백의 논리로 인해 이동하지 못합니다.

  5. 드래그 가능한 위젯은 객체 지향적이므로 단일 드래그 가능한 위젯을 만드는 논리는 동일한 위젯 유형의 다른 여러 인스턴스화와 동일합니다.

  6. 지금까지 내가 조작 한 코드는 다음과 같습니다.

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()
브라이언 오클리

문제의 근원은 다음 코드 줄입니다.

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

를 호출 할 때마다 self.canvas.bind위젯의 이전 바인딩을 대체합니다. 따라서 바인딩이 트리거되면 CreateCanvasObject이전 CreateCanvasObject개체에 의해 생성 된 바인딩이 대체되므로 마지막 이벤트 이벤트를 보게 됩니다.

그 때문에, 당신은 업데이트 self.win_width하고 self.win_height마지막으로 생성 된 개체 만 업데이트 합니다. 당신이 계산하는 값을 사용하기 때문에 self.cond3하고 self.cond4, 그 조건은 항상 거짓 따라서 객체 결코 이동합니다.

간단한 해결책은 바인딩을 제거하고 configure메서드를 제거 하고 대신 move함수 내부의 너비와 높이를 계산하는 것입니다. 또는 make self.win_widthself.win_height클래스 변수를 업데이트하면 모두 업데이트됩니다. 이것이 문제를 해결하는 유일한 방법은 아니지만 가장 간단합니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

클릭 가능한 캔버스를 사용하여 비트 맵을 만드는 방법은 무엇입니까?

분류에서Dev

드래그 가능한 jQuery UI 기능을 여러 항목에 적용하는 방법은 무엇입니까?

분류에서Dev

한 번에 여러 사각형을 캔버스에 그리는 방법은 무엇입니까?

분류에서Dev

임베드 가능한 여러 위젯을 만드는 방법은 무엇입니까?

분류에서Dev

균일 한 버퍼 개체와 인스턴스 렌더링을 사용하여 여러 개체를 그리는 방법은 무엇입니까?

분류에서Dev

클래스를 사용하여 tkinter 캔버스에 다각형을 그리는 방법은 무엇입니까?

분류에서Dev

클래스를 사용하여 tkinter로 여러 개의 유사한 프레임을 만드는 방법은 무엇입니까?

분류에서Dev

JavaScript를 사용하여 캔버스 끝을 칠 때 개체를 중지하는 방법은 무엇입니까?

분류에서Dev

메소드가 여러 유형을 허용한다는 것을 UML 클래스 다이어그램에서 묘사하는 방법은 무엇입니까?

분류에서Dev

여러 멤버 값을 설정하기 위해 클래스에 단일 개체 인스턴스를 사용하는 방법은 무엇입니까?

분류에서Dev

drawImage ()를 사용하여 캔버스에 그림을 그리는 방법은 무엇입니까?

분류에서Dev

SharedPreference를 사용하여 캔버스에 문자열을 그리는 방법은 무엇입니까?

분류에서Dev

다양한 기능을 테스트하기 위해 Swift 2 앱의 여러 버전을 만드는 가장 좋은 방법은 무엇입니까?

분류에서Dev

캔버스를 사용하여 그림자가 삽입 된 구멍을 이미지로 자르는 방법은 무엇입니까?

분류에서Dev

여러 캔버스가 포함 된 섹션 뒤에 섹션을 추가하는 방법은 무엇입니까?

분류에서Dev

Android Studio의 서버에 업로드하기 위해 선택한 여러 사진을 개별적으로 저장하는 방법은 무엇입니까?

분류에서Dev

tkinter 캔버스 위젯 / 애프터 메소드가 목록의 요소를 건너 뛰는 것을 중지하는 방법은 무엇입니까?

분류에서Dev

HAML : 클래스가 많은 요소로 여러 줄을 사용하는 방법은 무엇입니까?

분류에서Dev

스크롤 뷰에 동시에 여러 위젯을 추가하는 방법은 무엇입니까?

분류에서Dev

외부 라이브러리에서 WPF를 사용하여 동적으로 변경 가능한 스타일을 만드는 방법은 무엇입니까?

분류에서Dev

래스터 개체의 값을 사용하여 레이어를 만드는 방법은 무엇입니까?

분류에서Dev

두 개의 스레드가 Collection의 동일한 부분을 반복하지 않는 Collection을 반복하기 위해 Java에서 여러 스레드를 사용하는 방법은 무엇입니까?

분류에서Dev

Android에서 여러 스레드에 여러 버튼을 사용하는 방법은 무엇입니까?

분류에서Dev

각 개체에 여러 필드가있는 ehcache를 사용하여 캐시에 개체 배열을 추가하는 방법은 무엇입니까?

분류에서Dev

Angular를 사용하여 배열의 각 개체에 고유 한 클래스 이름을 추가하는 방법은 무엇입니까?

분류에서Dev

여러 가능한 URL 매개 변수 중 하나에서 값을 얻는 방법은 무엇입니까?

분류에서Dev

pyqt : 동일한 기능을 사용하여 다른 qt 위젯의 텍스트를 설정하는 방법은 무엇입니까?

분류에서Dev

여러 버튼을 클릭 한 후 <button> 태그를 사용하여 만든 버튼의 텍스트를 변경하는 방법은 무엇입니까?

분류에서Dev

가능한 여러 열거 형 유형으로 Codable 클래스를 만드는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    클릭 가능한 캔버스를 사용하여 비트 맵을 만드는 방법은 무엇입니까?

  2. 2

    드래그 가능한 jQuery UI 기능을 여러 항목에 적용하는 방법은 무엇입니까?

  3. 3

    한 번에 여러 사각형을 캔버스에 그리는 방법은 무엇입니까?

  4. 4

    임베드 가능한 여러 위젯을 만드는 방법은 무엇입니까?

  5. 5

    균일 한 버퍼 개체와 인스턴스 렌더링을 사용하여 여러 개체를 그리는 방법은 무엇입니까?

  6. 6

    클래스를 사용하여 tkinter 캔버스에 다각형을 그리는 방법은 무엇입니까?

  7. 7

    클래스를 사용하여 tkinter로 여러 개의 유사한 프레임을 만드는 방법은 무엇입니까?

  8. 8

    JavaScript를 사용하여 캔버스 끝을 칠 때 개체를 중지하는 방법은 무엇입니까?

  9. 9

    메소드가 여러 유형을 허용한다는 것을 UML 클래스 다이어그램에서 묘사하는 방법은 무엇입니까?

  10. 10

    여러 멤버 값을 설정하기 위해 클래스에 단일 개체 인스턴스를 사용하는 방법은 무엇입니까?

  11. 11

    drawImage ()를 사용하여 캔버스에 그림을 그리는 방법은 무엇입니까?

  12. 12

    SharedPreference를 사용하여 캔버스에 문자열을 그리는 방법은 무엇입니까?

  13. 13

    다양한 기능을 테스트하기 위해 Swift 2 앱의 여러 버전을 만드는 가장 좋은 방법은 무엇입니까?

  14. 14

    캔버스를 사용하여 그림자가 삽입 된 구멍을 이미지로 자르는 방법은 무엇입니까?

  15. 15

    여러 캔버스가 포함 된 섹션 뒤에 섹션을 추가하는 방법은 무엇입니까?

  16. 16

    Android Studio의 서버에 업로드하기 위해 선택한 여러 사진을 개별적으로 저장하는 방법은 무엇입니까?

  17. 17

    tkinter 캔버스 위젯 / 애프터 메소드가 목록의 요소를 건너 뛰는 것을 중지하는 방법은 무엇입니까?

  18. 18

    HAML : 클래스가 많은 요소로 여러 줄을 사용하는 방법은 무엇입니까?

  19. 19

    스크롤 뷰에 동시에 여러 위젯을 추가하는 방법은 무엇입니까?

  20. 20

    외부 라이브러리에서 WPF를 사용하여 동적으로 변경 가능한 스타일을 만드는 방법은 무엇입니까?

  21. 21

    래스터 개체의 값을 사용하여 레이어를 만드는 방법은 무엇입니까?

  22. 22

    두 개의 스레드가 Collection의 동일한 부분을 반복하지 않는 Collection을 반복하기 위해 Java에서 여러 스레드를 사용하는 방법은 무엇입니까?

  23. 23

    Android에서 여러 스레드에 여러 버튼을 사용하는 방법은 무엇입니까?

  24. 24

    각 개체에 여러 필드가있는 ehcache를 사용하여 캐시에 개체 배열을 추가하는 방법은 무엇입니까?

  25. 25

    Angular를 사용하여 배열의 각 개체에 고유 한 클래스 이름을 추가하는 방법은 무엇입니까?

  26. 26

    여러 가능한 URL 매개 변수 중 하나에서 값을 얻는 방법은 무엇입니까?

  27. 27

    pyqt : 동일한 기능을 사용하여 다른 qt 위젯의 텍스트를 설정하는 방법은 무엇입니까?

  28. 28

    여러 버튼을 클릭 한 후 <button> 태그를 사용하여 만든 버튼의 텍스트를 변경하는 방법은 무엇입니까?

  29. 29

    가능한 여러 열거 형 유형으로 Codable 클래스를 만드는 방법은 무엇입니까?

뜨겁다태그

보관