【问题标题】:How to display picture and get mouse click coordinate on it [closed]如何显示图片并在其上获取鼠标点击坐标[关闭]
【发布时间】:2017-02-03 04:08:17
【问题描述】:

我想知道是否可以在 Python (Windows) 中显示一些图片,然后在此图片上单击鼠标并获取此点击相对于图片边缘的坐标。

谢谢!

【问题讨论】:

    标签: python mouseevent image


    【解决方案1】:

    是的,一旦您了解了 tkinter,这可能而且非常简单,这里有一个快速脚本:

    from Tkinter import *
    from tkFileDialog import askopenfilename
    import Image, ImageTk
    
    if __name__ == "__main__":
        root = Tk()
    
        #setting up a tkinter canvas with scrollbars
        frame = Frame(root, bd=2, relief=SUNKEN)
        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)
        xscroll = Scrollbar(frame, orient=HORIZONTAL)
        xscroll.grid(row=1, column=0, sticky=E+W)
        yscroll = Scrollbar(frame)
        yscroll.grid(row=0, column=1, sticky=N+S)
        canvas = Canvas(frame, bd=0, xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
        canvas.grid(row=0, column=0, sticky=N+S+E+W)
        xscroll.config(command=canvas.xview)
        yscroll.config(command=canvas.yview)
        frame.pack(fill=BOTH,expand=1)
    
        #adding the image
        File = askopenfilename(parent=root, initialdir="C:/",title='Choose an image.')
        img = ImageTk.PhotoImage(Image.open(File))
        canvas.create_image(0,0,image=img,anchor="nw")
        canvas.config(scrollregion=canvas.bbox(ALL))
    
        #function to be called when mouse is clicked
        def printcoords(event):
            #outputting x and y coords to console
            print (event.x,event.y)
        #mouseclick event
        canvas.bind("<Button 1>",printcoords)
    
        root.mainloop()
    

    未经编辑,它将使用默认窗口坐标系打印到控制台。画布小部件使左上角成为 0,0 点,因此您可能不得不使用 printcoords 函数。要获得加载的图片尺寸,您将使用 canvas.bbox(ALL),并且您可能希望切换到使用 canvasx 和 canvasy 坐标而不是原来的方式。如果您不熟悉 tkinter; google 应该可以帮助你从这里完成它:)。

    【讨论】:

    • 不应该是from PIL import Image, ImageTk
    • 3.7 中的导入:from tkinter import * from tkinter import filedialog from PIL.Image import core as image from PIL import ImageTk from PIL import Image as PILImage
    【解决方案2】:

    这是我不久前使用 wxPython 和各种 wxPython 教程拼凑而成的版本。这会将鼠标单击坐标打印到单独的输出窗口。 (使用 Python 2.6.2、wxPython 2.8.10.1)

    在底部的filepath 变量中输入图片的路径。

    import wx
    
    class MyCanvas(wx.ScrolledWindow):
        def __init__(self, parent, id = -1, size = wx.DefaultSize, filepath = None):
            wx.ScrolledWindow.__init__(self, parent, id, (0, 0), size=size, style=wx.SUNKEN_BORDER)
    
            self.image = wx.Image(filepath)
            self.w = self.image.GetWidth()
            self.h = self.image.GetHeight()
            self.bmp = wx.BitmapFromImage(self.image)
    
            self.SetVirtualSize((self.w, self.h))
            self.SetScrollRate(20,20)
            self.SetBackgroundColour(wx.Colour(0,0,0))
    
            self.buffer = wx.EmptyBitmap(self.w, self.h)
            dc = wx.BufferedDC(None, self.buffer)
            dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
            dc.Clear()
            self.DoDrawing(dc)
    
            self.Bind(wx.EVT_PAINT, self.OnPaint)
            self.Bind(wx.EVT_LEFT_UP, self.OnClick)
    
        def OnClick(self, event):
            pos = self.CalcUnscrolledPosition(event.GetPosition())
            print '%d, %d' %(pos.x, pos.y)
    
        def OnPaint(self, event):
            dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)
    
        def DoDrawing(self, dc):
            dc.DrawBitmap(self.bmp, 0, 0)
    
    class MyFrame(wx.Frame): 
        def __init__(self, parent=None, id=-1, filepath = None): 
            wx.Frame.__init__(self, parent, id, title=filepath)
            self.canvas = MyCanvas(self, -1, filepath = filepath)
    
            self.canvas.SetMinSize((self.canvas.w, self.canvas.h))
            self.canvas.SetMaxSize((self.canvas.w, self.canvas.h))
            self.canvas.SetBackgroundColour(wx.Colour(0, 0, 0))
            vert = wx.BoxSizer(wx.VERTICAL)
            horz = wx.BoxSizer(wx.HORIZONTAL)
            vert.Add(horz,0, wx.EXPAND,0)
            vert.Add(self.canvas,1,wx.EXPAND,0)
            self.SetSizer(vert)
            vert.Fit(self)
            self.Layout()
    
    if __name__ == '__main__':
        app = wx.App()
        app.SetOutputWindowAttributes(title='stdout')  
        wx.InitAllImageHandlers()
    
        filepath = 'ENTER FILEPATH HERE'
        if filepath:
            print filepath
            myframe = MyFrame(filepath=filepath)
            myframe.Center()
            myframe.Show()
            app.MainLoop()
    

    【讨论】:

    • 我真的很喜欢这个!有没有办法放大和缩小图片?
    【解决方案3】:

    这是 bigjim 答案的修订版。它适用于 python 3.4+(没有测试其他任何东西)。我没有打扰 PIL 部分,因为 tkinter 的 PhotoImage 可以处理 gif 和 pgm,这足以演示这个。

    lambda 函数处理事件(窗口)坐标和图像坐标之间的转换。

    我还添加了对新闻与发布的支持,因为我需要该特定功能。

    from tkinter import *
    from tkinter.filedialog import askopenfilename
    
    event2canvas = lambda e, c: (c.canvasx(e.x), c.canvasy(e.y))
    
    if __name__ == "__main__":
        root = Tk()
    
        #setting up a tkinter canvas with scrollbars
        frame = Frame(root, bd=2, relief=SUNKEN)
        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)
        xscroll = Scrollbar(frame, orient=HORIZONTAL)
        xscroll.grid(row=1, column=0, sticky=E+W)
        yscroll = Scrollbar(frame)
        yscroll.grid(row=0, column=1, sticky=N+S)
        canvas = Canvas(frame, bd=0, xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
        canvas.grid(row=0, column=0, sticky=N+S+E+W)
        xscroll.config(command=canvas.xview)
        yscroll.config(command=canvas.yview)
        frame.pack(fill=BOTH,expand=1)
    
        #adding the image
        File = askopenfilename(parent=root, initialdir="M:/",title='Choose an image.')
        print("opening %s" % File)
        img = PhotoImage(file=File)
        canvas.create_image(0,0,image=img,anchor="nw")
        canvas.config(scrollregion=canvas.bbox(ALL))
    
        #function to be called when mouse is clicked
        def printcoords(event):
            #outputting x and y coords to console
            cx, cy = event2canvas(event, canvas)
            print ("(%d, %d) / (%d, %d)" % (event.x,event.y,cx,cy))
        #mouseclick event
        canvas.bind("<ButtonPress-1>",printcoords)
        canvas.bind("<ButtonRelease-1>",printcoords)
    
        root.mainloop()
    

    【讨论】:

      【解决方案4】:

      您可以使用 Tkinter 来执行此操作,并且它已经内置在 python 中。

      http://www.pythonware.com/library/tkinter/introduction/

      【讨论】:

        【解决方案5】:

        Tkinter 的一个很好的替代方法是在 Python 中使用 QT。您可以通过PyQTPySide 来实现。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-31
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多