wxpython wx.Notebook没有宽度

1 投票
1 回答
685 浏览
提问于 2025-04-17 13:38

我正在尝试创建一个项目工具,里面有一个 wx.Notebook,顶部有标签,底部有一个独立的面板。这个底部面板应该和 notebook 是分开的,切换标签时不应该改变底部面板的内容。当我只添加 notebook 的时候,它运行得很好,但当我同时添加我的底部面板(一个扩展自 wx.Panel 的面板)时,notebook 就被挤压了,像图片中显示的那样 这里

我有一个面板作为窗口,并将 notebook 和底部面板(叫做 BottomGroup,扩展自 wx.Panel)添加到不同的面板中。有人能发现问题吗?可能是和布局有关?我的窗口结构是这样的(不管标签的顺序是否正确):

class Window(wx.Frame):

def __init__(self, parent, title):

    wx.Frame.__init__(self, None, wx.ID_ANY, title)
    self.InitUI()


def InitUI(self):    

    menuBar = wx.MenuBar()
    menu = wx.Menu()
    menu_load = menu.Append(wx.ID_OPEN, 'Open', 'Open project')
    menu_save = menu.Append(wx.ID_SAVE, 'Save', 'Save project')
    menu_save_as = menu.Append(wx.ID_SAVEAS, 'Save as', 'Save project as')
    menu_exit = menu.Append(wx.ID_EXIT, 'Quit', 'Quit application')
    menuBar.Append(menu, '&File')
    self.SetMenuBar(menuBar)

    mainPanel = wx.Panel(self)

    self.noteBookPanel = wx.Panel(mainPanel)
    self.notebook = wx.Notebook(self.noteBookPanel)
    self.bottomPanel = wx.Panel(mainPanel)
    self.bottomGroup = BottomGroup(self.bottomPanel)

    mainSizer = wx.BoxSizer(wx.VERTICAL)

    self.pageNodePathsTables = PageNodesPathsTables(self.notebook)
    self.pageEscapeCriteria = PageEscapeCriteria(self.notebook)
    self.pageFileHandling = PageFileHandling(self.notebook)

    self.notebook.AddPage(self.pageNodePathsTables, "Define Paths and Nodes")
    self.notebook.AddPage(self.pageEscapeCriteria, "Define Escape Criteria")
    self.notebook.AddPage(self.pageFileHandling, "File Handling")

    mainSizer.Add(self.noteBookPanel,1,wx.TOP)
    mainSizer.Add(self.bottomGroup,1,wx.BOTTOM)

    self.Bind(wx.EVT_MENU, self.onSave, menu_save)
    self.Bind(wx.EVT_MENU, self.onLoad, menu_load)
    self.Bind(wx.EVT_MENU, self.OnQuit, menu_exit)

    self.SetDimensions(WindowOpenX,WindowOpenY,WindowWidth,WindowHeight) 
    self.Show(True)

更新:

我已经重构了我的代码,变成了这样(只显示重构的部分):

    self.notebook = wx.Notebook(self)
    self.bottomGroup = BottomGroup(self)

    self.setupMenu()

    #frameSizer = wx.GridBagSizer(rowGap,columnGap)
    #frameSizer.Add(self.notebook,pos=(0,0), span=(1,1),
    #              flag=wx.LEFT|wx.TOP|wx.EXPAND, border = 5)
    #frameSizer.Add(self.bottomGroup,pos=(1,0), span=(1,1),
    #              flag=wx.LEFT|wx.BOTTOM|wx.EXPAND, border = 5)

    frameSizer = wx.BoxSizer(wx.VERTICAL)
    frameSizer.Add(self.notebook, 2, wx.EXPAND)
    frameSizer.Add(self.bottomGroup,0)
    self.SetSizer(frameSizer)

其中 self.setupMenu() 定义如下:

def setupMenu(self):
    self.pageNodePathsTables = PageNodesPathsTables(self.notebook)
    self.pageEscapeCriteria = PageEscapeCriteria(self.notebook)
    self.pageFileHandling = PageFileHandling(self.notebook)
    self.pagePlotHistoryData = PagePlotHistoryData(self.notebook)
    self.pageCalculateEscape = PageCalculateEscape(self.notebook)

    self.notebook.AddPage(self.pageNodePathsTables, "Define Paths and Nodes")
    self.notebook.AddPage(self.pageEscapeCriteria, "Define Escape Criteria")
    self.notebook.AddPage(self.pageFileHandling, "File Handling")
    self.notebook.AddPage(self.pagePlotHistoryData, "Plot History Data")
    self.notebook.AddPage(self.pageCalculateEscape, "Calculate Escape")

这个比之前的代码清晰多了,也更容易理解。运行得很好,除了 bottomGroup 现在叠在了 notebook 上(也就是说,这两个元素都是从 wx.Frame 的左上角开始的)。我尝试过 wx.BoxSizerwx.GridBagLayout(如上面注释掉的部分)。你有什么建议吗?

我的 BottomGroup 定义如下:

class BottomGroup(wx.Panel):

def __init__(self,parent):
    wx.Panel.__init__(self,parent)
    panelSizer = wx.GridBagSizer(rowGap,columnGap)

    btnSaveProject = wx.Button(parent, label="Save project", size=(100,50))
    btnLoadProject = wx.Button(parent, label="Open project", size=(100,50))

    panelSizer.Add(btnSaveProject, pos=(0,0), span=(1,1),
                             flag=wx.EXPAND|wx.LEFT, border = borderWidth)
    panelSizer.Add(btnLoadProject, pos=(0,1), span=(1,1),
                             flag=wx.EXPAND|wx.LEFT, border = borderWidth)

    self.SetSizer(panelSizer)

我的主方法是这样的:

if __name__ == '__main__':
    app = wx.App()
    Window(None, WindowHeader)
    app.MainLoop()

1 个回答

1

我不想给你一个完整的解决方案,而是想给你一些关于用户界面编程的小建议。

你犯了个错误,就是创建了太多面板,但从来没有设置布局。在写用户界面代码之前,一定要先考虑你想创建的组件的结构(层级)。想想它们的布局。然后把代码写下来,按照局部原则分组:大概每一层的层级应该用几行代码来处理。

好吧,我们来应用这个原则。笔记本和底部面板在顶层:

wx.Frame  
 +- wx.NoteBook
     +- PageNodesPathsTables
     +- ...
 +- BottomGroup

在这个层级,所有的内容都可以用这四行简单的代码来完成:

sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 2, wx.EXPAND)
sizer.Add(self.bottomPanel, 0)
self.SetSizer(sizer)

显然你知道怎么正确使用 wx.NoteBook。非常重要的是调用 self.SetSizer(在你的代码中没有这个),因为否则框架不知道该用哪个布局来安排它的子组件。
你对将界面分成两半的要求很明确。这里有个小建议:不要做过多的嵌套。虽然这样可能更灵活(可以很容易地推迟),但目前并不需要。如果你这样做:

self.bottomPanel = wx.Panel(mainPanel)
self.bottomGroup = BottomGroup(self.bottomPanel)

你就引入了至少一层(self.bottomPanel),而这个层级只有一个子组件(self.bottomGroup),它不知道怎么布局它的子组件。去掉不必要的嵌套,你就能省去面板的创建、布局的创建、布局的分配等等。简化它会让你更快地了解整体结构。待办事项:

  • 重写你程序的这一部分。去掉多余的指令。
  • 确保每个面板都有一个布局。
  • 把菜单创建的部分重构到一个单独的方法中。
  • 窗口构造函数中的参数 parent 没有被使用。修复它。
  • 你的例子缺少主方法、导入等。下次提供一个 SSCCE

撰写回答