【问题标题】:unable to quit wxpython无法退出 wxpython
【发布时间】:2016-03-08 20:02:51
【问题描述】:

所以我想我知道我的问题是什么,但我似乎无法弄清楚如何解决它。我对 wxPython 比较陌生。我正在将终端脚本中的一些功能移动到 GUI 中,但似乎无法正确处理。我将 anaconda 用于我的 python 发行版,并为 GUI 添加了 wxPython。我希望用户能够将文件拖放到文本控件中,然后将文件内容导入数据框以使用 pandas 进行分析。到目前为止,一切都很愉快。除了程序不会退出的事实。我认为这与我如何定义窗口和框架有关。我已经从脚本中删除了大量的功能以帮助简化事情。请让我知道我错过了什么。

谢谢 泰勒

import wx
import os
#import pandas as pd
#import numpy as np
#import matplotlib.pyplot as ply
#from scipy.stats import linregress

class MyFileDropTarget(wx.FileDropTarget):

    #----------------------------------------------------------------------
    def __init__(self, window):
        wx.FileDropTarget.__init__(self)
        self.window = window

    #----------------------------------------------------------------------
    def OnDropFiles(self, x, y, filenames):
        self.window.SetInsertionPointEnd(y)
        #self.window.updateText("\n%d file(s) dropped at %d,%d:\n" %
        #                   (len(filenames), x, y), y)
        for filepath in filenames:
            self.window.updateText(filepath + '\n', y)  

class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        file_drop_target = MyFileDropTarget(self)
        self.CreateStatusBar() # A Statusbar in the bottom of the window

        # Creating the menubar.
        menubar = wx.MenuBar()
        fileMenu = wx.Menu()
        helpMenu = wx.Menu()

        menubar.Append(fileMenu, '&File')
        menuOpen = fileMenu.Append(wx.ID_OPEN, "&Open"," Open a file to edit")
        #self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
        fileMenu.AppendSeparator()
        menuExit = fileMenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)

        menubar.Append(helpMenu, '&Help')
        menuAbout= helpMenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)

        self.SetMenuBar(menubar)

        #Create some sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        grid = wx.GridBagSizer(hgap=5, vgap=5)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)

        #Create a button
        self.button = wx.Button(self, label="Test")
        #self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)

        # Radio Boxes
        sysList = ['QEXL','QEX10','QEX7']
        wlList = ['1100', '1400', '1800']
        sys = wx.RadioBox(self, label="What system are you calibrating ?", pos=(20, 40), choices=sysList,  majorDimension=3,
                        style=wx.RA_SPECIFY_COLS)
        grid.Add(sys, pos=(1,0), span=(1,3))

        WL = wx.RadioBox(self, label="Maximum WL you currently Calibrating ?", pos=(20, 100), choices=wlList,  majorDimension=0,
                        style=wx.RA_SPECIFY_COLS)
        grid.Add(WL, pos=(2,0), span=(1,3))


        self.lblname = wx.StaticText(self, label="Cal File 1 :")
        grid.Add(self.lblname, pos=(3,0))
        self.Cal_1 = wx.TextCtrl(self, name="Cal_1", value="", size=(240,-1))
        self.Cal_1.SetDropTarget(file_drop_target)
        grid.Add(self.Cal_1, pos=(3,1))

        self.lblname = wx.StaticText(self, label="Cal File 2 :")
        grid.Add(self.lblname, pos=(4,0))
        self.Cal_2 = wx.TextCtrl(self, value="", name="Cal_2", size=(240,-1))
        self.Cal_2.SetDropTarget(file_drop_target)
        grid.Add(self.Cal_2, pos=(4,1))

        self.lblname = wx.StaticText(self, label="Cal File 3 :")
        grid.Add(self.lblname, pos=(5,0))
        self.Cal_3 = wx.TextCtrl(self, value="", name="Cal_3", size=(240,-1))
        self.Cal_3.SetDropTarget(file_drop_target)
        grid.Add(self.Cal_3, pos=(5,1))

        hSizer.Add(grid, 0, wx.ALL, 5)

        mainSizer.Add(hSizer, 0, wx.ALL, 5)
        mainSizer.Add(self.button, 0, wx.CENTER)
        self.SetSizerAndFit(mainSizer)


        self.Show(True)

    def OnAbout(self,e):
        # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
        dlg = wx.MessageDialog( self, "A quick test to see if your scans pass repeatability", "DOMA-64 Tester", wx.OK)
        dlg.ShowModal() # Show it
        dlg.Destroy() # finally destroy it when finished.

    def OnExit(self,e):
        # Close the frame.
        self.Close(True)

    def SetInsertionPointEnd(self, y):
        if y <= -31:
            self.Cal_1.SetInsertionPointEnd()
        elif y >= -1:
            self.Cal_3.SetInsertionPointEnd()
        else:
            self.Cal_2.SetInsertionPointEnd()

    def updateText(self, text, y):
        if y <= -31:
            self.Cal_1.WriteText(text)
        elif y >= -1:
            self.Cal_3.WriteText(text)
        else:
            self.Cal_2.WriteText(text)  

app = wx.App(False)
frame = MainWindow(None, "Sample editor")
app.MainLoop()

【问题讨论】:

    标签: python python-2.7 user-interface wxpython


    【解决方案1】:

    问题在于您只创建了 MyFileDropTarget 类的一个实例,然后将同一对象分配给多个小部件。您似乎需要为每个小部件创建一个放置目标实例。我稍微重构了您的代码,但这是一种方法:

    import wx
    import os
    #import pandas as pd
    #import numpy as np
    #import matplotlib.pyplot as ply
    #from scipy.stats import linregress
    
    class MyFileDropTarget(wx.FileDropTarget):
    
        #----------------------------------------------------------------------
        def __init__(self, window):
            wx.FileDropTarget.__init__(self)
            self.window = window
    
        #----------------------------------------------------------------------
        def OnDropFiles(self, x, y, filenames):
            self.window.SetInsertionPointEnd(y)
            #self.window.updateText("\n%d file(s) dropped at %d,%d:\n" %
            #                   (len(filenames), x, y), y)
            for filepath in filenames:
                self.window.updateText(filepath + '\n', y)
    
    
    class MyPanel(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
            file_drop_target = MyFileDropTarget(self)
            file_drop_target2 = MyFileDropTarget(self)
            file_drop_target3 = MyFileDropTarget(self)
    
            #Create some sizers
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            grid = wx.GridBagSizer(hgap=5, vgap=5)
            hSizer = wx.BoxSizer(wx.HORIZONTAL)
    
            #Create a button
            self.button = wx.Button(self, label="Test")
            #self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
    
            # Radio Boxes
            sysList = ['QEXL','QEX10','QEX7']
            wlList = ['1100', '1400', '1800']
            sys = wx.RadioBox(self, label="What system are you calibrating ?", 
                              pos=(20, 40), choices=sysList,  majorDimension=3,
                              style=wx.RA_SPECIFY_COLS)
            grid.Add(sys, pos=(1,0), span=(1,3))
    
            WL = wx.RadioBox(self, label="Maximum WL you currently Calibrating ?",
                             pos=(20, 100), choices=wlList,  majorDimension=0,
                             style=wx.RA_SPECIFY_COLS)
            grid.Add(WL, pos=(2,0), span=(1,3))
    
    
            self.lblname = wx.StaticText(self, label="Cal File 1 :")
            grid.Add(self.lblname, pos=(3,0))
            self.Cal_1 = wx.TextCtrl(self, name="Cal_1", value="", size=(240,-1))
            self.Cal_1.SetDropTarget(file_drop_target)
            grid.Add(self.Cal_1, pos=(3,1))
    
            self.lblname = wx.StaticText(self, label="Cal File 2 :")
            grid.Add(self.lblname, pos=(4,0))
            self.Cal_2 = wx.TextCtrl(self, value="", name="Cal_2", size=(240,-1))
            self.Cal_2.SetDropTarget(file_drop_target2)
            grid.Add(self.Cal_2, pos=(4,1))
    
            self.lblname = wx.StaticText(self, label="Cal File 3 :")
            grid.Add(self.lblname, pos=(5,0))
            self.Cal_3 = wx.TextCtrl(self, value="", name="Cal_3", size=(240,-1))
            self.Cal_3.SetDropTarget(file_drop_target3)
            grid.Add(self.Cal_3, pos=(5,1))
    
            hSizer.Add(grid, 0, wx.ALL, 5)
    
            mainSizer.Add(hSizer, 0, wx.ALL, 5)
            mainSizer.Add(self.button, 0, wx.CENTER)
            self.SetSizer(mainSizer)
    
    
    
    class MainWindow(wx.Frame):
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent, title=title, size=(400,400))
            panel = MyPanel(self)
    
            self.CreateStatusBar() # A Statusbar in the bottom of the window
    
            # Creating the menubar.
            menubar = wx.MenuBar()
            fileMenu = wx.Menu()
            helpMenu = wx.Menu()
    
            menubar.Append(fileMenu, '&File')
            menuOpen = fileMenu.Append(wx.ID_OPEN, "&Open"," Open a file to edit")
            #self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
            fileMenu.AppendSeparator()
            menuExit = fileMenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
            self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
    
            menubar.Append(helpMenu, '&Help')
            menuAbout= helpMenu.Append(wx.ID_ABOUT, "&About",
                                       " Information about this program")
            self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
    
            self.SetMenuBar(menubar)
    
            self.Show(True)
    
        def OnAbout(self,e):
            # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
            dlg = wx.MessageDialog( self, "A quick test to see if your scans pass repeatability", "DOMA-64 Tester", wx.OK)
            dlg.ShowModal() # Show it
            dlg.Destroy() # finally destroy it when finished.
    
        def OnExit(self,e):
            # Close the frame.
            #del self.fdt
            self.Close(True)
    
    
    
    
    
    app = wx.App(False)
    frame = MainWindow(None, "Sample editor")
    app.MainLoop()
    

    UPDATE 2016.03.09 - 我决定发布 OP 解决方案的重构版本:

    import wx
    import os
    #import pandas as pd
    #import numpy as np
    #import matplotlib.pyplot as ply
    #from scipy.stats import linregress
    
    class MyFileDropTarget(wx.FileDropTarget):
    
        #----------------------------------------------------------------------
        def __init__(self, obj):
            wx.FileDropTarget.__init__(self)
            self.obj = obj
    
        #----------------------------------------------------------------------
        def OnDropFiles(self, x, y, filenames):
            #self.obj.SetInsertionPointEnd(y)
            #self.obj.WriteText("\n%d file(s) dropped at %d,%d:\n" %
            #                   (len(filenames), x, y))
            for filepath in filenames:
                self.obj.WriteText(filepath + '\n')
    
    
    class MyPanel(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
    
            #Create some sizers
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            grid = wx.GridBagSizer(hgap=5, vgap=5)
            hSizer = wx.BoxSizer(wx.HORIZONTAL)
    
            #Create a button
            self.button = wx.Button(self, label="Test")
            #self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
    
            # Radio Boxes
            sysList = ['QEXL','QEX10','QEX7']
            wlList = ['1100', '1400', '1800']
            sys = wx.RadioBox(self, label="What system are you calibrating ?",
                            pos=(20, 40), choices=sysList,  majorDimension=3,
                            style=wx.RA_SPECIFY_COLS)
            grid.Add(sys, pos=(1,0), span=(1,3))
    
            WL = wx.RadioBox(self, label="Maximum WL you currently Calibrating ?",
                            pos=(20, 100), choices=wlList,  majorDimension=0,
                            style=wx.RA_SPECIFY_COLS)
            grid.Add(WL, pos=(2,0), span=(1,3))
    
            x = 3
            for widget in range(1, 4):
                lbl = wx.StaticText(self, label="Cal File {} :".format(widget))
                grid.Add(lbl, pos=(x,0))
                txt = wx.TextCtrl(self, name="Cal_{}".format(widget),
                                         value="", size=(240,-1))
                dt = MyFileDropTarget(txt)
                txt.SetDropTarget(dt)
                grid.Add(txt, pos=(x,1))
                x += 1
    
            hSizer.Add(grid, 0, wx.ALL, 5)
    
            mainSizer.Add(hSizer, 0, wx.ALL, 5)
            mainSizer.Add(self.button, 0, wx.CENTER)
            self.SetSizer(mainSizer)
    
    
    class MainWindow(wx.Frame):
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent, title=title, size=(400,400))
            panel = MyPanel(self)
    
            self.CreateStatusBar() # A Statusbar in the bottom of the window
    
            # Creating the menubar.
            menubar = wx.MenuBar()
            fileMenu = wx.Menu()
            helpMenu = wx.Menu()
    
            menubar.Append(fileMenu, '&File')
            menuOpen = fileMenu.Append(wx.ID_OPEN, "&Open"," Open a file to edit")
            #self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
            fileMenu.AppendSeparator()
            menuExit = fileMenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
            self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
    
            menubar.Append(helpMenu, '&Help')
            menuAbout= helpMenu.Append(wx.ID_ABOUT, "&About",
                                    " Information about this program")
            self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
    
            self.SetMenuBar(menubar)
    
            self.Show(True)
    
        def OnAbout(self,e):
            # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
            dlg = wx.MessageDialog( self, "A quick test to see if your scans pass repeatability", "DOMA-64 Tester", wx.OK)
            dlg.ShowModal() # Show it
            dlg.Destroy() # finally destroy it when finished.
    
        def OnExit(self,e):
            # Close the frame.
            #del self.fdt
            self.Close(True)
    
    
    app = wx.App(False)
    frame = MainWindow(None, "Sample editor")
    app.MainLoop()
    

    请注意,您可以使用循环来创建这些标签和文本小部件。

    【讨论】:

    • @TylerDenton 如果这回答了您的问题,也许您应该考虑“接受”它或将其标记为有用,或两者兼而有之!
    【解决方案2】:

    迈克,你的解决方案真的帮了我很多,谢谢。虽然它解决了窗口不关闭的问题,但它导致了引入文件和显示文件名的能力问题。我修改了您提供的代码,以便它对我有用,并将其发布在这里,以防其他人遇到类似的问题。这不是最优雅的解决方案,但它确实有效。再次感谢。

    import wx
    import os
    #import pandas as pd
    #import numpy as np
    #import matplotlib.pyplot as ply
    #from scipy.stats import linregress
    
    class MyFileDropTarget(wx.FileDropTarget):
    
        #----------------------------------------------------------------------
        def __init__(self, obj):
            wx.FileDropTarget.__init__(self)
            self.obj = obj
    
        #----------------------------------------------------------------------
        def OnDropFiles(self, x, y, filenames):
            #self.obj.SetInsertionPointEnd(y)
            #self.obj.WriteText("\n%d file(s) dropped at %d,%d:\n" %
            #                   (len(filenames), x, y))
            for filepath in filenames:
                self.obj.WriteText(filepath + '\n')
    
    
    class MyPanel(wx.Panel):
    
        def __init__(self, parent):
            wx.Panel.__init__(self, parent)
    
            #Create some sizers
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            grid = wx.GridBagSizer(hgap=5, vgap=5)
            hSizer = wx.BoxSizer(wx.HORIZONTAL)
    
            #Create a button
            self.button = wx.Button(self, label="Test")
            #self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
    
            # Radio Boxes
            sysList = ['QEXL','QEX10','QEX7']
            wlList = ['1100', '1400', '1800']
            sys = wx.RadioBox(self, label="What system are you calibrating ?", 
                            pos=(20, 40), choices=sysList,  majorDimension=3,
                            style=wx.RA_SPECIFY_COLS)
            grid.Add(sys, pos=(1,0), span=(1,3))
    
            WL = wx.RadioBox(self, label="Maximum WL you currently Calibrating ?",
                            pos=(20, 100), choices=wlList,  majorDimension=0,
                            style=wx.RA_SPECIFY_COLS)
            grid.Add(WL, pos=(2,0), span=(1,3))
    
    
            self.lblname = wx.StaticText(self, label="Cal File 1 :")
            grid.Add(self.lblname, pos=(3,0))
            self.Cal_1 = wx.TextCtrl(self, name="Cal_1", value="", size=(240,-1))
            Cal1 = MyFileDropTarget(self.Cal_1)
            self.Cal_1.SetDropTarget(Cal1)
            grid.Add(self.Cal_1, pos=(3,1))
    
            self.lblname = wx.StaticText(self, label="Cal File 2 :")
            grid.Add(self.lblname, pos=(4,0))
            self.Cal_2 = wx.TextCtrl(self, value="", name="Cal_2", size=(240,-1))
            Cal2 = MyFileDropTarget(self.Cal_2)
            self.Cal_2.SetDropTarget(Cal2)
            grid.Add(self.Cal_2, pos=(4,1))
    
            self.lblname = wx.StaticText(self, label="Cal File 3 :")
            grid.Add(self.lblname, pos=(5,0))
            self.Cal_3 = wx.TextCtrl(self, value="", name="Cal_3", size=(240,-1))
            Cal3 = MyFileDropTarget(self.Cal_3)
            self.Cal_3.SetDropTarget(Cal3)
            grid.Add(self.Cal_3, pos=(5,1))
    
            hSizer.Add(grid, 0, wx.ALL, 5)
    
            mainSizer.Add(hSizer, 0, wx.ALL, 5)
            mainSizer.Add(self.button, 0, wx.CENTER)
            self.SetSizer(mainSizer)
    
    
    class MainWindow(wx.Frame):
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent, title=title, size=(400,400))
            panel = MyPanel(self)
    
            self.CreateStatusBar() # A Statusbar in the bottom of the window
    
            # Creating the menubar.
            menubar = wx.MenuBar()
            fileMenu = wx.Menu()
            helpMenu = wx.Menu()
    
            menubar.Append(fileMenu, '&File')
            menuOpen = fileMenu.Append(wx.ID_OPEN, "&Open"," Open a file to edit")
            #self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
            fileMenu.AppendSeparator()
            menuExit = fileMenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
            self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
    
            menubar.Append(helpMenu, '&Help')
            menuAbout= helpMenu.Append(wx.ID_ABOUT, "&About",
                                    " Information about this program")
            self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
    
            self.SetMenuBar(menubar)
    
            self.Show(True)
    
        def OnAbout(self,e):
            # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
            dlg = wx.MessageDialog( self, "A quick test to see if your scans pass repeatability", "DOMA-64 Tester", wx.OK)
            dlg.ShowModal() # Show it
            dlg.Destroy() # finally destroy it when finished.
    
        def OnExit(self,e):
            # Close the frame.
            #del self.fdt
            self.Close(True)
    
    
    app = wx.App(False)
    frame = MainWindow(None, "Sample editor")
    app.MainLoop()
    

    【讨论】:

    • 我更新了我的示例,加入了重构后的代码版本,以展示一种使其更紧凑的方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 2015-02-17
    • 1970-01-01
    • 2023-03-10
    • 2012-10-24
    • 2020-11-23
    • 1970-01-01
    相关资源
    最近更新 更多