使用底图作为Python GUI中的图形

时间:2016-02-02 21:29:13

标签: python matplotlib tkinter matplotlib-basemap

我有代码片段来生成底图,以及GUI(非常粗略)的启动。但是,我找不到那个" one-liner"将允许我将地图显示为GUI中的图形。代码片段如下;理想情况下,我想要做一些事情:

  1. '底图的图像'重新审视sin(2*pi*t)
  2. 的情节
  3. 我真的很想代码在图形上记录(像素)位置,如果我点击显示的图表(希望你可以点击地图上的任何地方,脚本会记录纬度和你点击的经度。)
  4. 关于第1步,我尝试过设置图形变量f等于底图;这完全杀死了GUI部分,只是在另一个窗口中显示了地图的图像。

    我试图通过尝试实现我在stackexchange上找到的几个例程来解决#2问题,但从未让它完全运行。

    底图:

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap
    
    ## User-chosen datapoint
    #lons = [10]; lats = [20];
    
    # Define map projection
    m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\
                llcrnrlon=-180,urcrnrlon=180,resolution='c')
    m.drawcoastlines()
    

    粗糙的GUI:

    import matplotlib
    matplotlib.use('TkAgg')
    
    from numpy import arange, sin, pi
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
    # implement the default mpl key bindings
    from matplotlib.backend_bases import key_press_handler
    
    from Tkinter import *
    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
    
    from PIL import Image
    from mpl_toolkits.basemap import Basemap
    
    from matplotlib.figure import Figure
    
    import sys
    if sys.version_info[0] < 3:
        import Tkinter as Tk
    else:
        import tkinter as Tk
    
    root = Tk.Tk()
    root.wm_title("Embedding in TK")
    
    f = Figure(figsize=(5, 4), dpi=100)
    a = f.add_subplot(111)
    t = arange(0.0, 3.0, 0.01)
    s = sin(2*pi*t)
    
    a.plot(t, s)
    
    # a tk.DrawingArea
    canvas = FigureCanvasTkAgg(f, master=root)
    canvas.show()
    canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
    
    toolbar = NavigationToolbar2TkAgg(canvas, root)
    toolbar.update()
    canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
    
    def on_key_event(event):
        print('you pressed %s' % event.key)
        key_press_handler(event, canvas, toolbar)
    
    canvas.mpl_connect('key_press_event', on_key_event)
    
    def _quit():
        root.quit()     # stops mainloop
        root.destroy()  # this is necessary on Windows to prevent
                        # Fatal Python Error: PyEval_RestoreThread: NULL tstate
    button = Tk.Button(master=root, text='Quit', command=_quit)
    button.pack(side=Tk.BOTTOM)
    
    Tk.mainloop()
    

2 个答案:

答案 0 :(得分:1)

一种简单的技术是定义on_click函数,显示图像,然后覆盖该图像。尽管图像发生了变化,on_click功能仍会读取鼠标点击位置。

下面是一个示例代码,证明如下所示:

import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

def on_click(event):
    if event.inaxes is not None:
        print event.xdata, event.ydata
    else:
        print 'Clicked ouside axes bounds but inside plot window'

fig, ax = plt.subplots()
fig.canvas.callbacks.connect('button_press_event', on_click)
plt.show()

#Define map projection
m = Basemap(projection='cyl', llcrnrlat=-90, urcrnrlat=90,
            llcrnrlon=-180, urcrnrlon=180, resolution='c')
m.drawcoastlines()

答案 1 :(得分:1)

如何将底图绘制到Tkinter中的问题实际上尚未得到解答。因此,我们的想法是在图中创建一个轴ax并将底图添加到轴中。这是通过ax参数

完成的
m = Basemap(..., ax=ax)

然后以通常的方式将该图添加到画布中;下面是一个完整的例子。

from mpl_toolkits.basemap import Basemap
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import sys
if sys.version_info[0] < 3:
    import Tkinter as Tk
else:
    import tkinter as Tk

root = Tk.Tk()
root.wm_title("Embedding in TK")

fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)

m = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\
            llcrnrlon=-180,urcrnrlon=180,resolution='c', ax=ax)
m.drawcoastlines()

# a tk.DrawingArea
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

toolbar = NavigationToolbar2TkAgg(canvas, root)
toolbar.update()
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

def _quit():
    root.quit()     # stops mainloop
    root.destroy()  # this is necessary on Windows to prevent
                    # Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = Tk.Button(master=root, text='Quit', command=_quit)
button.pack(side=Tk.BOTTOM)

Tk.mainloop()

enter image description here

注意:在较新版本的matplotlib中,您应使用NavigationToolbar2Tk代替NavigationToolbar2TkAgg