窗口关闭不会关闭程序,即使调用绑定到窗口 close_event 的 sys.exit() 的函数也是如此。什么可能导致这种情况?
下面的程序设置一个图表,并在用户每次单击时显示一个蓝色框。 用户可以使用右键单击弹出菜单来制作更多框。当我实现弹出菜单(从而允许多个蓝色框)时,程序在窗口关闭时停止关闭。我将 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()
The program below sets up a graph and displays a blue box each time the user clicks.
A user can make more boxes using the right-click popup menu. When I implemented the popup menu (thus allowing multiple blue boxes) the program stopped closing on the window close. I connected a deleteAll() method to the canvas to force a sys.exit() on close, but the program still stays open. What am I doing wrong?
#**************************************************************************#
# 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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
app.Exit()
或app.ExitMainLoop()
退出主循环。Use
app.Exit()
orapp.ExitMainLoop()
to exit the main loop instead.到关闭事件和关闭事件函数 (deleteAll()) 的绑定需要位于创建图形的类中。
工作代码如下。
The binding to the close event and the close event function (deleteAll()) needed to be in the class where the graph was being created.
The working code is below.