2018/03/01

wxPython & XRC でパネルを動的追加する方法


2018/3/5 追記
より使い勝手の良い方法があったので、そちらの方法で実装しなおしたバージョンを作りました。
[wxPython &XRC でパネルを動的追加する方法 with Two Stage Creation | 穀風](https://kokufu.blogspot.com/2018/03/wxpython-with-two-stage-creation.html)
`Add Panel` ボタンをクリックすると動的に `MyPanel` を追加するサンプルを作りました。 `MyPanel` はラベルとボタンが一つずつあるだけのシンプルなもので、ボタンをクリックすると自パネルの背景が変わるというお遊びつきです全く役に立たない!
なお、`MyPanel` は [wxPython & XRC で Custom Frame を作る方法2種+α | 穀風](https://kokufu.blogspot.com/2018/03/wxpython-xrc-custom-frame-2.html) で紹介した方法で XRC から生成していますFrame も XRC から作れますが、今回は Panel が主役なのであえてコードで生成 ポイントは `Add()` でパネルを追加した後、`Layout()` を読んで再描画する必要があるという点ですむしろそれだけ。 これを行わないと、ウィンドウサイズが変わるなどの再描画イベントが走るまで表示が崩れてしまいます。 ```python `highlight: 25; from random import randrange import wx import wx.xrc as xrc class MyFrame(wx.Frame): def __init__(self, *args, **kw): super().__init__(*args, **kw) self.panels = [] self.sizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(self.sizer) # Add Panel ボタン button = wx.Button(self, label="Add Panel") button.Bind(wx.EVT_BUTTON, self.on_click) self.sizer.Add(button) def on_click(self, event): panel = MyPanel(self) panel.set_value(len(self.panels)) self.sizer.Add(panel, 1, wx.EXPAND) self.sizer.Layout() self.panels.append(panel) class MyPanel(wx.Panel): def __init__(self, *args, **kw): super().__init__(*args, **kw) this_panel = self class MyPanelXmlHandler(xrc.XmlResourceHandler): def CanHandle(self, node): return self.IsOfClass(node, "wxPanel") and node.GetAttribute('name') == 'top' def DoCreateResource(self): self.CreateChildren(this_panel) return this_panel res = xrc.XmlResource('MyPanel.xrc') res.InsertHandler(MyPanelXmlHandler()) res.LoadPanel(None, "top") self.text = xrc.XRCCTRL(self, 'text') self.button = xrc.XRCCTRL(self, 'button') self.button.Bind(wx.EVT_BUTTON, self.on_click) def set_value(self, value): self.text.SetLabel(str(value)) def on_click(self, event): # ボタンクリックで背景をランダムに変えるお遊び r = randrange(256) g = randrange(256) b = randrange(256) self.SetBackgroundColour([r, g, b]) def main(): app = wx.App(False) frame = MyFrame(None) frame.Show() app.MainLoop() if __name__ == '__main__': main() ``` ```xml `title: "MyPanel.xrc"; <?xml version="1.0" ?> <resource> <object class="wxPanel" name="top"> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxBoxSizer"> <object class="sizeritem"> <object class="wxStaticText" name="text"/> </object> <object class="sizeritem"> <object class="wxButton" name="button"> <label>Click me!</label> </object> </object> <orient>wxHORIZONTAL</orient> </object> <option>1</option> <flag>wxALIGN_CENTRE_HORIZONTAL</flag> </object> </object> </object> </resource> ```

0 件のコメント: