下面的程序会设置一个图表,并在每次用户点击时显示一个蓝色框。 用户可以使用右键单击弹出菜单制作更多框。当我实现弹出菜单(因此允许多个蓝色框)时,程序在窗口关闭时停止关闭。我将一个deleteAll()方法连接到画布以强制关闭sys.exit(),但程序仍保持打开状态。我究竟做错了什么?
#**************************************************************************#
# Set up a graph. A click creates a blue box. More blue boxes can be made
# by choosing "Make a new box" from right/click menu.
#**************************************************************************#
import wx
import matplotlib
matplotlib.use('WX')
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanv
from pylab import *
#**************************************************************************#
class MainCanvas(wx.Frame):
""" Class to set up graph """
def __init__(self):
wx.Frame.__init__(self,None,-1, 'Make Blue Boxes',size=(550,350))
#**********************************************************************#
def setupGraph(self):
""" Set up window and graph """
self.definePlot()
self.canvas = FigCanv(self, -1, self.figure)
self.setSizer()
#**********************************************************************#
def definePlot(self):
""" Define attributes of graph """
self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
#**********************************************************************#
def setSizer(self):
""" Set the size of the graph """
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
#**************************************************************************#
class BlueBox(MainCanvas):
""" Class to set up BlueBox """
def __init__(self):
MainCanvas.__init__(self)
#**********************************************************************#
def setupBlueBox(self):
""" Blue box set up """
self.blueBox = patches.Rectangle((0, 0), 0.05, 0.05,
fc = "Blue", visible = False, zorder = 3)
# Set zorder so new boxes are in front of old
if len(self.listDT)>1:
oldz = self.listDT[len(self.listDT)-2].blueBox.get_zorder() + 3
self.listDT[len(self.listDT)-1].blueBox.set_zorder(oldz)
self.axes.add_patch(self.blueBox)
#**********************************************************************#
def onPick(self, event):
""" Behavior when graph is clicked """
# Refresh BlueBox position and coordinate text
self.refreshBlueBox(event)
# Set the current BlueBox visible
self.listDT[len(self.listDT)-1].setVisible()
#**********************************************************************#
def refreshBlueBox(self, event):
""" Blue box refresh """
# Center the BlueBox (Point Box) over the mouse click location
self.blueBox.set_x(event.xdata - .5 * self.blueBox.get_width())
self.blueBox.set_y(event.ydata - .5 * self.blueBox.get_height())
#**********************************************************************#
def setVisible(self):
""" Make BlueBox visible and refresh canvas """
self.blueBox.set_visible(True)
self.figure.canvas.draw()
#**********************************************************************#
def setGraphAttributes(self, axes, figure, listDT):
""" Tell each BlueBox about the graph attributes it needs """
self.axes = axes
self.figure = figure
self.listDT = listDT
#**************************************************************************#
class MyPopupMenu(BlueBox):
""" Class to handle right clicks """
def __init__(self):
BlueBox.__init__(self)
#**********************************************************************#
def setup(self):
""" Set up graph and BlueBox """
self.setupGraph()
# Bind right clicks to open the popup menu
self.canvas.Bind(wx.EVT_RIGHT_DOWN,
self.createPopupMenu)
# Create lists for BlueBoxs and binding IDs
self.listDT = []
self.listBID = []
self.popupCreateNew = wx.NewId()
self.menu = wx.Menu()
self.cn = self.menu.Append(self.popupCreateNew,
"Make a new box")
self.Bind(wx.EVT_MENU, self.createNew, self.cn)
# Make the first BlueBox
self.newBox()
# Connect close events to delete everything
self.figure.canvas.mpl_connect('close_event', self.deleteAll)
#**********************************************************************#
def deleteAll(self, event):
""" Close out of the program cleanly """
self.Destroy()
sys.exit(0)
#**********************************************************************#
def createPopupMenu(self, event):
""" Create all parts of the right-click popup menu """
self.PopupMenu(self.menu)
#**********************************************************************#
def newBox(self):
""" Make a new BlueBox """
self.listDT.append(BlueBox())
self.listDT[len(self.listDT)-1].setGraphAttributes(self.axes,
self.figure, self.listDT)
self.listDT[len(self.listDT)-1].setupBlueBox()
self.listBID.append(self.figure.canvas.mpl_connect('button_press_event',
self.listDT[len(self.listDT)-1].onPick))
#**********************************************************************#
def createNew(self, event):
""" Create a new BlueBox """
event.Skip()
self.newBox()
if len(self.listBID) > 1:
self.figure.canvas.mpl_disconnect(self.listBID[len(self.listBID)-2])
#**************************************************************************#
class app(wx.App):
""" Create and show all """
def OnInit(self):
self.mpm = MyPopupMenu()
self.mpm.setup()
self.frame = self.mpm.Show()
return True
#**************************************************************************#
# Run the program
#**************************************************************************#
app = app(0)
app.MainLoop()
答案 0 :(得分:0)
使用app.Exit()
或app.ExitMainLoop()
代替退出主循环。
答案 1 :(得分:0)
对close事件和close事件函数(deleteAll())的绑定需要位于创建图形的类中。
工作代码如下。
#**************************************************************************#
# Set up a graph. A click creates a blue box. More blue boxes can be made
# by choosing "Make a new box" from right/click menu.
#**************************************************************************#
import wx
import matplotlib
matplotlib.use('WX')
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanv
from pylab import *
#**************************************************************************#
class MainCanvas(wx.Frame):
""" Class to set up graph """
def __init__(self):
wx.Frame.__init__(self,None,-1, 'Make Blue Boxes',size=(550,350))
self.Bind(wx.EVT_CLOSE, self.deleteAll)
#**********************************************************************#
def deleteAll(self,event):
sys.exit()
#**********************************************************************#
def setupGraph(self):
""" Set up window and graph """
self.definePlot()
self.canvas = FigCanv(self, -1, self.figure)
self.setSizer()
#**********************************************************************#
def definePlot(self):
""" Define attributes of graph """
self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
#**********************************************************************#
def setSizer(self):
""" Set the size of the graph """
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
self.SetSizer(self.sizer)
self.Fit()
#**************************************************************************#
class BlueBox(MainCanvas):
""" Class to set up BlueBox """
def __init__(self):
MainCanvas.__init__(self)
#**********************************************************************#
def setupBlueBox(self):
""" Blue box set up """
self.blueBox = patches.Rectangle((0, 0), 0.05, 0.05,
fc = "Blue", visible = False, zorder = 3)
# Set zorder so new boxes are in front of old
if len(self.listDT)>1:
oldz = self.listDT[len(self.listDT)-2].blueBox.get_zorder() + 3
self.listDT[len(self.listDT)-1].blueBox.set_zorder(oldz)
self.axes.add_patch(self.blueBox)
#**********************************************************************#
def onPick(self, event):
""" Behavior when graph is clicked """
# Refresh BlueBox position and coordinate text
self.refreshBlueBox(event)
# Set the current BlueBox visible
self.listDT[len(self.listDT)-1].setVisible()
#**********************************************************************#
def refreshBlueBox(self, event):
""" Blue box refresh """
# Center the BlueBox (Point Box) over the mouse click location
self.blueBox.set_x(event.xdata - .5 * self.blueBox.get_width())
self.blueBox.set_y(event.ydata - .5 * self.blueBox.get_height())
#**********************************************************************#
def setVisible(self):
""" Make BlueBox visible and refresh canvas """
self.blueBox.set_visible(True)
self.figure.canvas.draw()
#**********************************************************************#
def setGraphAttributes(self, axes, figure, listDT):
""" Tell each BlueBox about the graph attributes it needs """
self.axes = axes
self.figure = figure
self.listDT = listDT
#**************************************************************************#
class MyPopupMenu(BlueBox):
""" Class to handle right clicks """
def __init__(self):
BlueBox.__init__(self)
#**********************************************************************#
def setup(self):
""" Set up graph and BlueBox """
self.setupGraph()
# Bind right clicks to open the popup menu
self.canvas.Bind(wx.EVT_RIGHT_DOWN,
self.createPopupMenu)
# Create lists for BlueBoxs and binding IDs
self.listDT = []
self.listBID = []
self.popupCreateNew = wx.NewId()
self.menu = wx.Menu()
self.cn = self.menu.Append(self.popupCreateNew,
"Make a new box")
self.Bind(wx.EVT_MENU, self.createNew, self.cn)
# Make the first BlueBox
self.newBox()
#**********************************************************************#
def createPopupMenu(self, event):
""" Create all parts of the right-click popup menu """
self.PopupMenu(self.menu)
#**********************************************************************#
def newBox(self):
""" Make a new BlueBox """
self.listDT.append(BlueBox())
self.listDT[len(self.listDT)-1].setGraphAttributes(self.axes,
self.figure, self.listDT)
self.listDT[len(self.listDT)-1].setupBlueBox()
self.listBID.append(self.figure.canvas.mpl_connect('button_press_event',
self.listDT[len(self.listDT)-1].onPick))
#**********************************************************************#
def createNew(self, event):
""" Create a new BlueBox """
event.Skip()
self.newBox()
if len(self.listBID) > 1:
self.figure.canvas.mpl_disconnect(self.listBID[len(self.listBID)-2])
#**************************************************************************#
class app(wx.App):
""" Create and show all """
def OnInit(self):
self.mpm = MyPopupMenu()
self.mpm.setup()
self.frame = self.mpm.Show()
return True
#**************************************************************************#
# Run the program
#**************************************************************************#
app = app(0)
app.MainLoop()