1

私は独学で (Wx) Python を教えていますが、行き詰まってしまいました。ほとんどのコードを含む TestFrame 内に一連の繰り返し情報を持つ子ウィンドウを作成したいと考えています。問題は、コードに 1 つのウィジェットしか表示されないことです。私にとって重要な順に、次のことを理解しようとしています。

**このコードはこのページの拡張機能であることに注意してください。*

  1. 「AddBox」クラスの複数のウィジェットが正しく表示されるようにするにはどうすればよいですか?
  2. ウィンドウのサイズを変更すると、添付の画面のようにボタンの画像が破損します。どうすればこれを修正できますか?
  3. これらの動的に作成されたウィジェットのそれぞれをどのように呼び出し/バインドしますか?
  4. おまけ:「OnSize」モジュールはここで必要ですか?

ご協力ありがとうございました。許可/適切であれば、私に PM を送信していただければ、Paypal 経由で当選者に 5 ドルを寄付します。

import wx

class AddBox(wx.Window):
    def __init__(self, parent):
        wx.Window.__init__(self, parent)        

        pbox = wx.BoxSizer(wx.VERTICAL)

        controlback = wx.Button(self, label="Back")
        controlforward = wx.Button(self, label="Forward")

        pbox.AddMany([(controlback, 1, wx.ALL), (controlforward, 1, wx.ALL)])

class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1, size=(1000, 550))

        self.Bind(wx.EVT_SIZE, self.OnSize)

        pbox0 = wx.BoxSizer(wx.VERTICAL)
        controlback0 = wx.Button(self, label="Back0")
        controlforward0 = wx.Button(self, label="Forward0")
        pbox0.AddMany([(controlback0, 1, wx.ALL), (controlforward0, 1, wx.ALL)])
        pbox2 = wx.BoxSizer(wx.VERTICAL)

        self.scrolling_window = wx.ScrolledWindow( self )
        self.scrolling_window.SetScrollRate(1,6)
        self.scrolling_window.EnableScrolling(True,True)
        self.sizer_container = wx.BoxSizer( wx.VERTICAL )
        self.sizer = wx.BoxSizer( wx.VERTICAL )
        self.sizer_container.Add(self.sizer,1,wx.CENTER,wx.EXPAND)
        self.child_windows = []
        for i in range(0,8):
            wind = AddBox(self.scrolling_window)
            self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
            self.child_windows.append(wind)

        self.scrolling_window.SetSizer(self.sizer_container)
        #self.Layout() #not needed?


        pbox2.AddMany([(self.sizer_container, 1, wx.ALL)])

    def OnSize(self, event):
        self.scrolling_window.SetSize(self.GetClientSize())

if __name__=='__main__':
    app = wx.PySimpleApp()
    f = TestFrame()
    f.Show()
    app.MainLoop()
4

2 に答える 2

1

ここのコードはかなり複雑で、理解するのが困難です。wx.Window を使用する必要はほとんどありません。実際、wxPython を 6 年近く使用していますが、直接使用したことはありません。PySimpleApp も非推奨です。とにかく、私はコードをまとめて整理し、以下でやり直しました。これがあなたが探しているものかどうかはわかりません。また、後者の方が使いやすいと思うので、ScrolledPanel の ScrolledWindow を交換したことにも注意してください。

import wx
import  wx.lib.scrolledpanel as scrolled

class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, size=(1000, 550))
        panel = wx.Panel(self)

        mainSizer = wx.BoxSizer(wx.VERTICAL)
        pbox0 = wx.BoxSizer(wx.VERTICAL)
        controlback0 = wx.Button(panel, label="Back0")
        controlforward0 = wx.Button(panel, label="Forward0")
        pbox0.Add(controlback0, 0, wx.ALL)
        pbox0.Add(controlforward0, 0, wx.ALL)
        mainSizer.Add(pbox0)

        self.scrolling_window = scrolled.ScrolledPanel( panel )
        self.scrolling_window.SetAutoLayout(1)
        self.scrolling_window.SetupScrolling()
        self.sizer = wx.BoxSizer( wx.VERTICAL )
        self.child_windows = []
        for i in range(0,8):
            wind = self.addBox()
            self.sizer.Add(wind, 0, wx.CENTER|wx.ALL, 5)
        self.scrolling_window.SetSizer(self.sizer)

        mainSizer.Add(self.scrolling_window, 1, wx.EXPAND)
        panel.SetSizer(mainSizer)

    def addBox(self):
        pbox = wx.BoxSizer(wx.VERTICAL)

        controlback = wx.Button(self.scrolling_window, label="Back")
        controlforward = wx.Button(self.scrolling_window, label="Forward")

        pbox.AddMany([(controlback, 0, wx.ALL), (controlforward, 0, wx.ALL)])
        return pbox

    def OnSize(self, event):
        self.scrolling_window.SetSize(self.GetClientSize())

if __name__=='__main__':
    app = wx.App(False)
    f = TestFrame()
    f.Show()
    app.MainLoop()

Widget Inspection Tool も参照してください。次のようなレイアウトの問題を把握するのに役立ちます: http://wiki.wxpython.org/Widget%20Inspection%20Tool

編集: 上記のコードは項目 #1 と 2 を処理していると思います。#3 については、昨年書いた次の記事を参照してください。 -複数のウィジェットから同じハンドラへ/

基本的に、ループ自体にバインドしてから、イベント ハンドラーで event.GetEventObject() を使用して、呼び出し元のウィジェットを返し、その値などを設定できます。4 番目の質問については、いいえ、OnSize メソッドは必要ありません。wxPython でそれをオーバーライドする必要はほとんどありません。サンプル コードでは確かにオーバーライドしませんでした。

于 2012-04-20T14:35:37.107 に答える
0

今のところ 3 に対する答えがあります。動的に作成された各ウィジェットに ID を割り当て、この ID を辞書 ({id : widget }) に保存し、コールバック関数としてラムダ関数を渡すか、functools.partial を使用して「実際の」コールバックへの ID。(もちろん、ウィジェットをラムダ関数に直接渡すこともできますが、いつかこれらにアクセスする必要がある場合は、作成されたウィジェットのインスタンスをどこかに置くのが好きです)

    def __init__(...):
    self.event_dispatch = dict()

    ...

    for id in xrange(500, 508):
        wind = AddBox(self.scrolling_window, id)
        ...
        self.event_dispatch[id] = wind
        self.scrolling_window.Bind(wx.MY_EVENT, lambda evt: self.on_event(evt, id), id=id)


def on_event(event, id):
    widget = self.event_dispatch[id]
    # do something with widget
于 2012-04-20T14:38:19.227 に答える