【问题标题】:Using basemap as a figure in a Python GUI在 Python GUI 中使用底图作为图形
【发布时间】:2016-05-11 21:17:15
【问题描述】:

我有生成底图的 sn-ps 代码,以及 GUI 的(非常粗略的)启动。但是,我找不到“单线”可以让我在 GUI 中将地图显示为图形。代码sn-ps如下;理想情况下,我希望发生几件事:

  1. “底图”的图像替换sin(2*pi*t) 的绘图
  2. 我真的希望代码记录图形上的(像素)位置,如果我要单击显示的图(希望您可以单击地图上的任何位置,脚本会记录纬度和点击位置的经度)。

关于第一步,我尝试过设置图形变量 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()

粗略的图形用户界面:

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()

【问题讨论】:

    标签: python matplotlib tkinter matplotlib-basemap


    【解决方案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()
    

    注意:在较新版本的 matplotlib 中,您应该使用 NavigationToolbar2Tk 而不是 NavigationToolbar2TkAgg

    【讨论】:

    • 我想知道,如果我希望在整个画布区域上绘制底图,那么我将在 canvas.show() 行之前使用 ax.set_aspect('auto') 如果我运行代码然后底图似乎占据了整个画布区域。现在的问题是,如果我尝试使用导航工具栏中的“缩放到矩形”选项放大地图的特定区域,那么地图似乎被拉伸了,这就是我想要避免的。你能解释一下它为什么会发生以及如何避免它。
    【解决方案2】:

    一种简单的技术是定义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()
    

    【讨论】:

      猜你喜欢
      • 2013-07-24
      • 2013-10-30
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多