ラベル wxWidgets の投稿を表示しています。 すべての投稿を表示
ラベル wxWidgets の投稿を表示しています。 すべての投稿を表示

2020-10-22

【備忘録】Matplotlib で SPC チャート (2)

本ブログで以前、PyGObject で Matplotlib で描画した SPC チャート(管理図)のサンプルを紹介しました [1]。SPC は Statistical Process Control(統計的工程管理)の略で、SPC チャートは処理順に注目特性をプロットした折れ線グラフです。製造工程が管理状態にあるかどうかを判断するためなどに活用されます。詳しい SPC チャートの説明は割愛します。ご興味のある方は、例えば参考サイト [2] などをご覧になってください。

Matplotlib を利用して、PyGObject で SPC チャートがらみのちょっとしたツールを作りました。なかなか出来が良かったので、チームで共有しようと Windows 上で使えるようにパッケージ化を検討しましたが、あえなく挫折。結局、GUI のライブラリを PyGObject から wxPython に変更して GUI の部分を書き直しました。PyInstealler でパッケージ化して動作することを確認してから、チームにデモンストレーションをしました。

幸い、チームのファースト・インプレッションは良好で、さまざまな意見をもらいました。その中で SPC チャートの管理線に関する注文が特に重要だと考え、早速改良に取り掛かりました。横線である管理線のラベルの扱いに改良が必要だったわけなのですが、結局、縦軸の目盛りのラベルをカスタマイズすることが一番扱いやすいと判断し、軸目盛をカスタマイズすることにしました。テスト用のサンプルでベタな書き方をしていますが、備忘録にします。

本ブログ記事では下記の OS 環境で動作確認をしています。

Fedora 33 beta (Workstation Edition) x86_64

横線は自由に描画できるので、あとはラベルを左右どちらかの縦軸に目盛ラベルとして表示することが今回の目的でした。コーディングは、もっと効率的で綺麗な記述ができると思うので、改良を続けることにします。

wx_matplotlib.py の実行例
wx_matplotlib.py

参考サイト

  1. bitWalk's: 【備忘録】Matplotlib で SPC チャート [2020-07-09]
  2. 管理図とは?QC7つ道具との関係、管理図の仕組みや種類を網羅的に解説 | Backlogブログ [2020-02-26]

 

ブログランキング・にほんブログ村へにほんブログ村

2020-10-11

PyInstaller を使ってみる

定型的な業務から逃れるため、Python で GUI アプリを作って自動化することに精を出しています。使用実績を上げれば、次のステップとして、作ったツールをチームで共有したくなります。メンバーが自分と同じように Python を使えるのであれば悩むことはありませんが、残念ながらそうではありません。😭

自分が作ったツールを他の人に使ってもらうために Python の環境を準備してもらうことが現実的でないとき、動作に必要なファイルをまとめてパッケージとして共有できれば便利です。会社業務で使う Windows 上でできればとても助かります。そんなニーズをかなえてくれるのが PyInstaller です。

PyInstaller とは

PyInstaller は Python アプリと依存するライブラリなどのファイルを一つのパッケージにまとめます。ユーザーは、Python インタプリタやモジュールをインストールすることなく、パッケージ化されたアプリを実行することができます。

PyInstaller は Python 3.5 以降をサポートし、NumPy, PyQt, Django, wxPython などの主要な Python パッケージを正しくバンドルします。PyInstaller は Windows, Mac OS X, GNU/Linux でテストされています。しかし、クロスコンパイラではありません: Windows アプリを作るには Windows 上で、GNU/Linux アプリを作るには GNU/Linux 上で PyInstaller を実行します。

PyInstaller Manual より引用・翻訳

PyInstaller を使ってみる

使用した OS 環境は下記の通りです。

Windows 10 Home (x64) 1909, 18363.1110
» Python 3.8.6 python-3.8.6-amd64.exe

※ Python は Microsoft Store のものではなく、https://www.python.org/downloads/release/python-386/ からダウンロードしたパッケージをインストールして使っています。

wxPython 版 Hellow World!

ここでは、wxPython を使った簡単な GUI アプリ(下記)を PyInstaller でパッケージ化してみます。

hello_wx.py
hello_wx.py の実行例

プログラムの実行にアイコンファイルを使っています。github にリポジトリを用意しましたので、git で下記のように clone してご利用ください。

git clone https://github.com/bitwalk123/hello.git

PyInstaller をインストール

コマンドプロンプトを起動して pip で PyInstaller をインストールします。

pip install pyinstaller
pyinstaller のインストール

PyInstaller で hello_wx.py をパッケージ化する

コマンドプロンプトを起動してパッケージ化したいファイル(この例では hello_wx.py)があるディレクトリに移って pyinstaller コマンドを実行してもいいのですが、運用上、別のフォルダでパッケージを作成することにします。

hello_wx.py

d:\bitwa\Projects\hello\hello_wx.py

パッケージを作成するディレクトリ

d:\bitwa\Packages

git clone したディレクトリ内にある pkinstaller.ico を、あらかじめ、パッケージを作成するディレクトリ内にコピーしておきます。これはパッケージ化した exe 形式のファイルのアイコンに使います。

コマンドプロンプトを起動して、パッケージを作成するディレクトリへ移り、pyinstaller コマンドを実行します。

Microsoft Windows [Version 10.0.18363.1110]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\bitwa>d:

D:\>cd bitwa\Packages

D:\bitwa\Packages>dir
 ドライブ D のボリューム ラベルは SD です
 ボリューム シリアル番号は E0E1-F674 です

 D:\bitwa\Packages のディレクトリ

2020/10/11  08:48    <DIR>          .
2020/10/11  08:48    <DIR>          ..
2020/10/10  22:36            16,958 pyinstaller.ico
               1 個のファイル              16,958 バイト
               2 個のディレクトリ  119,623,282,688 バイトの空き領域

D:\bitwa\Packages>pyinstaller -w -i pyinstaller.ico d:\bitwa\Projects\hello\hello_wx.py
1294 INFO: PyInstaller: 4.0
1294 INFO: Python: 3.8.6
1299 INFO: Platform: Windows-10-10.0.18362-SP0
1304 INFO: wrote D:\bitwa\Packages\hello_wx.spec
1314 INFO: UPX is not available.
1339 INFO: Extending PYTHONPATH with paths
['d:\\bitwa\\Projects\\hello', 'D:\\bitwa\\Packages']
1444 INFO: checking Analysis
...
(途中省略)
...
27536 INFO: Building COLLECT COLLECT-00.toc
40317 INFO: Building COLLECT COLLECT-00.toc completed successfully.

D:\bitwa\Packages>

今回使用したオプションの -w は、実行時にコンソールを表示しないようにする GUI アプリ向けのオプションです。-i は、作成する exe 形式のファイルのアイコン表示に指定するオプションです。最後に、パッケージにする Python スクリプトのパスを指定します。PyInstaller のオプション詳細は、参考サイト [1] にあります。

PyInstaller を実行した後、build と dist のフォルダ、hello_wx.spec というファイルが生成されます。

PyInstaller 実行後のディレクトリ

パッケージ化されたファイルは dist\hello_wx にあります。

PyInstaller で生成された hello_wx.exe ファイル

生成された hello_wx.exe ファイルの他に、ランタイムライブラリなどの関連ファイルがたくさんあります。これが煩わしい場合は、pyinstaller コマンド実行時に -F オプションを付けると、大きなサイズの単一ファイルになります。

動作確認

動作確認のため hello_wx.exe ファイルをダブルクリックしたところ、./wx.ico が見つからないというエラーが出ました。

hello_wx.exe の実行例 (1)

プログラムが読み込む ico ファイルまではパッケージ化してくれないようです。これは wx.ico をパッケージのフォルダ内にコピーすることで解決しました。

hello_wx.exe の実行例 (2)

アプリケーションが使用するアイコン類は、最終的にはエンコードして Python のスクリプト内に記述することにします。

たったこれだけのプログラムなのにランタイムライブラリなどを含めるとこんなサイズになります(下記)。

パッケージ化した hello_wx フォルダのサイズ

まとめ

PyInstaller の使い方については、もうすこし使い込んでから、使用例を含めてまとめる予定です。

個人的には、大きなサイズの単一の exe 形式のファイルにすることにはあまり興味が無く、exe 形式のファイル + 関連ファイルが一つのフォルダ内に収まれば御の字です。あとは Inno Setup などでインストーラを作成すれば完璧です。😃

参考サイト

  1. PyInstaller Manual — PyInstaller 4.0 documentation
  2. Inno Setup

ブログランキング・にほんブログ村へ
にほんブログ村

2018-04-26

wxPythonで標準出力のリダイレクト

Python に限ったことではないのですが、問題解決のためにちょっとしたプログラムを作って、それで問題を解決できれば、やれやれなんとかなったとまずはひと安心します。そのプログラムにある程度の頻度で今後も使う需要があるならば、少し汎用化して GUI 化したくなります。私の場合、Python では、wxPython を使って GUI 化をします。

GUI 化をするにあたって、あったら便利な機能が標準出力のリダイレクトです。参考文献 [1] にピッタリなサンプルがありましたので、自分なり理解するために少しだけ書き直したサンプルを紹介します。

使用環境は以下のとおりです。今回も業務上必要だったので Windows を使っています。

  • OS: Windows 7 Enterprise SP1 (x86_64)
  • Python: Python 3.6.5 (amd64)
  • Eclipse IDE for Java Developers, Version: Oxygen.3a Release (4.7.3a) + PyDev 6.3.2

 

標準出力を Text ウィジェットへリダイレクトするサンプル
import sys
import wx


class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, title="TEST")
        panel = wx.Panel(self) 
        vbox = wx.BoxSizer(wx.VERTICAL) 

        # ---------------------------------------------------------------------
        # horizontal button bar
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        # start
        start = wx.Button(panel, wx.ID_ANY, "start")
        start.Bind(wx.EVT_BUTTON, self.onClicked)
        # stop
        stop = wx.Button(panel, wx.ID_ANY, "stop")
        stop.Bind(wx.EVT_BUTTON, self.onClicked)

        hbox.Add(start, 0, wx.ALIGN_LEFT)
        hbox.Add(stop, 0, wx.ALIGN_LEFT)

        # ---------------------------------------------------------------------
        # log window
        style = wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL
        log = wx.TextCtrl(panel, wx.ID_ANY, style=style)
        
        vbox.Add(hbox, 0, wx.ALL | wx.EXPAND, 2) 
        vbox.Add(log, 1, wx.ALL | wx.EXPAND, 2) 
        panel.SetSizer(vbox) 

        # ---------------------------------------------------------------------
        # redirect text here
        sys.stdout = log
        
    def onClicked(self, event):
        msg = event.GetEventObject().GetLabel()
        print("Label of pressed button = " + msg)

  
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()    

実行例を示しました。

Text ウィジェットへ標準出力をリダイレクト

参考サイト

  1. wxPython – Redirecting stdout / stderr | The Mouse Vs. The Python

 

ブログランキング・にほんブログ村へ
にほんブログ村

2018-04-19

wxPython ふたたび

Websocket を Java で扱いたくて悪戦苦闘していましたが、JavaEE 環境を用意せずにちょこっとプログラムを作るなんていうことはどうやら叶わぬ夢と悟りました。いや、ほんと、ちょこっとした環境でテストして、JavaFX でちょこっとした GUI プログラムにして、ちょこっと使えるようにしたかったのですが…。

もしかすると python であれば、そんな夢を叶えてくれるかもしれないと考え、試してみたところ…難なくやりたいことが出来てしまいました。💦

使用環境は以下のとおりです。

  • OS: Windows 7 Enterprise SP1 (x86_64)
  • Python: Python 3.6.5 (amd64)

さて、ここからが本題です。

今回、python 2.7 系をアンインストールして、情報量が豊富であろう最新の python 3.6 系をインストールしました。そもそも python 2.7 系を使っていたのは、その当時、wxPython が新しい python にまだ対応していなかったからでした。さすがに今ではもう対応しているだろうとあらためて調べてみると、すでに pip でインストールできるようになっていました。早速、下記のようにしてインストールしました。

> py -m pip install -U wxPython

しばらく wxPython を使っていなかったので、リハビリがてら、参考サイト [3] にあった Hello World のプログラムをコピーして動作確認しました。コメントを除いて以下に再掲しました。

リスト:helloworld2.py 
import wx

class HelloFrame(wx.Frame):

    def __init__(self, *args, **kw):
        super(HelloFrame, self).__init__(*args, **kw)

        pnl = wx.Panel(self)

        st = wx.StaticText(pnl, label="Hello World!", pos=(25,25))
        font = st.GetFont()
        font.PointSize += 10
        font = font.Bold()
        st.SetFont(font)

        self.makeMenuBar()

        self.CreateStatusBar()
        self.SetStatusText("Welcome to wxPython!")


    def makeMenuBar(self):

        fileMenu = wx.Menu()
        helloItem = fileMenu.Append(-1, "&Hello...\tCtrl-H", "Help string shown in status bar for this menu item")
        fileMenu.AppendSeparator()
        exitItem = fileMenu.Append(wx.ID_EXIT)

        helpMenu = wx.Menu()
        aboutItem = helpMenu.Append(wx.ID_ABOUT)

        menuBar = wx.MenuBar()
        menuBar.Append(fileMenu, "&File")
        menuBar.Append(helpMenu, "&Help")

        self.SetMenuBar(menuBar)

        self.Bind(wx.EVT_MENU, self.OnHello, helloItem)
        self.Bind(wx.EVT_MENU, self.OnExit,  exitItem)
        self.Bind(wx.EVT_MENU, self.OnAbout, aboutItem)


    def OnExit(self, event):
        self.Close(True)


    def OnHello(self, event):
        wx.MessageBox("Hello again from wxPython")


    def OnAbout(self, event):
        wx.MessageBox("This is a wxPython Hello World sample", "About Hello World 2", wx.OK|wx.ICON_INFORMATION)


if __name__ == '__main__':
    app = wx.App()
    frm = HelloFrame(None, title='Hello World 2')
    frm.Show()
    app.MainLoop()

実行例を示します。

> py helloworld2.py

ざっと眺めたところ、昔と変わりありません。しばらく GUI プログラムをするのに JavaFX を使うのを止めて、ふたたび wxPython を使ってみたくなりました。今回 Windows を使っているのは、純粋に業務上必要だったからなのですが、自宅で Linux 上でも動作確認をして、具合が良ければもうすこしのめり込みます。

参考サイト

  1. Python Releases for Windows | Python.org
  2. Welcome to wxPython! | wxPython
  3. Overview of wxPython | wxPython

ブログランキング・にほんブログ村へ
にほんブログ村

2018-01-06

Maximaであそぶ

Maxima は、LISP で記述された数式処理システムです。GNU GPL に基づくフリーソフトウェアであり、現在も活発に開発が続けられています。[Wikipedia より]

以前の記事 [1] で Maxima on Android を紹介しましたが、Maxima は Linux 上で利用できます。Maxima on Android に慣れるには、まず Maxima に慣れる方が、大きな画面とキーボードが利用できることから、より簡単だと思われます。ということで、早速 Maxima をインストールしてみました。

使用している環境は以下の通りです。

  • OS: Fedora 27 (x86_64)

Maxima のインストール

まず、maxima をキーワードにして、関連するパッケージを検索します。

$ su
パスワード:
# dnf search maxima
メタデータの期限切れの確認は、0:00:20 時間前の 2018年01月02日 08時57分50秒 に実施しました。
========================= 名前 Exactly Matched: maxima =========================
maxima.x86_64 : Symbolic Computation Program
========================== 名前 & 概要 の一致: maxima ==========================
maxima-src.x86_64 : maxima lisp source code
maxima-gui.x86_64 : Tcl/Tk GUI interface for maxima
maxima-runtime-ecl.x86_64 : Maxima compiled with ECL
maxima-runtime-gcl.x86_64 : Maxima compiled with GCL
wxMaxima.x86_64 : Graphical user interface for Maxima
maxima-runtime-sbcl.x86_64 : Maxima compiled with SBCL
maxima-runtime-clisp.x86_64 : Maxima compiled with clisp
============================= 概要 の一致: maxima ==============================
wannier90.x86_64 : Maximally-localised Wannier functions
nodejs-simple-is.noarch : Maximally minimal type-testing library
nodejs-simple-fmt.noarch : Maximally minimal string formatting library

wxMaxima をインストールする事で、Maxima 本体を含む関連するパッケージもインストールします。

この wxMaximaは、wxWidgets によるグラフィカルな Maxima のユーザーインターフェイスです。見映えのする数式表示と、メニューとダイアログを通じた Maxima へのアクセスを提供します。

# dnf install wxMaxima
メタデータの期限切れの確認は、0:01:00 時間前の 2018年01月02日 08時57分50秒 に実施しました。
依存性が解決されました。
================================================================================
 パッケージ               アーキテクチャ
                                      バージョン             リポジトリ   サイズ
================================================================================
インストール:
 wxMaxima                 x86_64      16.04.2-4.fc27         fedora       2.6 M
依存関係のインストール:
 gnuplot                  x86_64      5.0.6-5.fc27           fedora       824 k
 gnuplot-common           x86_64      5.0.6-5.fc27           fedora       643 k
 jsmath-fonts             noarch      20090708-12.fc27       fedora       123 k
 maxima                   x86_64      5.41.0-1.fc27          updates       22 M
 maxima-runtime-sbcl      x86_64      5.41.0-1.fc27          updates       12 M
 rlwrap                   x86_64      0.42-7.fc27            fedora       102 k
 wxBase3                  x86_64      3.0.3-5.fc27           fedora       1.1 M
 wxGTK3                   x86_64      3.0.3-5.fc27           fedora       5.1 M
 wxGTK3-webview           x86_64      3.0.3-5.fc27           fedora        64 k

トランザクションの要約
================================================================================
インストール  10 パッケージ

総ダウンロードサイズ: 44 M
パッケージ展開後のサイズ: 180 M
これでいいですか? [y/N]: y
パッケージをダウンロードしています:
(1/10): jsmath-fonts-20090708-12.fc27.noarch.rp  24 kB/s | 123 kB     00:05    
(2/10): wxBase3-3.0.3-5.fc27.x86_64.rpm         180 kB/s | 1.1 MB     00:06    
...
...
...
  検証中           : gnuplot-common-5.0.6-5.fc27.x86_64                   10/10 

インストール済み:
  wxMaxima.x86_64 16.04.2-4.fc27      gnuplot.x86_64 5.0.6-5.fc27              
  gnuplot-common.x86_64 5.0.6-5.fc27  jsmath-fonts.noarch 20090708-12.fc27     
  maxima.x86_64 5.41.0-1.fc27         maxima-runtime-sbcl.x86_64 5.41.0-1.fc27 
  rlwrap.x86_64 0.42-7.fc27           wxBase3.x86_64 3.0.3-5.fc27              
  wxGTK3.x86_64 3.0.3-5.fc27          wxGTK3-webview.x86_64 3.0.3-5.fc27       

完了しました!
# 

Maxima の実行例

下記に使用例をいくつか示しました。wxMaxima 上では [Enter] ではなく、[Shift] + [Enter] で入力します。

関数の定義

f(x) := x^3 - 1;

方程式の解

solve(f(x) = 0);

微分

diff(f(x), x);

不定積分

integrate(f(x), x);

定積分

integrate(f(x), x, 1, 2);

定積分の数値計算

romberg(f(x), x, 1, 2);
wxMaxima の実行例

グラフ表示の例として、媒介変数で定義したメビウスの帯を描画してみました。グラフはデフォルトで gnuplot 上に描画されます。

メビウスの帯 [4]

x: cos(2*t)*(r*cos(t) + 2);
y: sin(2*t)*(r*cos(t) + 2);
z: r*sin(t);
plot3d([x, y, z], [r, -1, 1], [t, 0, %pi], [grid, 10, 100]);
Möbius strip

参考サイト

  1. bitWalk's: Maxima on Android を試す [2018-01-01]
  2. Maxima Manual:
  3. Maxima - Wikibooks
  4. メビウスの帯 - Wikipedia
  5. Maxima入門 Maximaのインストールから簡単な数式、グラフ作成まで

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-06-23

【備忘録】PlotCanvas と横線 ─ wxPython

JavaFX で作っていたプログラムで、リソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しています。python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回は PlotCanvas に横線を引くサンプルです。

もともと JavaFX で作っていたプログラムで抱えていたリソース不足の一因は、チャート (LineChart) にありました。機能が単純なわりに、データポイントがインスタンスになるため結構なリソースを消費します。本ブログでは、JavaFX の LineChart についてはズーム機能の追加を重点的に紹介していました。実際はそれだけでなく、細かな機能を追加していましたが、紹介しきれていません。横線(あるいは縦線)を引く、というような単純な機能もその一つで LineChart に追加していましたが、wxPython の PlotCanvas でも、横線を引くのに、結局、機能の追加に迫られました。

そんなわけで、品質管理に使うようなトレンドチャートにリミット線を引く場合、というサンプルにして紹介します。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64)
  • python-2.7.11-5.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-5.0.0-1.fc24.x86_64
# -*- coding: utf-8 -*- 
import wx
import wx.lib.plot as plot

class XbarChart(plot.PlotCanvas):
    def __init__(self, parent, data, LSL, USL, gTitle, xLabel, yLabel):
        plot.PlotCanvas.__init__(self, parent, wx.ID_ANY, style=wx.SIMPLE_BORDER)
        self.SetFont(wx.Font(11, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
        self.SetFontSizeAxis(11)

        self.LSL = LSL
        self.USL = USL

        line = plot.PolyLine(data, colour='blue', width=1)
        marker = plot.PolyMarker(data, colour='blue', marker="circle")

        gc = plot.PlotGraphics([line, marker], gTitle, xLabel, yLabel)
        self.Draw(gc, xAxis=(0, len(data) + 1), yAxis=(4, 8))

    def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks):
        super(XbarChart, self)._drawAxes(dc, p1, p2, scale, shift, xticks, yticks)
        
        # LSL, USL
        penWidth = self.printerScale * self._pointSize[0]
        dc.SetPen(wx.Pen(wx.Colour(255, 0, 0), penWidth))

        x1 = scale[0] * p1[0] + shift[0]
        x2 = scale[0] * p2[0] + shift[0]

        for spec in [self.LSL, self.USL]:
            y = scale[1] * spec + shift[1]
            dc.DrawLine(x1, y, x2, y)

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, "SPC", size=(600, 300))

        # X bar Chart
        data = [(1, 6.2), (2, 5.3), (3, 5.4), (4, 6.5), (5, 4.8),
                (6, 6.7), (7, 5.3), (8, 6.1), (9., 5.7), (10, 4.9),
                (11, 5.1), (12, 5.6), (13, 5.2), (14, 6.5)]
        lsl = 5.0
        usl = 7.0
        chart = XbarChart(self, data, lsl, usl, "X-bar Chart", "Lot", "Measurement")

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(chart, proportion=1, flag=wx.EXPAND, border=0)
        self.SetSizer(sizer)
        self.Layout()

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None)
        frame.Show(True)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()
    

実行例を以下に示しました。

 

参考サイト

  1. wxWidgets/wxPython: This is the repository for "Classic"

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-06-04

【備忘録】CustomTreeCtrl とポップアップメニュー ─ wxPython

JavaFX で作っていたプログラムで、リソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しています。python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回は CustomTreeCtrl です。参考文献 [1] を参考にして、JavaFX の時と同じようなサンプルを作ってみました [2]。ポップアップメニューは、ツリーの末端のアイテムのみ表示するために、判定用に wx.TreeItemData() を利用してアイテムに値を持たせています。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-5.0.0-1.fc24.x86_64
#!/usr/bin/env python
# -*- coding: utf-8 -*- 

import wx
import wx.lib.agw.customtreectrl as CT

ID_TREE = wx.NewId()

class MyTree(CT.CustomTreeCtrl):
    def __init__(self, parent):
        CT.CustomTreeCtrl.__init__(self, parent, wx.ID_ANY, agwStyle=wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT)

        # image list
        il = wx.ImageList(32, 32)
        CAROT = il.AddIcon(wx.Icon("image/carot.png", wx.BITMAP_TYPE_PNG))
        EGGPLANT = il.AddIcon(wx.Icon("image/eggplant.png", wx.BITMAP_TYPE_PNG))
        TOMATO = il.AddIcon(wx.Icon("image/tomato.png", wx.BITMAP_TYPE_PNG))
        APPLE = il.AddIcon(wx.Icon("image/apple.png", wx.BITMAP_TYPE_PNG))
        GRAPE = il.AddIcon(wx.Icon("image/grape.png", wx.BITMAP_TYPE_PNG))
        BANANA = il.AddIcon(wx.Icon("image/banana.png", wx.BITMAP_TYPE_PNG))
        self.SetImageList(il)

        root = self.AddRoot(u"食べ物")
        vegetable = self.AppendItem(root, u"野菜")
        fruit = self.AppendItem(root, u"果物")

        leafData = wx.TreeItemData("leaf")

        carot = self.AppendItem(vegetable, u"にんじん")
        self.SetItemImage(carot, CAROT)
        self.SetPyData(carot, leafData)

        eggplant = self.AppendItem(vegetable, u"なす")
        self.SetItemImage(eggplant, EGGPLANT)
        self.SetPyData(eggplant, leafData)

        tomato = self.AppendItem(vegetable, u"とまと")
        self.SetItemImage(tomato, TOMATO)
        self.SetPyData(tomato, leafData)

        apple = self.AppendItem(fruit, u"りんご")
        self.SetItemImage(apple, APPLE)
        self.SetPyData(apple, leafData)

        grape = self.AppendItem(fruit, u"ぶどう")
        self.SetItemImage(grape, GRAPE)
        self.SetPyData(grape, leafData)

        banana = self.AppendItem(fruit, u"ばなな")
        self.SetItemImage(banana, BANANA)
        self.SetPyData(banana, leafData)
        
        self.ExpandAll()


class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size=wx.Size(300, 400))
        self.CreateStatusBar()
        self.createMenu()

        self.tree = MyTree(self)
        self.tree.Bind(wx.EVT_CONTEXT_MENU, self.showPopupMenu)

        layout = wx.BoxSizer(wx.VERTICAL)
        layout.Add(self.tree, proportion=1, flag=wx.GROW)
        self.SetSizer(layout)
        self.Centre()
        
    def createMenu(self):
        self.menu = wx.Menu()
        item_tree = wx.MenuItem(self.menu, ID_TREE, u"処理")
        self.menu.AppendItem(item_tree)
        self.Bind(wx.EVT_MENU, self.OnCapital, id=ID_TREE)

    def showPopupMenu(self, evt):
        item_id = self.tree.GetSelection()
        item_data = self.tree.GetItemPyData(item_id)
        if item_data != None:
            if item_data.GetData() == "leaf":
                position = self.ScreenToClient(wx.GetMousePosition())
                self.PopupMenu(self.menu, position)

    def OnCapital(self, event):
        itemId = self.tree.GetSelection()
        itemText = self.tree.GetItemText(itemId)
        self.SetStatusText(u"「" + itemText + u"」が選択されました。")


class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, wx.ID_ANY, "MyTree")
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

実行例を以下に示しました。

 

参考サイト

  1. customtreectrl — wxPython (Phoenix) 3.0.3 documentation
  2. bitWalk's: JavaFX: TreeView と ContextMenu (2)

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-05-25

【備忘録】プロットの y 軸の目盛をカスタマイズ ─ wxPython

JavaFX で作っていたプログラムでリソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しており、python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回はマイナーな話題です。

wx.lib.plot.PlotCanvas を利用して、ある複数パラメータのトレンドデータを一度に扱って解析をするアプリケーションを作っているのですが、パラメータの値の大きさがまちまちであるため、縦に並べると y 軸の位置が不揃いになります。

JavaFX で当アプリケーションを作成していた時には、プロット枠の左側からの位置を制御できたので、wxPython の PlotCanvas で同じようなことをしようといろいろ調べましたが、どうもやり方が判りません。

そこで、苦肉の策として y 軸に表示される目盛の幅を、例えば 10 文字分というように固定幅を取るようにして揃えようとしました。

PlotCanvas を継承したクラスで、 y 軸の目盛を扱う _yticks メソッドをオーバーライドして目盛のカスタマイズをするのですが、参照したサイトの URL が判らなくなってしまいました。あとで追記します†。参考として PlotCanvas を継承した MyPlot クラスを以下に示しました。

† 2016-05-26 同等の内容のサイトを見つけましたので、参考サイト [1] に加えました。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-5.0.0-1.fc24.x86_64
class MyPlot(plot.PlotCanvas):
    def __init__(self, parent, id,):
        plot.PlotCanvas.__init__(self, parent, wx.ID_ANY,)

    def _yticks(self, *args):

        """override  _yticks to write centigrade on y axis"""

        ticks = plot.PlotCanvas._yticks(self, *args)
        new_ticks = []

        for tick in ticks:
            t = tick[0]
            t_padded = str(t).rjust(10, ' ')
            new_ticks.append((t, t_padded))
              
        return new_ticks

Linux の環境では、これだけでうまくいくように見えるのですが Windows 上ではフォントが違うためかうまくいきません。フォントファミリーを Monospace にしたいのですが、思うようにコントロールできません。この件についてはひきつづき調べて、うまくいったら紹介することにします。

参考サイト

  1. wxPython-users - wx.lib.plot custom labels?

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-05-19

【備忘録】CheckListBox のアイテムにインスタンスを追加 ─ wxPython

JavaFX で作っていたプログラムでリソース不足 (OutOfMemoryError) に悩まされているため、結局同じことになるかもしれないと思いつつも、軽快に GUI が動く wxPython にプログラムを移植しており、python のプログラミングに不慣れなためハマった個所を備忘録としてブログ用のサンプルに書き換えて残しています。

今回は CheckListBox です。ListBox のアイテムにインスタンスを追加するために紹介したサンプル [1] をベースに、Web で見つけた CheckListBox のサンプルのコード [2] を参考にさせていただきました。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-4.6.0-1.fc24.x86_64
# -*- coding: utf-8 -*- 
import wx

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title=u"都道府県リスト", size=(250, 200))
        self.CreateStatusBar()
        self.create_listbox()

    def create_listbox(self):
        self.lbox = wx.CheckListBox(self, wx.ID_ANY)
        self.lbox.Bind(wx.EVT_LISTBOX, self.SelectEvent)
        self.Bind(wx.EVT_CHECKLISTBOX, self.CheckEvent, self.lbox)

        elem_01 = PrefObj(u"北海道", u"札幌市")
        self.lbox.Append(elem_01.pref, elem_01)

        elem_02 = PrefObj(u"青森県", u"青森市")
        self.lbox.Append(elem_02.pref, elem_02)

        elem_03 = PrefObj(u"岩手県", u"盛岡市")
        self.lbox.Append(elem_03.pref, elem_03)

    def SelectEvent(self, event):
        obj1 = event.GetEventObject()
        obj2 = self.lbox.GetClientData(self.lbox.GetSelection())
        self.SetStatusText(obj1.GetStringSelection() + u"の県庁所在地は" + obj2.capital + u"です。")

    def CheckEvent(self, event):
        index = event.GetSelection()
        obj = self.lbox.GetClientData(index)
        if self.lbox.IsChecked(index):
            self.SetStatusText(obj.pref + u"が選択されました。")
        else:
            self.SetStatusText(obj.pref + u"が選択解除されました。")

class PrefObj():
    def __init__(self, pref, capital):
        self.pref = pref
        self.capital = capital

class MyApp(wx.App):
    def OnInit(self):
        ui = MyFrame(None)
        ui.Show(True)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

実行例を以下に示しました。リストのアイテムを選択した時のバインディング self.lbox.Bind(wx.EVT_LISTBOX, self.SelectEvent) と、チェックボックスをチェックするときのイベント self.Bind(wx.EVT_CHECKLISTBOX, self.CheckEvent, self.lbox) の両方を実装しているため、予期せぬメッセージがステータスバーに表示される場合があります。

Windows 7 上で同じサンプルを確認しましたが、チェックボックスとアイテム選択のイベントを容易に区別できました。OS による動作の違いはおいおい詳しく確認していきます。

 

参考サイト

  1. bitWalk's: 【備忘録】ListBox のアイテムにインスタンスを追加 ─ wxPython
  2. wxPython/CheckListBox.py at master · wxWidgets/wxPython

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-05-15

【備忘録】ListBox のアイテムにポップアップメニュー ─ wxPython

ListBox のアイテムにオブジェクト(インスタンス)を表示することができましたので [1]、さらにポップアップメニューを付けてみました [2]。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-4.6.0-1.fc24.x86_64
# -*- coding: utf-8 -*- 
import wx

ID_CAPITAL = wx.NewId()

class MyFrame(wx.Frame):

    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title=u"都道府県リスト", size=(250, 200))
        self.CreateStatusBar()
        self.create_listbox()
        self.createMenu()

    def create_listbox(self):
        self.lbox = wx.ListBox(self, wx.ID_ANY)
        self.lbox.Bind(wx.EVT_CONTEXT_MENU, self.showPopupMenu)

        elem_01 = PrefObj(u"北海道", u"札幌市")
        self.lbox.Append(elem_01.pref, elem_01)

        elem_02 = PrefObj(u"青森県", u"青森市")
        self.lbox.Append(elem_02.pref, elem_02)

        elem_03 = PrefObj(u"岩手県", u"盛岡市")
        self.lbox.Append(elem_03.pref, elem_03)

    def createMenu(self):
        self.menu = wx.Menu()
        item_capital = wx.MenuItem(self.menu, ID_CAPITAL,  u"県庁所在地")
        self.menu.AppendItem(item_capital)
        self.Bind(wx.EVT_MENU, self.OnCapital, id=ID_CAPITAL)
        
    def showPopupMenu(self,evt):
        position = self.ScreenToClient(wx.GetMousePosition())
        self.PopupMenu(self.menu,position)

    def OnCapital(self, event):
        obj = self.lbox.GetClientData(self.lbox.GetSelection())
        self.SetStatusText(obj.pref + u"の県庁所在地は" + obj.capital + u"です。")
        
class PrefObj():
    def __init__(self, pref, capital):
        self.pref = pref
        self.capital = capital

class MyApp(wx.App):
    def OnInit(self):
        ui = MyFrame(None)
        ui.Show(True)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

実行例を以下に示しました。

 

参考サイト

  1. bitWalk's: 【備忘録】ListBox のアイテムにインスタンスを追加 ─ wxPython
  2. Revx At Large: wxPython ListBox PopupMenu

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-05-14

【備忘録】ListBox のアイテムにインスタンスを追加 ─ wxPython

ListBox は 1 つあるいはそれ以上の文字列のリストを表示、マウスで選択するときに使用するウィジェットです。しかし単純な文字列のリストではなく、インスタンスのリストを使いたい場合があります。例えばあるファイル・オブジェクト(インスタンス)の一覧を ListBox へ表示する場合などです。

JavaFX の ListView では、比較的簡単にインスタンスのリストを表示することができたのですが、wxPython の wx.ListBox では同じようには出来なかったので、少し調べたところ、やり方は異なるものの、やりたいことが実現できることが判りました [1]。

ということで、備忘録として簡単なサンプルを作りました。都道府県クラス PrefObj のインスタンスを ListBox のアイテムに追加しています。ListBox のアイテムには文字列の name プロパティを表示し、マウスのクリックイベントで message プロパティをステータスバーに表示しています。マウスのクリックイベントだけでは、PrefObj のインスタンスを取得できなかったので別の方法でインスタンスを取得しています。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Beta)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-4.6.0-1.fc24.x86_64
# -*- coding: utf-8 -*- 
import wx

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, title=u"都道府県リスト", size=(250, 200))
        self.CreateStatusBar()
        self.create_listbox()

    def create_listbox(self):
        self.lbox = wx.ListBox(self, wx.ID_ANY)
        self.lbox.Bind(wx.EVT_LISTBOX, self.listbox_select)

        elem_01 = PrefObj(u"北海道", u"札幌市")
        self.lbox.Append(elem_01.name, elem_01)

        elem_02 = PrefObj(u"青森県", u"青森市")
        self.lbox.Append(elem_02.name, elem_02)

        elem_03 = PrefObj(u"岩手県", u"盛岡市")
        self.lbox.Append(elem_03.name, elem_03)

    def listbox_select(self, event):
        obj1 = event.GetEventObject()
        obj2 = self.lbox.GetClientData(self.lbox.GetSelection())
        self.SetStatusText(obj1.GetStringSelection() + u"の県庁所在地は" + obj2.message + u"です。")

class PrefObj():
    def __init__(self, name, message):
        self.name = name
        self.message = message

class MyApp(wx.App):
    def OnInit(self):
        ui = MyFrame(None)
        ui.Show(True)
        return True

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

実行例を以下に示しました。

まだまだ初心者ですが、Python でプログラミングをするようになってから不思議な感覚にとらわれています。インデントが構文規則に含まれていることで、不思議なコーディングの美しさというものを感じるようになってきたからです。今のところ、JavaFX で作っているアプリケーションを、wxPython に置き換えたらパフォーマンスがどのぐらい変化するかを評価するために四苦八苦しながら移植していますが、もしも(対象のアプリケーションについて)wxPython のパフォーマンスの方が良ければ、ひょっとすると JavaFX を使わなくなってしまうかもしれません。

参考サイト

  1. wxPython: Storing Objects in ComboBox or ListBox Widgets | The Mouse Vs. The Python

 

ブログランキング・にほんブログ村へ
にほんブログ村

2016-05-05

wxPython のチャート

JavaFX を利用して大量のデータを LineChart へプロットする GUI アプリケーションを作っています。機能が豊富で気に入っているのですが、対象のデータ量を扱うとヒープメモリが不足して OutOfMemoryError の発生に悩まされています。

Java VM のパラメータチューニングをすることを検討すべきではありますが、その前に、もっとリソースを使わないライブラリがないかどうか評価してみたいと考えました。

wxPython

wxPython は、C++ で書かれた wxWidgets というクロスプラットフォームなウィジェット・ツールキットを Python から利用できるようにラッピングした Python のモジュールです。興味があった Python のプログラミングを始めるきっかけとして良い機会と考えました。

プロットするだけのライブラリであれば他にも興味を惹くものはありますが、GUI アプリケーションである以上、プロットだけでなく一般的な GUI 用のウィジェットも利用できる必要があります。

参考サイト [1] によれば、wav 形式のファイルを読み込ませるとメモリを食い潰して動かなくなるようです。これは本質的に自分が抱えている問題と同じなのですが、程度の違いを確認するために、Python のプログラミングを覚えながら少し評価してみる事にしました。

手始めに、参考サイト [2] に紹介されていたサンプルをちょっといじって実行してみました。

動作環境は次の通りです。

  • OS: Fedora 24 (x86_64, Alpha)
  • python-2.7.11-4.fc24.x86_64
  • wxPython-3.0.2.0-10.fc24.x86_64
  • IDE: eclipse-pydev-4.5.5-2.fc24.x86_64
リスト:MyPlot.py 
# -*- coding: utf-8 -*- 
import wx
import wx.lib.plot as plot

class MyPlot(wx.Frame):
    def __init__(self):
        self.frame = wx.Frame(None, title="wx.lib.plot", id=wx.ID_ANY, size=(410, 340))
        #icon = wx.Icon("./application_x_python.png", wx.BITMAP_TYPE_PNG)
        #self.frame.SetIcon(icon)

        self.panel = wx.Panel(self.frame)
        self.panel.SetBackgroundColour("yellow")
        
        plotter = plot.PlotCanvas(self.panel)
        plotter.SetInitialSize(size=(400, 300))
        # enable the zoom feature (drag a box around area of interest)
        plotter.SetEnableZoom(True)
        plotter.SetEnableGrid(True)
        plotter.SetGridColour('gray')
        
        # list of (x,y) data point tuples
        data = [(1, 2), (2, 3), (3, 5), (4, 6), (5, 8), (6, 8), (12, 10), (13, 4)]
        # draw points as a line
        line = plot.PolyLine(data, colour='red', width=1)
        # also draw markers, default colour is black and size is 2
        # other shapes 'circle', 'cross', 'square', 'dot', 'plus'
        marker = plot.PolyMarker(data, marker='triangle', colour='red')
        # set up text, axis and draw
        gc = plot.PlotGraphics([line, marker], 'Line/Marker Graph', 'x axis', 'y axis')
        plotter.Draw(gc, xAxis=(0, 15), yAxis=(0, 15))
        
        self.frame.Show(True)

app = wx.App()
f = MyPlot()
app.MainLoop()

実行例を以下に示します。簡単なサンプルですが、これをベースに、自分が使う描画用のクラスを作成できそうです。

Python 初心者ですので、参考サイト [3] で勉強中です。このサイトで言及していないウィジェットなどの話題があれば、本ブログで紹介していきたいと思います。

参考サイト

  1. wxPythonのwx.lib.plotでwavファイルをプロットする - yattの日記
  2. Using wxPython for Plotting | DaniWeb
  3. Python入門から応用までの学習サイト

 

ブログランキング・にほんブログ村へ
にほんブログ村

2009-07-18

wxWidgets でもクロスコンパイル(2)

Get MinGW Cross Compiler at SourceForge.net. Fast, secure and Free Open Source software downloads

Fedora 11 から Win32 クロスコンパイル用パッケージが正式にサポートされるようになって、自分の SourceForge.net のプロジェクトサイトで、クロスコンパイル用 RPM パッケージの公開に対するモチベーションが下がってしまい、活動が低調になっていました。

とあるユーザから、wxWidgets 用の RPM を Fedora 11 用にも公開してほしいというメールを受け取りました。

Date: Thu, 16 Jul 2009 14:51:21 +0200
Subject: mingw-wxwidgets on fedora11?
From: ##### ######### <#####.########@gmail.com>
To: bitwalk at users.sourceforge.net

Dear ####### #########,

I've succesfully used your rpm packaging of mingw32-wxWidgets on fedora 10
(mingw32-wxWidgets-2.8.9-2.fc10.noarch.rpm), it was really helpful to me in
developing a cross-platform application that I need to mantain. So much
important that the only thing that I'm actually waiting for before
switching to fedora11 is exactly the release of the same package for
fedora11. So I would like to ask you if you have any plan to release such
package for fedora11, or if there is any way that I can use the f10
package on fedora11.

Thank you very much for your attention and many thanks for your great work,
##### ########

wxWidgets の RPM パッケージについては、Fedora MinGW のメーリングリストで話題が出ていたので、きっと誰かが作るだろうと放っておいたのでした。しかし、直接メールを送ってくれるユーザがいれば話は別です。返事を出して早速パッケージを作成しました。

Browse MinGW Cross Compiler Files on SourceForge.net
- mingw32-wxWidgets-2.8.10-1.fc11.noarch.rpm
- mingw32-filesystem-50-3.fc11.2.noarch.rpm

このサイトで公開した mingw32-filesystem は、wxWidgets のファイルの依存性を解決するために必要になります。

以前、「wxWidgets でもクロスコンパイル」で紹介したサンプルを再掲して、現在の環境に合わせたクロスコンパイル方法を紹介します。サンプルは以下をベースにしています。

Hello World - wxWidgets

表示される文字列を日本語にした他は、同じプログラムです。

// Hello World program with wxWidgets
#include "wx/wx.h"

class MyApp: public wxApp
{
virtual bool OnInit();
};

class MyFrame: public wxFrame
{
public:

MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);

void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);

DECLARE_EVENT_TABLE()
};

enum
{
ID_Quit = 1,
ID_About,
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_MENU(ID_About, MyFrame::OnAbout)
END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame(_T("こんにちは、世界!"),
wxPoint(50,50), wxSize(450,340));
frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
wxMenu *menuFile = new wxMenu;

menuFile->Append(ID_About, _T("このプログラムについて(&A)"));
menuFile->AppendSeparator();
menuFile->Append(ID_Quit, _T("終了(&x)"));

wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append(menuFile, _T("ファイル(&F)"));

SetMenuBar(menuBar);

CreateStatusBar();
SetStatusText(_T("wxWidgets へようこそ!"));
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE);
}

void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(_T("はじめてのプログラム、こんにちは、世界!"),
_T("このプログラムについて"), wxOK | wxICON_INFORMATION, this);
}
// END PROGRAM
// hello.cpp


コンパイルには、Linux の pkg-config を利用するので、MinGW のバイナリがインストールされている /usr/i686-pc-mingw32/sys-root/mingw/bin へパスを通しておきます。もし、Linux 用の wxWidgets もインストールされている場合には、検索パスを順序も含めて適正に指定するか、pkg-config の代わりに MinGW クロスコンパイル用の i686-pc-mingw32-pkg-config を利用すればいいでしょう。

$ export PATH=$PATH:/usr/i686-pc-mingw32/sys-root/mingw/bin
$ echo $PATH
/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/bin:/usr/b
in:/usr/local/sbin:/usr/sbin:/sbin:/home/bitwalk/bin:/opt/mingw32ce/bin:/usr/i68
6-pc-mingw32/sys-root/mingw/bin

$ i686-pc-mingw32-g++ hello.cpp `wx-config --libs` `wx-config --cxxflags`
-o hello.exe


wbc で、ビルドした hello.exe が依存する DLL を調べると、次の様になります。




Wine


Wine 上で実行した例を示しました。

$ ./hello.exe


Windows


関連する DLL と一緒に Windows Vista へコピーして実行すると以下の様になります。とりあえず日本語表示は問題なさそうです。

Linux


Linux 上で Win32 用にクロスコンパイルしましたが、wxWidgets はクロスプラットフォーム対応のツールキットですので、Linux 上でそのまま、Linux ネイティブ用にコンパイルして実行することも(もちろん)できます。

$ g++ hello.cpp `wx-config --libs` `wx-config --cxxflags` -o hello
$ ./hello



[1] MinGW クロスコンパイル環境の設定