将笔记本放在wxpython中的splitterwindow上

时间:2014-02-04 07:48:13

标签: python user-interface wxpython

当我尝试运行下面的代码时,我收到此错误:

Can't create window of class wxWindowNR (error 1406: cannot create a top-level child window.)

这是什么问题?

代码:

import os
import sys
import wx
from datetime import datetime, timedelta

szflags = wx.EXPAND | wx.ALL
min_height = 50
height_ratio = 4
pborder = 10
lborder = 5

class TangoArtProvider(wx.ArtProvider):
    def __init__(self):
        super(TangoArtProvider, self).__init__()
        self.path = os.path.join(os.getcwd(), "icons")
        self.bmps = [bmp.replace('.png', '')
                    for bmp in os.listdir(self.path)
                    if bmp.endswith('.png')]
        print self.bmps

    def CreateBitmap(self, id, client=wx.ART_OTHER, size=wx.DefaultSize):
        if wx.Platform == '__WXGTK__':
            return wx.NullBitmap
        bmp = wx.NullBitmap
        if id in self.bmps:
                path = os.path.join(self.path, id+'.png')
                bmp = wx.Bitmap(path)
        else:
            pass
        return bmp   

class ChartPanel(wx.Panel):

    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        self.SetBackgroundColour('GREEN')

        self.st = wx.StaticText(self, label='CHART PANEL')

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.st, 0 , szflags , lborder)
        self.SetSizer(sizer)

class NotebookPage(wx.Panel):

    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)

        self.chartPanel = ChartPanel(self, name='Notebook_Page_ChartPanel')

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.chartPanel, height_ratio, szflags, pborder)
        self.SetSizer(sizer) 

class Notebook(wx.Notebook):

    def __init__(self, *args, **kwargs):
        wx.Notebook.__init__(self, *args, **kwargs)
        #self.SetBackgroundColour('PINK')

        self.nbPages = {}
        fleets = ["333"]
        page_ix = 0
        for fleet in fleets:
            self.nbPages[fleets.index(fleet)] = NotebookPage(self, name='NotebookPage0')

        for fleet in fleets:
            self.AddPage(self.nbPages[fleets.index(fleet)], fleet, True)




class ChartPanel(wx.Panel):

    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        #self.st = wx.StaticText(self, label='Chart Panel')

        self.noteBook = Notebook(self, name='Notebook')

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.noteBook, 1, szflags)
        self.SetSizer(sizer) 

class SettingsPanel(wx.Panel):

    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)

        self.st = wx.StaticText(self, label='Settings Panel')

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.st, 0, szflags)
        self.SetSizer(self.sizer)   

class OutputPanel(wx.Panel):

    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)

        self.st = wx.StaticText(self, label='Output Panel')

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.st, 0, szflags)
        self.SetSizer(self.sizer)         



class ProportionalSplitter(wx.SplitterWindow):
        def __init__(self,parent, id = -1, proportion=0.66, size = wx.DefaultSize, **kwargs):
                wx.SplitterWindow.__init__(self,parent,id,wx.Point(0, 0),size, **kwargs)
                self.SetMinimumPaneSize(50) #the minimum size of a pane.
                self.proportion = proportion
                if not 0 < self.proportion < 1:
                        raise ValueError, "proportion value for ProportionalSplitter must be between 0 and 1."
                self.ResetSash()
                self.Bind(wx.EVT_SIZE, self.OnReSize)
                self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged, id=id)
                ##hack to set sizes on first paint event
                self.Bind(wx.EVT_PAINT, self.OnPaint)
                self.firstpaint = True

        def SplitHorizontally(self, win1, win2):
                if self.GetParent() is None: return False
                return wx.SplitterWindow.SplitHorizontally(self, win1, win2,
                        int(round(self.GetParent().GetSize().GetHeight() * self.proportion)))

        def SplitVertically(self, win1, win2):
                if self.GetParent() is None: return False
                return wx.SplitterWindow.SplitVertically(self, win1, win2,
                        int(round(self.GetParent().GetSize().GetWidth() * self.proportion)))

        def GetExpectedSashPosition(self):
                if self.GetSplitMode() == wx.SPLIT_HORIZONTAL:
                        tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().height)
                else:
                        tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().width)
                return int(round(tot * self.proportion))

        def ResetSash(self):
                self.SetSashPosition(self.GetExpectedSashPosition())

        def OnReSize(self, event):
                "Window has been resized, so we need to adjust the sash based on self.proportion."
                self.ResetSash()
                event.Skip()

        def OnSashChanged(self, event):
                "We'll change self.proportion now based on where user dragged the sash."
                pos = float(self.GetSashPosition())
                if self.GetSplitMode() == wx.SPLIT_HORIZONTAL:
                        tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().height)
                else:
                        tot = max(self.GetMinimumPaneSize(),self.GetParent().GetClientSize().width)
                self.proportion = pos / tot
                event.Skip()

        def OnPaint(self,event):
                if self.firstpaint:
                        if self.GetSashPosition() != self.GetExpectedSashPosition():
                                self.ResetSash()
                        self.firstpaint = False
                event.Skip()

class MainFrame(wx.Frame):

    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)
        self.SetBackgroundColour('YELLOW')

        self.CreateStatusBar(2)
        self.SetStatusWidths([-2, -1])

        #=======================================================================
        # toolbar = self.CreateToolBar()
        # toolbar.SetToolBitmapSize((20,20))      
        # icon_size = (32,32)          
        # 
        # wx.ArtProvider.PushProvider(TangoArtProvider())
        # 
        # run = wx.ArtProvider.GetBitmap("forward", wx.ART_TOOLBAR, icon_size)
        # settings = wx.ArtProvider.GetBitmap("tools", wx.ART_TOOLBAR, icon_size)
        # quit = wx.ArtProvider.GetBitmap("quit", wx.ART_TOOLBAR, icon_size)
        # toolbar.AddSimpleTool(1, run, "Run", "Run the report")
        # toolbar.AddSimpleTool(2, settings, "Settings", "Change program settings")
        # toolbar.AddSimpleTool(3, quit, "Quit", "Exit Program")
        # 
        # toolbar.Realize()      
        #=======================================================================

        self.split1 = ProportionalSplitter(self,-1, 0.66)
        self.split2 = ProportionalSplitter(self.split1,-1, 0.50)

        print "line 200"
        self.rightpanel = ChartPanel(self.split1)
        self.rightpanel.SetBackgroundColour('cyan')
        print "line 203"
        self.topleftpanel = SettingsPanel(self.split2)
        self.topleftpanel.SetBackgroundColour('pink')
        print "line 206"
        self.bottomleftpanel = OutputPanel(self.split2)
        self.bottomleftpanel.SetBackgroundColour('sky Blue')

        ## add your controls to the splitters:
        self.split1.SplitVertically(self.split2, self.rightpanel)
        self.split2.SplitHorizontally(self.topleftpanel, self.bottomleftpanel)                  


class App(wx.App):

    def OnInit(self):
        self.mainFrame = MainFrame(None, 
            size=(1000, 80*10), 
            title='Report', name='MainFrame')

        wx.GetApp().SetTopWindow( self.mainFrame )

        self.mainFrame.Show()

        return True

def main(*args, **kwargs):
    """A nice place to process things before MainLoop"""
    global app

    import wx.lib.inspection

    app = App()
    #wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()


if __name__ == "__main__":
    app = None
    main() 

1 个答案:

答案 0 :(得分:1)

您的代码中存在无限循环:

ChartPanel - &gt;笔记本 - &gt; NotebookPage - &gt;的 ChartPanel