2

接続を確立するこのプログラムがあります。接続しようとすると、ProgressDialog が作成されます。接続が失敗すると、ProgressDialog をきれいに閉じる必要がありますが、そうではなく、segfault が発生します。

問題のコードの縮小例を次に示します。このスクリプトを実行して Enter キーを数回押すと、この動作を再現できます。これにより、アプリの唯一のボタンがクリックされ、コードがトリガーされて接続が試行されます。

これまでのところ、アプリがクラッシュするのは行 53:'print('after_pulse')' が実行されていない場合のみであることがわかりました。これは、「Pulse」呼び出しに問題があることを示していますが、わかりません何を。

このコードがクラッシュする原因を知っている人はいますか?

そうでない場合、少なくともこの動作を再現できますか?

仕様:

Ubuntu 12.04

パイソン 2.7.3

wxPython 2.8.12.1

編集:ねじれたコードのないはるかに小さなサンプルプログラム。

#!/usr/bin/env python

'''test2'''

import wx   # Must be imported before any other wx modules


class TestFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title='TestFrame')
        self.button = wx.Button(self, label='test')
        self.button.Bind(wx.EVT_BUTTON, self.button_handler)
        self.button.SetFocus()

    def button_handler(self, event):
        pd_style = wx.PD_APP_MODAL|wx.PD_CAN_ABORT|wx.PD_SMOOTH
        self.pd = wx.ProgressDialog('test_title', 'test_msg', parent=self,  
                                    style=pd_style)
        self.pd.SetFocus()

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        self.timer.Start(1000/60, False)

        wx.CallAfter(self.err_connection)

    def on_timer(self, event):
        print('before_pulse')
        cont, _skip = self.pd.Pulse()
        print('after_pulse')
        if not cont:
            self.err_connection()

    def err_connection(self):
        print('err_connection')
        self.timer.Stop()
        self.pd.Destroy()
        self.button.SetFocus()


def main():
    app = wx.App()
    frame = TestFrame()
    frame.Show()
    app.MainLoop()


if __name__ == '__main__':
    main()
4

2 に答える 2

1

最後の Pulse() を実行している最中に、進行状況ダイアログを破棄していると思われます。一部のプラットフォームでは、特定の API の処理の一部を、最初の部分が完了した後などに延期することがあります。Destroy の呼び出しを遅らせると、おそらくより良い結果が得られます。試す:

wx.CallAfter(self.pd.Destroy)

また、UI 要素の更新などでは、1 秒あたり 60 回は非常に高速です。これは目に見えるよりもはるかに高速であり、ダイアログが破棄された後にタイマーイベントを取得して Pulse() を実行しようとするなど、一部のイベントがスタックし、ハンドラーが予期しない順序で呼び出される可能性があります。代わりに、1 秒あたり 10 回または 20 回試してください。

于 2012-07-21T18:52:26.177 に答える
0

ShowModal() が必要であることがわかりました。

dlg = wx.ProgressDialog(title, msg, maximum=100)
dlg.ShowModal()
dlg.Update(0, "Please Wait...")
...
dlg.Destroy()

ShowModal() がないと、次に別の進行状況ダイアログを表示しようとしたときにアプリがクラッシュします。

于 2016-05-25T07:12:46.913 に答える