3

この単純な行:

wx.MessageBox('Foo', 'Bar', wx.OK | wx.ICON_ERROR)

エラーアイコンとWindowsエラーノイズ(これはと同じノイズではありませんwx.Bell())が表示されたメッセージボックスが表示されます。キャッチされない例外のカスタムエラーダイアログを作成します。この場合、トレースバックはテキストコントロールなどで使用でき、Windowsエラーアイコンとノイズの両方を含めたいと思います。どちらもWindowsのバージョンによって異なり、エラーノイズもカスタマイズできることを私は知っています。

これらのネイティブWindowsリソースをwxPythonで使用する簡単な方法はありますか?ボーナス質問; 答えが「いいえ」の場合、私がやろうとしていることを行う最も簡単な方法は何でしょうか。


回答を受け入れた後の結果:

匿名の臆病者の素晴らしい答えの後で、結果が私の期待をはるかに超えていたので、結果を披露したかっただけです。これは、未処理の例外(Windows 8の場合)でポップアップするエラーダイアログです。

スクリーンショット

また、最新のWindows「UNNK!」も搭載されています。エラー音。これはダイアログの背後にあるコードです。sys.excepthookインポート時にオーバーライドする別のモジュールに配置します。

"""This module, when imported, overrides the default unhandled exception hook
with one that displays a fancy wxPython error dialog."""

import sys
import textwrap
import traceback
import winsound

import wx

def custom_excepthook(exception_type, value, tb):
    dialog = ExceptionDialog(exception_type, value, tb)
    dialog.ShowModal()

# Override sys.excepthook
sys.excepthook = custom_excepthook

class ExceptionDialog(wx.Dialog):
    """This class displays an error dialog with details information about the
    input exception, including a traceback."""

    def __init__(self, exception_type, exception, tb):
        wx.Dialog.__init__(self, None, -1, title="Unhandled error",
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)

        self.SetSize((640, 480))
        self.SetMinSize((420, 200))

        self.exception = (exception_type, exception, tb)
        self.initialize_ui()

        winsound.MessageBeep(winsound.MB_ICONHAND)

    def initialize_ui(self):
        extype, exception, tb = self.exception

        panel = wx.Panel(self, -1)

        # Create the top row, containing the error icon and text message.
        top_row_sizer = wx.BoxSizer(wx.HORIZONTAL)

        error_bitmap = wx.ArtProvider.GetBitmap(
            wx.ART_ERROR, wx.ART_MESSAGE_BOX
        )
        error_bitmap_ctrl = wx.StaticBitmap(panel, -1)
        error_bitmap_ctrl.SetBitmap(error_bitmap)

        message_text = textwrap.dedent("""\
            I'm afraid there has been an unhandled error. Please send the
            contents of the text control below to the application's developer.\
        """)
        message_label = wx.StaticText(panel, -1, message_text)

        top_row_sizer.Add(error_bitmap_ctrl, flag=wx.ALL, border=10)
        top_row_sizer.Add(message_label, flag=wx.ALIGN_CENTER_VERTICAL)

        # Create the text control with the error information.
        exception_info_text = textwrap.dedent("""\
            Exception type: {}

            Exception: {}

            Traceback:
            {}\
        """)
        exception_info_text = exception_info_text.format(
            extype, exception, ''.join(traceback.format_tb(tb))
        )

        text_ctrl = wx.TextCtrl(panel, -1,
                                style=wx.TE_MULTILINE | wx.TE_DONTWRAP)
        text_ctrl.SetValue(exception_info_text)

        # Create the OK button in the bottom row.
        ok_button = wx.Button(panel, -1, 'OK')
        self.Bind(wx.EVT_BUTTON, self.on_ok, source=ok_button)
        ok_button.SetFocus()
        ok_button.SetDefault()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(top_row_sizer)
        # sizer.Add(message_label, flag=wx.ALL | wx.EXPAND, border=10)
        sizer.Add(text_ctrl, proportion=1, flag=wx.EXPAND)
        sizer.Add(ok_button, flag=wx.ALIGN_CENTER | wx.ALL, border=5)

        panel.SetSizer(sizer)

    def on_ok(self, event):
        self.Destroy()

私が望むことができる唯一の改善は、静的テキストがダイアログの幅に応じて自動的に流れて折り返されることですが、それだけのためにカスタムコントロールクラスを作成することはできませんでした。

4

1 に答える 1

4

wx.MessageBox、OS固有の標準メッセージ/アラートダイアログボックスを呼び出します(Windowsでは、user32.dllのMessageBox()です)。wxWidgetsは、指定したフラグ(wx.OKやwx.ICON_INFORMATIONなど)をOS固有のフラグとネイティブメッセージボックスのオプションに変換するだけです。

からOS固有のアイコンを取得できますwx.ArtProvider

サウンドに関しては、wx.Soundサウンドファイルのみを再生できます。ただし、アプリケーションが移植可能である必要がない場合は、winsoundモジュールを使用できます。

import wx
import winsound # windows only

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None,wx.ID_ANY)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add( wx.StaticBitmap(self,bitmap=wx.ArtProvider.GetBitmap(wx.ART_INFORMATION)) )
        sizer.Add( wx.StaticBitmap(self,bitmap=wx.ArtProvider.GetBitmap(wx.ART_QUESTION)) )
        sizer.Add( wx.StaticBitmap(self,bitmap=wx.ArtProvider.GetBitmap(wx.ART_WARNING)) )
        sizer.Add( wx.StaticBitmap(self,bitmap=wx.ArtProvider.GetBitmap(wx.ART_ERROR)) )
        self.SetSizerAndFit(sizer)
        self.Show()
        winsound.MessageBeep(winsound.MB_ICONASTERISK)
        winsound.PlaySound('SystemHand', winsound.SND_ASYNC | winsound.SND_ALIAS)

app = wx.PySimpleApp()
Frame()
app.MainLoop()
于 2012-12-12T11:28:52.047 に答える