如何找到窗口小部件/对象的中心点并在另一个函数中使用它

时间:2014-11-25 20:25:12

标签: python object tkinter widget coordinates

我所拥有的是我的河内塔益智游戏的正在进行中。我只是在一两天工作,我在这里遇到的问题如下:如何将对象捕捉到屏幕上的特定位置。此刻发生的事情是对象会根据鼠标触摸对象的位置捕捉​​到特定位置。

import Tkinter as tk
from Tkinter import *
class SampleApp(tk.Tk):
    User_Input = input("How many disks?")
    global User_Input
    '''Illustrate how to drag items on a Tkinter canvas'''

    def __init__(self, *args, **kwargs):


        tk.Tk.__init__(self, *args, **kwargs)

        # create a canvas
        self.canvas = tk.Canvas(width=600, height=600)
        self.canvas.pack(fill="both", expand=True)

        # this data is used to keep track of an
        # item being dragged
        self._drag_data = {"x": 0, "y": 0, "item": None, "score": 0}
        self._disk_data = {"x": 0, "y": 0}
        self._pole1_data = {"x": 102, "y": 425}
        self._pole2_data = {"x": 0, "y": 0}
        self._pole3_data = {"x": 0, "y": 0}

        # create a couple movable OBJECTS

        self._create_token((100, 550), "black")
        self._create_bases((100, 600), "orange")
        self._create_poles((145, 585), "blue")
        self.scores(0)

        # add bindings for clicking, dragging and releasing over
        # any object with the "token" tag
        self.canvas.tag_bind("token", "<ButtonPress-1>", self.OnTokenButtonPress)
        self.canvas.tag_bind("token", "<ButtonRelease-1>", self.OnTokenButtonRelease)
        self.canvas.tag_bind("token", "<B1-Motion>", self.OnTokenMotion)

    def scores(self, score):
        global setrep
        global score_set
        if score >= 0:
            self.score_set = Label(self.canvas, text = "Moves: " + str(score), width = 20, height = 5, bg = "black", fg = "white").place(relx = 0.76, rely = 0.82)


    def _create_poles(self, coord, color):
        (x,y) = coord
        for i in range(0, 3):
            self.canvas.create_rectangle(x-45, y-30, x-45, y-395, outline = color, fill = color)
            x += 150

    def _create_bases(self, coord, color):
        (x,y) = coord
        for i in range(0, 3):
            self.canvas.create_rectangle(x-45, y-25, x+45, y-45, outline = color, fill = color)
            x += 150



    def _create_token(self, coord, color):
        '''Create a token at the given coordinate in the given color'''
        (x,y) = coord
        for i in range(0, User_Input):

            self.canvas.create_rectangle(x-45+(8*i), y-25, x+45, y-45, outline=color, fill=color, tags="token")
            y -= 50
            x -= 4.5

    def OnTokenButtonPress(self, event):
        '''Being drag of an object'''
        # record the item and its location
        self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
        self._drag_data["x"] = event.x
        self._drag_data["y"] = event.y

    def OnTokenButtonRelease(self, event):
        '''End drag of an object'''
        # reset the drag information
        self._drag_data["x"] = 0
        self._drag_data["y"] = 0
        self._drag_data["score"] += 1
        self.scores(self._drag_data["score"])
        self.canvas.move(self._drag_data["item"], self._pole1_data["x"]-event.x, self._pole1_data["y"]-event.y)
        print event.x, event.y
        self._drag_data["item"] = None


    def OnTokenMotion(self, event):
        '''Handle dragging of an object'''
        # compute how much this object has moved
        delta_x = event.x - self._drag_data["x"]
        delta_y = event.y - self._drag_data["y"]
        # move the object the appropriate amount
        self.canvas.move(self._drag_data["item"], delta_x, delta_y)
        # record the new position
        self._drag_data["x"] = event.x
        self._drag_data["y"] = event.y

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

我建议只使用1或2个磁盘进行测试,否则可能会造成混淆。

你要看的主要部分是 def TokenButtonRelease(self,event),并声明 self.canvas.move(self._drag_data [“item”], self._pole1_data [“x”] - event.x,self._pole1_data [“y”] - event.y)

问题是“-event.x”和“-event.y”,因为我真的希望减去对象的中心点。所以我的主要问题是如何找到这个,以及如何声明我希望这是必须带走的价值。您会注意到对象会捕捉到某个位置,但是如果您在不同的点抓住该对象,它显然会捕捉到稍微不同的点。

1 个答案:

答案 0 :(得分:1)

您可以跟踪字典或某个容器中的左上角。然后,您可以将左上角移动到所需的任何位置,然后更新字典。该程序使用tag_bind来告诉鼠标何时进入矩形,作为识别位置的简单演示,当然您也可以使用按钮释放等。

try
    import Tkinter as tk     ## Python 2.x
except ImportError:
    import tkinter as tk     ## Python 3.x

from functools import partial

class SampleApp():
    '''Illustrate how to drag items on a Tkinter canvas'''
    def __init__(self):
        self.user_input=0
        self.get_input()

        self.top=tk.Tk()
        self.create_canvas()
        self.x=20
        self.y=100
        self.rectangle_dict={}
        for ctr in range(0, self.user_input):
            self.create_rectangle(ctr)
        self.top.mainloop()

    def create_canvas(self):
        self.canvas = tk.Canvas(width=600, height=600)
        self.canvas.pack(fill="both", expand=True)

    def create_rectangle(self, ctr):
        colors=["red", "blue", "green", "orange", "yellow"]
        rc = self.canvas.create_rectangle(self.x, self.y,.
                           self.x+25, self.y+50, outline='white',
                           fill=colors[ctr])
        ## call the function, "func1", and send the value
        ## in ctr to it when the mouse enters
        ## this rectangle, i.e. different memory
        ## address/rectangle for "rc" for each 
        ## function call
        self.canvas.tag_bind(rc, "<Enter>",
                             partial(self.func1, ctr))
        self.rectangle_dict[ctr]=[self.x, self.y]
        self.x += 75
        self.y += 100

    def func1(self, ctr, event):
        """ "bind" sends a Tkinter event which must
            be caught even though it is not used
        """
        print "Enter called for rectangle number", ctr
        print "top left corner is %d, %d" % (self.rectangle_dict[ctr][0],
                                                self.rectangle_dict[ctr][1])

    def get_input(self):
        """ allow for 1 to 5 rectangles to be created
        """
        while self.user_input not in range(1, 6):
            self.user_input = raw_input("How many disks? ")
            if self.user_input.isdigit():
                self.user_input=int(self.user_input)
        print "%d disks will be created" % (self.user_input)

SA=SampleApp()