wxPython ScrolledPanel 在我调用面板上的任何方法时不显示小部件

问题描述 投票:0回答:1

在另一个面板中有两个面板(一个是ScrolledPanel)。最下面的是 ScrolledPanel,只要我调用 ScrolledPanel 上的任何方法,例如

panel.SetScrollRate(10, 10)
,所有小部件都会消失。注释掉该行,所有小部件都会重新出现。顶部面板始终显示良好。

我刚刚发现,如果我在 InspectionTool 中添加下面的行,它就会开始工作,但如果我在实际代码中包含该行,我就不会像以前一样得到任何小部件。

obj.SetupScrolling(rate_x=10, rate_y=10, scrollToTop=False)

class FieldEdit(wx.Panel):
    tmd = TomlMetaData()

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent
        self.title = '''Add/Remove Fields'''
        self._bg_color = (232, 213, 149)
        w_bg_color = (222, 237, 230)
        w_fg_color_0 = (50, 50, 204)
        w_fg_color_1 = (197, 75, 108)
        self.SetBackgroundColour(wx.Colour(*self._bg_color))
        # Setup sizers.
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        # Setup panels.
        kwargs = {'g_sizer': sizer, 'bg_color': self._bg_color,
                  'w_bg_color': w_bg_color, 'w_fg_color_0': w_fg_color_0,
                  'w_fg_color_1': w_fg_color_1}
        panel_top = self._panel_top(kwargs)
        sizer.Add(panel_top, 0, wx.EXPAND | wx.ALL, 6)

    def _panel_top(self, kwargs):
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(sizer)
        grid_sizer = wx.GridBagSizer(vgap=2, hgap=2)
        sizer.Add(grid_sizer, 0, wx.CENTER | wx.ALL, 6)
        w_bg_color = kwargs['w_bg_color']
        w_fg_color_0 = kwargs['w_fg_color_0']
        w_fg_color_1 = kwargs['w_fg_color_1']
        desc = wx.StaticText(panel, wx.ID_ANY, self._description, style=0)
        desc.SetForegroundColour(wx.Colour(*w_fg_color_1))
        desc.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                             wx.FONTWEIGHT_BOLD, 0, ''))
        grid_sizer.Add(desc, (0, 0), (1, 3), wx.ALIGN_CENTER | wx.ALL, 6)

        edit_names = self._edit_names
        kwargs['edit_names'] = edit_names
        edit_names.insert(0, 'Choose the Page to Edit')
        combo_box = wx.ComboBox(panel, wx.ID_ANY, value=edit_names[0],
                                choices=edit_names, style=wx.TE_READONLY)
        combo_box.SetBackgroundColour(wx.Colour(*w_bg_color))
        combo_box.SetForegroundColour(wx.Colour(*w_fg_color_0))
        combo_box.SetMinSize([196, 23])
        self.Bind(wx.EVT_COMBOBOX, self.selection_closure(kwargs), combo_box)
        grid_sizer.Add(combo_box, (1, 0), (1, 1),
                       wx.ALIGN_CENTER_VERTICAL | wx.ALL, 6)

        field_desc = wx.StaticText(panel, wx.ID_ANY, "Enter a new field name:",
                                   style=0)
        field_desc.SetForegroundColour(wx.Colour(*w_fg_color_0))
        field_desc.SetFont(
            wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                    wx.FONTWEIGHT_BOLD, 0, ''))
        grid_sizer.Add(field_desc, (2, 0), (1, 1), wx.ALL, 6)

        field_name = wx.TextCtrl(panel,  wx.ID_ANY, "", style=wx.TE_LEFT)
        field_name.SetBackgroundColour(wx.Colour(*w_bg_color))
        field_name.SetForegroundColour(wx.Colour(*w_fg_color_0))
        field_name.SetMinSize((200, 23))
        grid_sizer.Add(field_name, (2, 1), (1, 1), wx.ALL, 6)
        add_button = wx.Button(panel,  wx.ID_ANY, 'Add')
        add_button.SetMinSize((50, 23))
        add_button.SetBackgroundColour(wx.Colour(*w_bg_color))
        add_button.SetForegroundColour(wx.Colour(*w_fg_color_0))
        add_button.Bind(wx.EVT_BUTTON, self.add_button)
        grid_sizer.Add(add_button, (2, 2), (1, 1), wx.ALL, 6)

        line = wx.StaticLine(panel, wx.ID_ANY)
        line.SetBackgroundColour(wx.Colour(*w_fg_color_0))
        grid_sizer.Add(line, (3, 0), (1, 3), wx.EXPAND | wx.BOTTOM, 2)
        return panel

    def _panel_bot(self, kwargs):
        panel = ScrolledPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(sizer)
        grid_sizer = wx.GridBagSizer(vgap=2, hgap=2)
        sizer.Add(grid_sizer, 0, wx.CENTER | wx.ALL, 6)
        w_fg_color_0 = kwargs['w_fg_color_0']
        w_fg_color_1 = kwargs['w_fg_color_1']
        widget_labels = kwargs['widget_labels']

        for idx, label in enumerate(widget_labels):
            label = label.replace(r'\n', '\n')
            widget = wx.StaticText(panel, wx.ID_ANY, label)

            if label.endswith(':'):
                span = 1
                weight = 10
                color = w_fg_color_0
            else:
                span = 2
                weight = 12
                color = w_fg_color_1

            if '\n' in label:
                width = 46
            else:
                width = 23

            widget.SetFont(wx.Font(
                weight, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                wx.FONTWEIGHT_BOLD, 0, ''))
            widget.SetForegroundColour(wx.Colour(*color))
            widget.SetMinSize((-1, width))
            grid_sizer.Add(
                widget, (idx, 0), (1, span),
                wx.ALIGN_CENTER_VERTICAL | wx.LEFT | wx.RIGHT | wx.BOTTOM, 6)

        #panel.SetScrollRate(10, 10) # When uncommented the widgets do not display.

        kwargs['panel'] = panel
        return panel

    def selection_closure(self, kwargs):
        def get_selection(event):
            edit_names = kwargs['edit_names']
            chosen = event.GetString().lower()
            widget_labels = []

            if edit_names[0].lower() != chosen:
                items = self.tmd.panel_config.get(
                    chosen, {}).get('widgets', {})

                for value in items.values():
                    if (not isinstance(value, list)
                        or value[0] != 'StaticText'): continue
                    args = self._find_dict(value).get('args', [])
                    widget_labels.append(args[2])

                kwargs['widget_labels'] = widget_labels
                self._create_widgets(kwargs)
            else:
                self._destroy_panel(kwargs.get('panel'), kwargs.get('g_sizer'))

        return get_selection

    def _create_widgets(self, kwargs):
        g_sizer = kwargs['g_sizer']
        panel = kwargs.get('panel')
        # Destroy the previous panel if it exists.
        self._destroy_panel(panel, g_sizer)
        # Create a new panel.
        panel = self._panel_bot(kwargs)
        g_sizer.Add(panel, 0, wx.EXPAND | wx.ALL, 6)

    def _destroy_panel(self, panel, g_sizer):
        if g_sizer and panel:
            g_sizer.Remove(1)
            panel.Destroy()
            g_sizer.Layout()
python-3.x wxpython
1个回答
0
投票

我已经解决了主要问题。我必须做两件事才能让它正常工作。

首先,我在

_create_widgets
方法的末尾添加了以下行。

        wx.CallLater(100, panel.SetupScrolling, rate_x=10, rate_y=10)

其次,我必须创建一个在发生调整大小事件时运行的事件。下面的行或多或少被添加到

_panel_bot
方法的末尾。

        self.Bind(wx.EVT_SIZE, self.resize_closure(panel, grid_sizer))

我倾向于在调用事件时使用闭包,这样我就可以将其他变量传递到事件中。活动代码如下。

    def resize_closure(self, panel, grid_sizer):
        def on_size_change(event):
            width, height = grid_sizer.GetSize()

            if not width <= 1 or not height <= 1:
                panel.SetSizeHints(width, height)

        return on_size_change

这似乎解决了除一个问题之外的所有问题。我需要使用框架底部的状态栏,但是当我滚动到任何面板的底部时,最后一个小部件被状态栏部分覆盖。然而,这是一个不同的问题。

© www.soinside.com 2019 - 2024. All rights reserved.