当我关闭我的主机时,如何避免我的程序保持 运行?
How can I avoid my program to keep running when I close my main frame?
我目前正在自学 wxPython 库。我想到了创建一个带有一个主框架的 GUI,它可以打开一个子框架。
我知道我可以通过将两个框架编译成相同的代码来做到这一点,但是对于我的项目,我需要将它们分开。
我成功地管理了子框架的打开和关闭,但不幸的是,它在我的父框架中产生了新问题。
这是我的代码:
wx_Practicing.py
import wx
import time
import wx_Practicing_child
import threading
import os
import sys
"""Class which defines my main frame."""
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# Click counter
self.click = 0
# Init of the opening variable which is set to 1 when a child frame is opened
self.OpenButtonFlag = 0
# Init of the frame child invoked by the parent frame
self.child = wx_Practicing_child.MainWindow_child()
self.child.label = "child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel = PanelMainWindow(self)
test_panel.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the main frame
btn_quit = wx.Button(test_panel, label ="Quit")
btn_quit.Bind(wx.EVT_BUTTON, self.OnQuit)
sizer_verti.Add(btn_quit)
# Button counting number of time you trigger it
btn_counter = wx.Button(test_panel, label="Click counter")
sizer_verti.Add(btn_counter)
btn_counter.Bind(wx.EVT_LEFT_DOWN, self.OnCount)
# Button opening the child frame
btn_new_frame = wx.Button(test_panel, label = "Open new frame",
pos=(100,100))
btn_new_frame.Bind(wx.EVT_LEFT_DOWN, self.OnNewFrame)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Frame displaying
self.Show()
def OnClose(self, event):
self.Destroy(True)
# Method used to close the parent frame
def OnQuit(self, event):
self.Destroy()
print("closed")
# Method used to count number of click
def OnCount(self, event):
self.click +=1
print(self.click)
# Method calling wx_Practicing_child.py to open a child frame
def OnNewFrame(self, event):
if self.child.OpenButtonFlag == 0 :
self.child = wx_Practicing_child.MainWindow_child()
self.child.label = "child"
print("Flag before",self.child.OpenButtonFlag)
self.child.Show()
print("new Frame opened")
self.child.OpenButtonFlag = 1
else :
print("Frame already launched, close the previous one and retry")
print("Flag after", self.child.OpenButtonFlag)
"""Class of the panel"""
class PanelMainWindow(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
test = wx.App(False)
frame = MainWindow()
test.MainLoop()
和wx_Practicing_child.py
import wx
import time
"""Classe définissant une frame (i.e la zone globale parente). Elle permet
de faire exister le panel et ses attributs."""
class MainWindow_child(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
self.OpenButtonFlag = 0
self.label = "Child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel_child = PanelMainWindow_child(self)
test_panel_child.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the frame
btn_quit = wx.Button(test_panel_child, label ="Quit")
btn_quit.Bind(wx.EVT_LEFT_DOWN, self.OnQuit)
sizer_verti.Add(btn_quit)
# Method used to quit the frame
def OnQuit(self, event):
self.OpenButtonFlag = 0
self.Destroy()
print("child print", self.OpenButtonFlag)
"""Class which defines a panel for the child frame"""
class PanelMainWindow_child(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
所以我的主要问题是,当我点击父框架(wx_practicing.py)上的"Quit"按钮或"x"框时,框架关闭了,但是程序不关机。经过几次尝试,我注意到这似乎是由 MainWindow 中的 self.child 声明引起的。
但是,我需要这个声明来允许 MainWindow 打开 MainWindow_child。
我试图在我的 MainWindow class 的 Onquit() 方法中添加一个 self.child.Close() 但它没有成功。
经过一些研究,我发现我可以使用 CloseEvent 处理程序,但我并没有真正理解它的用途和工作原理。
希望我说得够清楚了。
注意:两个程序都在同一个文件夹中。
欢迎使用 Whosebug
您的代码的问题在于您正在创建两个 MainWindow_child 实例。您可以通过在文件 wx_Practicing.py 中的每一行下方添加 print(self.child)
来查看这一点,例如 self.child = wx_Practicing_child.MainWindow_child()
。如果您现在 运行 您的代码并创建一个子框架,您会得到如下内容:
<wx_Practicing_child.MainWindow_child object at 0x102e078b8>
<wx_Practicing_child.MainWindow_child object at 0x1073373a8>
Flag before 0
new Frame opened
Flag after 1
上面的前两行意味着您有两个 MainWindow_child 实例,指针 self.child
仅指向其中一个。因此,当您使用 self.child.Destroy()
或以正常方式(红色 X 按钮)关闭子框架时,您只会破坏一个实例。另一个实例永远存在,因为你从不显示它,所以你不能按下关闭按钮来销毁它或使用 self.child.Destroy()
因为 self.child 指向不同的对象。永远活着的子框架是您的程序永远不会关闭的原因。
为了更清楚,如果将 wx_Practicing.py 中的 OnQuit()
和 OnClose()
方法更改为:
def OnClose(self, event):
try:
self.child.Destroy()
except Exception:
pass
self.Destroy()
# Method used to close the parent frame
def OnQuit(self, event):
try:
self.child.Destroy()
except Exception:
pass
self.Destroy()
print("closed")
如果您不按Open new frame
按钮,程序将关闭,因为self.child
指向子框架的唯一实例。一旦你按下按钮,你就会有两个实例,其中一个没有显示并且没有指针,程序不再关闭。
用 parent
调用 child window 即
self.child = wx_Practicing_child.MainWindow_child(self)
在 child 中声明 parent 即
class MainWindow_child(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
现在 child 将在 parent 被销毁时被销毁,程序将干净地退出。
我认为 test_panel_child = PanelMainWindow_child(self)
是某种编辑错误,实际上应该是 test_panel_child = wx.Panel(self)
。
使用self.Destroy()
不self.Destroy(True)
另一种方法是不执行对child帧的初始调用并将child打开标志移动到parent.
为此,child 需要记下 parent 并确保 child 打开标志不仅在退出按钮上而且在 [=57= 上都设置为 false ] 关闭在顶部 right-hand 角。
这样你的主程序就变成了这样:
import wx
import time
import wx_Practicing_child
import threading
import os
import sys
"""Class which defines my main frame."""
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(400,350), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# Click counter
self.click = 0
# Init of the opening variable which is set to 1 when a child frame is opened
self.OpenButtonFlag = 0
# Init of the frame child invoked by the parent frame
#self.child = wx_Practicing_child.MainWindow_child(self)
#self.child.label = "child"
self.child_open_flag = False
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel = PanelMainWindow(self)
test_panel.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the main frame
btn_quit = wx.Button(test_panel, label ="Quit")
btn_quit.Bind(wx.EVT_BUTTON, self.OnQuit)
sizer_verti.Add(btn_quit)
# Button counting number of time you trigger it
btn_counter = wx.Button(test_panel, label="Click counter")
sizer_verti.Add(btn_counter)
btn_counter.Bind(wx.EVT_LEFT_DOWN, self.OnCount)
# Button opening the child frame
btn_new_frame = wx.Button(test_panel, label = "Open new frame",
pos=(100,100))
btn_new_frame.Bind(wx.EVT_LEFT_DOWN, self.OnNewFrame)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Frame displaying
self.Show()
def OnClose(self, event):
self.Destroy()
# Method used to close the parent frame
def OnQuit(self, event):
self.Destroy()
print("closed")
# Method used to count number of click
def OnCount(self, event):
self.click +=1
print(self.click)
# Method calling wx_Practicing_child.py to open a child frame
def OnNewFrame(self, event):
if self.child_open_flag:
wx.MessageBox("Frame already launched, close the previous one and retry",'Error', wx.OK | wx.ICON_INFORMATION)
else:
self.child = wx_Practicing_child.MainWindow_child(self)
self.child.label = "child"
self.child.Show()
self.child_open_flag = True
"""Class of the panel"""
class PanelMainWindow(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
test = wx.App(False)
frame = MainWindow()
test.MainLoop()
和您的 child 程序
import wx
import time
"""Classe définissant une frame (i.e la zone globale parente). Elle permet
de faire exister le panel et ses attributs."""
class MainWindow_child(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, "Test", wx.DefaultPosition,
(200,250), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# make parent accessible
self.parent = parent
self.label = "Child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel_child = wx.Panel(self)
test_panel_child.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the frame
btn_quit = wx.Button(test_panel_child, label ="Quit")
btn_quit.Bind(wx.EVT_LEFT_DOWN, self.OnQuit)
#Reset the open flag if the child is closed not using the button
self.Bind(wx.EVT_CLOSE, self.OnQuit)
sizer_verti.Add(btn_quit)
# Method used to quit the frame
def OnQuit(self, event):
# clear the child open flag in the parent
self.parent.child_open_flag = False
self.Destroy()
我目前正在自学 wxPython 库。我想到了创建一个带有一个主框架的 GUI,它可以打开一个子框架。
我知道我可以通过将两个框架编译成相同的代码来做到这一点,但是对于我的项目,我需要将它们分开。
我成功地管理了子框架的打开和关闭,但不幸的是,它在我的父框架中产生了新问题。
这是我的代码:
wx_Practicing.py
import wx
import time
import wx_Practicing_child
import threading
import os
import sys
"""Class which defines my main frame."""
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# Click counter
self.click = 0
# Init of the opening variable which is set to 1 when a child frame is opened
self.OpenButtonFlag = 0
# Init of the frame child invoked by the parent frame
self.child = wx_Practicing_child.MainWindow_child()
self.child.label = "child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel = PanelMainWindow(self)
test_panel.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the main frame
btn_quit = wx.Button(test_panel, label ="Quit")
btn_quit.Bind(wx.EVT_BUTTON, self.OnQuit)
sizer_verti.Add(btn_quit)
# Button counting number of time you trigger it
btn_counter = wx.Button(test_panel, label="Click counter")
sizer_verti.Add(btn_counter)
btn_counter.Bind(wx.EVT_LEFT_DOWN, self.OnCount)
# Button opening the child frame
btn_new_frame = wx.Button(test_panel, label = "Open new frame",
pos=(100,100))
btn_new_frame.Bind(wx.EVT_LEFT_DOWN, self.OnNewFrame)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Frame displaying
self.Show()
def OnClose(self, event):
self.Destroy(True)
# Method used to close the parent frame
def OnQuit(self, event):
self.Destroy()
print("closed")
# Method used to count number of click
def OnCount(self, event):
self.click +=1
print(self.click)
# Method calling wx_Practicing_child.py to open a child frame
def OnNewFrame(self, event):
if self.child.OpenButtonFlag == 0 :
self.child = wx_Practicing_child.MainWindow_child()
self.child.label = "child"
print("Flag before",self.child.OpenButtonFlag)
self.child.Show()
print("new Frame opened")
self.child.OpenButtonFlag = 1
else :
print("Frame already launched, close the previous one and retry")
print("Flag after", self.child.OpenButtonFlag)
"""Class of the panel"""
class PanelMainWindow(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
test = wx.App(False)
frame = MainWindow()
test.MainLoop()
和wx_Practicing_child.py
import wx
import time
"""Classe définissant une frame (i.e la zone globale parente). Elle permet
de faire exister le panel et ses attributs."""
class MainWindow_child(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
self.OpenButtonFlag = 0
self.label = "Child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel_child = PanelMainWindow_child(self)
test_panel_child.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the frame
btn_quit = wx.Button(test_panel_child, label ="Quit")
btn_quit.Bind(wx.EVT_LEFT_DOWN, self.OnQuit)
sizer_verti.Add(btn_quit)
# Method used to quit the frame
def OnQuit(self, event):
self.OpenButtonFlag = 0
self.Destroy()
print("child print", self.OpenButtonFlag)
"""Class which defines a panel for the child frame"""
class PanelMainWindow_child(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
所以我的主要问题是,当我点击父框架(wx_practicing.py)上的"Quit"按钮或"x"框时,框架关闭了,但是程序不关机。经过几次尝试,我注意到这似乎是由 MainWindow 中的 self.child 声明引起的。
但是,我需要这个声明来允许 MainWindow 打开 MainWindow_child。 我试图在我的 MainWindow class 的 Onquit() 方法中添加一个 self.child.Close() 但它没有成功。
经过一些研究,我发现我可以使用 CloseEvent 处理程序,但我并没有真正理解它的用途和工作原理。
希望我说得够清楚了。
注意:两个程序都在同一个文件夹中。
欢迎使用 Whosebug
您的代码的问题在于您正在创建两个 MainWindow_child 实例。您可以通过在文件 wx_Practicing.py 中的每一行下方添加 print(self.child)
来查看这一点,例如 self.child = wx_Practicing_child.MainWindow_child()
。如果您现在 运行 您的代码并创建一个子框架,您会得到如下内容:
<wx_Practicing_child.MainWindow_child object at 0x102e078b8>
<wx_Practicing_child.MainWindow_child object at 0x1073373a8>
Flag before 0
new Frame opened
Flag after 1
上面的前两行意味着您有两个 MainWindow_child 实例,指针 self.child
仅指向其中一个。因此,当您使用 self.child.Destroy()
或以正常方式(红色 X 按钮)关闭子框架时,您只会破坏一个实例。另一个实例永远存在,因为你从不显示它,所以你不能按下关闭按钮来销毁它或使用 self.child.Destroy()
因为 self.child 指向不同的对象。永远活着的子框架是您的程序永远不会关闭的原因。
为了更清楚,如果将 wx_Practicing.py 中的 OnQuit()
和 OnClose()
方法更改为:
def OnClose(self, event):
try:
self.child.Destroy()
except Exception:
pass
self.Destroy()
# Method used to close the parent frame
def OnQuit(self, event):
try:
self.child.Destroy()
except Exception:
pass
self.Destroy()
print("closed")
如果您不按Open new frame
按钮,程序将关闭,因为self.child
指向子框架的唯一实例。一旦你按下按钮,你就会有两个实例,其中一个没有显示并且没有指针,程序不再关闭。
用 parent
调用 child window 即
self.child = wx_Practicing_child.MainWindow_child(self)
在 child 中声明 parent 即
class MainWindow_child(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, "Test", wx.DefaultPosition,
(1000,850), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
现在 child 将在 parent 被销毁时被销毁,程序将干净地退出。
我认为 test_panel_child = PanelMainWindow_child(self)
是某种编辑错误,实际上应该是 test_panel_child = wx.Panel(self)
。
使用self.Destroy()
不self.Destroy(True)
另一种方法是不执行对child帧的初始调用并将child打开标志移动到parent.
为此,child 需要记下 parent 并确保 child 打开标志不仅在退出按钮上而且在 [=57= 上都设置为 false ] 关闭在顶部 right-hand 角。
这样你的主程序就变成了这样:
import wx
import time
import wx_Practicing_child
import threading
import os
import sys
"""Class which defines my main frame."""
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Test", wx.DefaultPosition,
(400,350), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# Click counter
self.click = 0
# Init of the opening variable which is set to 1 when a child frame is opened
self.OpenButtonFlag = 0
# Init of the frame child invoked by the parent frame
#self.child = wx_Practicing_child.MainWindow_child(self)
#self.child.label = "child"
self.child_open_flag = False
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel = PanelMainWindow(self)
test_panel.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the main frame
btn_quit = wx.Button(test_panel, label ="Quit")
btn_quit.Bind(wx.EVT_BUTTON, self.OnQuit)
sizer_verti.Add(btn_quit)
# Button counting number of time you trigger it
btn_counter = wx.Button(test_panel, label="Click counter")
sizer_verti.Add(btn_counter)
btn_counter.Bind(wx.EVT_LEFT_DOWN, self.OnCount)
# Button opening the child frame
btn_new_frame = wx.Button(test_panel, label = "Open new frame",
pos=(100,100))
btn_new_frame.Bind(wx.EVT_LEFT_DOWN, self.OnNewFrame)
self.Bind(wx.EVT_CLOSE, self.OnClose)
# Frame displaying
self.Show()
def OnClose(self, event):
self.Destroy()
# Method used to close the parent frame
def OnQuit(self, event):
self.Destroy()
print("closed")
# Method used to count number of click
def OnCount(self, event):
self.click +=1
print(self.click)
# Method calling wx_Practicing_child.py to open a child frame
def OnNewFrame(self, event):
if self.child_open_flag:
wx.MessageBox("Frame already launched, close the previous one and retry",'Error', wx.OK | wx.ICON_INFORMATION)
else:
self.child = wx_Practicing_child.MainWindow_child(self)
self.child.label = "child"
self.child.Show()
self.child_open_flag = True
"""Class of the panel"""
class PanelMainWindow(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
test = wx.App(False)
frame = MainWindow()
test.MainLoop()
和您的 child 程序
import wx
import time
"""Classe définissant une frame (i.e la zone globale parente). Elle permet
de faire exister le panel et ses attributs."""
class MainWindow_child(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, "Test", wx.DefaultPosition,
(200,250), wx.DEFAULT_FRAME_STYLE, wx.FrameNameStr)
# make parent accessible
self.parent = parent
self.label = "Child"
# Sizers
sizer_hori = wx.BoxSizer(wx.HORIZONTAL)
sizer_verti = wx.BoxSizer(wx.VERTICAL)
# Init of the panel
test_panel_child = wx.Panel(self)
test_panel_child.SetSizer(sizer_verti)
# Buttons declaration
# Button to quit the frame
btn_quit = wx.Button(test_panel_child, label ="Quit")
btn_quit.Bind(wx.EVT_LEFT_DOWN, self.OnQuit)
#Reset the open flag if the child is closed not using the button
self.Bind(wx.EVT_CLOSE, self.OnQuit)
sizer_verti.Add(btn_quit)
# Method used to quit the frame
def OnQuit(self, event):
# clear the child open flag in the parent
self.parent.child_open_flag = False
self.Destroy()