wxPython - 将 BoxSizer 添加到 ScrolledPanel

问题描述

我正在构建一个窗口,我想在其中构建一个非常简单的日历。我是_organizeData 的循环,每次有新的月份时,我都想向GridSizer 添加一些按钮,GridSizer 位于顶部有文本的垂直框内。我想不通将此垂直 BoxSizer (vBox) 添加到 scrollPanel。 self.data 将是一个像这样的结构体,一个字典列表:

[{'date': '14-03-2021','xyValues': [[01:00,02:00,...],[18.5,17.2,...]]},...]

import wx
import wx.lib.scrolledpanel as scrolled

class GraphCalendar(wx.Frame):
    def __init__(self,parent,data):
        wx.Frame.__init__(self,parent)

        self.data = data
        self.consumption = []
        self.text = wx.StaticText(self,wx.ID_ANY,label="This is a test")
        self.scrollPanel = scrolled.ScrolledPanel(self,size=((400,600)),style=wx.SUNKEN_BORDER)
        self.scrollPanel.SetupScrolling()

        self.topVerticalBox = wx.BoxSizer(wx.VERTICAL)
        self.topVerticalBox.Add(self.text,flag=wx.EXPAND)
        self.topVerticalBox.Add(self.scrollPanel)

        self.Center()

        self._organizeData()

    def _organizeData(self):

        currentMonth = ''

        for i in range(0,len(self.data)):
            words = self.data[i]['date'].split('-')  # words -> [0]day,[1]month and [2]year.

            if currentMonth != words[1]:
                currentMonth = words[1]
                vBox = wx.BoxSizer(wx.VERTICAL)
                # Name of the month / year.
                text = wx.StaticText(self,f"{(words[1])} of {words[2]}")
                # Grid where the button of the days will be added
                gridSizer = wx.GridSizer(rows=5,cols=5,hgap=5,vgap=5)

                vBox.Add(text,wx.ID_ANY)
                vBox.Add(gridSizer,wx.ID_ANY)


            # Create the button of the day and add it to the gridSizer.
            button = wx.Button(self,1000 + i,label=words[0],size=((20,20)))
            button.Bind(wx.EVT_BUTTON,self.OnButtonClicked)
            gridSizer.Add(button,border=5)

        self.SetSizerAndFit(self.topVerticalBox)


    def OnButtonClicked(self,event):
        """ Funcao chamada quando um botao e apertado. """

        event.GetEventObject()
        print(event.GetId())

app = wx.App()
frame = GraphCalendar(None,data=[{'date': '14-03-2021','xyValues': [['01:00','02:00'],17.2]]},{'date': '15-04-2021',[19.5,18.2]]}])
frame.Show()
app.MainLoop()

这是所需的输出

Intended result

这是上面的代码产生的:

enter image description here

解决方法

我不知道这是否是最终解决方案,但它应该为您指明正确的方向。
我为滚动面板添加了一个额外的 sizer(如我的评论中所述),并在您将项目添加到 wx.ID_ANY 时删除了 proportionvBox 参数的错误分配(天知道sizer 认为 -31000 之类的比例)。

在开始之前,您可能需要考虑重组您的数据,因为这样做有点笨拙。

import wx
import wx.lib.scrolledpanel as scrolled

class GraphCalendar(wx.Frame):
    def __init__(self,parent,data):
        wx.Frame.__init__(self,parent)

        self.data = data
        self.consumption = []
        self.text = wx.StaticText(self,wx.ID_ANY,label="This is a test\nof my text placement above a calendar of sorts")
        self.text.SetBackgroundColour("lightgreen")
        self.scrollPanel = scrolled.ScrolledPanel(self,size=((400,600)),style=wx.SUNKEN_BORDER)
        self.scrollPanel.SetupScrolling()

        self.topVerticalBox = wx.BoxSizer(wx.VERTICAL)
        self.sp_vbox1 = wx.BoxSizer(wx.VERTICAL)

        self.scrollPanel.SetSizer(self.sp_vbox1)
        self._organizeData()
        
        self.topVerticalBox.Add(self.text,flag=wx.EXPAND)
        self.topVerticalBox.AddSpacer(10)
        self.topVerticalBox.Add(self.scrollPanel)
        self.SetSizer(self.topVerticalBox)

        self.Center()

    def _organizeData(self):

        currentMonth = ''

        for d in self.data:
            words = d['date'].split('-')  # words -> [0]day,[1]month and [2]year.

            if currentMonth != words[1]:
                if currentMonth != '':
                    self.sp_vbox1.Add(vBox)
                currentMonth = words[1]
                vBox = wx.BoxSizer(wx.VERTICAL)
                # Name of the month / year.
                text = wx.StaticText(self.scrollPanel,f"{(words[1])} of {words[2]}")
                # Grid where the button of the days will be added
                gridSizer = wx.GridSizer(rows=5,cols=5,hgap=5,vgap=5)

                vBox.Add(text)
                vBox.Add(gridSizer)


            # Create the button of the day and add it to the gridSizer.
            button = wx.Button(self.scrollPanel,label=words[0],size=((60,20)))
            button.Bind(wx.EVT_BUTTON,self.OnButtonClicked)
            gridSizer.Add(button,border=5)

        self.sp_vbox1.Add(vBox)


    def OnButtonClicked(self,event):
        """ Funcao chamada quando um botao e apertado. """

        event.GetEventObject()
        print(event.GetId())

app = wx.App()
frame = GraphCalendar(None,data=[{'date': '14-03-2021','xyValues': [['01:00','02:00'],[18.5,17.2]]},{'date': '15-04-2021',[19.5,18.2]]},{'date': '16-04-2021',{'date': '19-04-2021',{'date': '11-05-2021',{'date': '15-08-2021',18.2]]}])
frame.Show()
app.MainLoop()

enter image description here