mieki256's diary



2019/11/11(月) [n年前の日記]

#1 [wxpython][python] pycairoの描画結果をwxPythonで表示

PyGTK を使うと、入力欄を含んだ Widget を表示するだけで謎の警告メッセージが出てしまう。GTK+ は使えんなと。

ならば、他のGUIライブラリはどうだろう。試したら、少なくとも wxPython はその手のメッセージは出さなかったので、GUI部分は wxPython で書こうかなと。

しかし、pycairo で surface に描画した結果を、wxPython で表示することはできるのかな。どうなんだろう。

試してみた。一応できた。たぶん。環境は、Windows10 x64 + Python 2.7.17 32bit + wxPython 4.0.7.post1 + pycairo 1.8.10。

wxpython_with_pycairo_ss0.png

Generateボタンをクリックすると、pycairo を使って、surface 内に、ランダムに矩形を描画して、その surface を wxPython で表示する。みたいな。

_wxpython_with_pycairo.py
import wx
import wx.lib.wxcairo
import cairo
import random
import math
import time


random_seed = 42


def make_texture(tw, th):
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, tw, th)
    cr = cairo.Context(surface)

    # fill BG
    cr.set_source_rgb(0, 0, 0)
    cr.rectangle(0, 0, tw, th)
    cr.fill()

    random.seed(random_seed)

    # fill rectangles
    for i in range(96):
        w = int(random.uniform(tw * 0.02, tw * 0.25))
        h = int(random.uniform(th * 0.02, th * 0.25))
        x = random.randint(0 - w, tw - 1)
        y = random.randint(0 - h, th - 1)

        r = random.uniform(0.0, 1.0)
        g = random.uniform(0.0, 1.0)
        b = random.uniform(0.0, 1.0)
        a = random.uniform(0.0, 1.0)

        cr.set_source_rgba(r, g, b, a)
        cr.rectangle(x, y, w, h)
        cr.fill()

    return surface


class MyDrawingArea(wx.Panel):

    def __init__(self, parent):
        super(MyDrawingArea, self).__init__(parent, wx.ID_ANY, size=(512, 512))
        self.w, self.h = 512, 512
        self.SetBackgroundColour([64, 64, 64])
        self.SetDoubleBuffered(True)
        self.Bind(wx.EVT_PAINT, self.on_paint)

    def on_paint(self, e):
        dc = wx.PaintDC(self)
        cr = wx.lib.wxcairo.ContextFromDC(dc)
        # w, h = self.Size.GetWidth(), self.Size.GetHeight()
        self.surface = make_texture(self.w, self.h)
        cr.set_source_surface(self.surface, 0, 0)
        cr.paint()


class MyFrame(wx.Frame):

    def __init__(self, title):
        super(MyFrame, self).__init__(None, title=title, size=(720, 600))

        self.panel = wx.Panel(self)

        self.btn1 = wx.Button(self.panel, wx.ID_ANY, "Generate")
        self.btn1.Bind(wx.EVT_BUTTON, self.on_click_generate)

        self.btn2 = wx.Button(self.panel, wx.ID_ANY, "Redraw")
        self.btn2.Bind(wx.EVT_BUTTON, self.on_click_redraw)

        self.darea = MyDrawingArea(self.panel)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.vbox.Add(self.btn1, 2)
        self.vbox.Add(self.btn2, 1)

        self.hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.hbox.Add(self.darea, 4, wx.EXPAND | wx.ALL, 8)
        self.hbox.Add(self.vbox, 1)
        self.panel.SetSizer(self.hbox)

    def on_click_generate(self, event):
        global random_seed
        random_seed = math.floor(time.time() * 100)
        self.darea.Refresh()

    def on_click_redraw(self, event):
        self.darea.Refresh()


def main():
    app = wx.App(False)
    frm = MyFrame("wxPython with pycairo")
    frm.Show()
    app.MainLoop()


if __name__ == '__main__':
    main()

以下のページを参考にした。ありがたや。

_python - Drawing with cairo in wxpython - Stack Overflow

肝は、このあたりだろうか…。

import wx
import wx.lib.wxcairo

# ...

    def on_paint(self, e):
        dc = wx.PaintDC(self)
        cr = wx.lib.wxcairo.ContextFromDC(dc)
        self.surface = make_texture(self.w, self.h)
        cr.set_source_surface(self.surface, 0, 0)
        cr.paint()

それと、wxPython の Widget の再描画は、.Refresh() を呼べばいいらしい。どうすれば再描画してくれるのか分からなくて、ちょっとハマった。

    def on_click_redraw(self, event):
        self.darea.Refresh()

余談。 :

GUIアプリのウインドウ内で図形描画をするだけなら、wxPython にも図形描画機能があるので、全て wxPython の機能だけで実験ができるのだけど。

今回は、GIMP の Python-Fu (Gimp-Python) にも流用できる図形描画処理を書きたくて。となると、pycairo縛りで図形描画する必要があって。故に、pycairo の描画結果をGUIアプリのウインドウ内に表示したくて、アレコレ試しているところだったりするのでした。

#2 [wxpython][python] wxGlade 0.9.4 を試用

wxPython の Widget をレイアウトするのが結構面倒臭い。そういう時のために、レイアウトを試行錯誤できるツールがいくつかあって。その手のツールは、RAD と呼ばれてるらしいけど。

_XRCed Homepage
_wxGlade: a GUI builder for wxWidgets/wxPython
_Releases - wxFormBuilder/wxFormBuilder

今回は、wxGlade 0.9.4 を使ってみたり。

昔はスタンドアローン版があったのだけど、今現在は、Python + wxPython をインストールした環境で動かせる Python スクリプトとして公開されているようで。wxGlade-0.9.4.zip をDLして解凍すると、中に wxglade.pyw というファイルがあるので、それを実行すると起動する模様。

wxPython 向けのレイアウトファイルを作成したい場合、2つの方法があるようで。


Pythonスクリプトとして出力してみたソレは、手元の環境で実行したら、そのままレイアウトも再現されたのだけど。XRC を読み込んで表示するソレは、読み込むスクリプトを書いて動かしても、何故かエラーメッセージが出てしまってハマっているところ。subclass がどうとか表示されてるけど、何がおかしいのか…。

巷の解説ページのサンプルを動かすと、表示されるのだよなあ…。wxGlade 上でレイアウトをする際に、自分が何か間違って操作している、ということだよな…。

XRCed はどうなったんだろう。 :

昔は、wxPython に XRCed が同梱されていた記憶があるのだけれど。今はどうなってるんだろう…。最新版が 2007年っぽいし、開発停止状態ってことなのかな…。

#3 [prog] GUIレイアウトのMarkdown的フォーマットはないのだろうか

GUIアプリのレイアウトにおける、Markdown的なフォーマットって無いのかなと、なんとなく思ったり。

分かる人なら、これで話は終わりというか。

GUIレイアウト指定のトレンド。 :

一応、簡単に説明。

GUIアプリを作る際は、「ウインドウ内の、このへんに、このWidget(GUI部品)が配置されて、そのWidgetはこんなプロパティを持ってるよ」といった指定を ―― レイアウト情報を記述していく必要があって。

それらレイアウト情報は、プログラムのソース内に、プログラマーが手打ちで記述していくことも、一応はできるのだけど。

しかし、一般的には、レイアウト情報だけをまとめた別ファイルを書いて、プログラム側はソレを読み込んでレイアウトをする事例が多いわけで。それがトレンドというか、随分前から当たり前になってるようで。

そりゃまあ、そうなるよなと。だって、Widgetの位置やサイズを変更するたびに、UIのデザイナーさんがプログラマーにお願いして、プログラムソースを弄ってもらうとか、そんなの面倒臭いし…。間違って、計算その他の処理部分を弄ってしまってエンバグしたらヤバいし…。見た目とロジックは分離しておいたほうがいいわけで。

もしかすると、Webページが、ページ内容を記述する HTML と、ページの見た目についての指定を記述する CSS に分かれている、てなノリに近いのかもしれない。見た目に関する情報だけをまとめて別ファイルで管理しようぜ、そのほうがイケてるぜ、みたいな。

それらレイアウトを指定するファイルのフォーマットは、GUIライブラリ毎に違っていて。

  • wxWidgets (wxPython) : XRC
  • Kivy : .kv
  • Microsoft : XAML?
  • Qt : QML?

他にも色々あるだろうけど、つまりは各ライブラリが自身にとって都合のいいように、フォーマットを勝手気ままに決めている状態というか。

統一できないのかな。 :

GUIレイアウト情報を記述するフォーマットは、GUIライブラリ毎に違っているので、たくさん種類があるというか、乱立しちゃってるわけだけど。

なんだかこのへん、wiki記法とか、はてな記法とか、HNS(hnf) とか、reStructuredText とか、Markdown とか、その手の軽量マークアップ言語を連想するなと。

少し説明しておくと…。HTML だの PDF だの、そのあたりのソースは、コンピュータが読み書きして処理がしやすくなることを前提にしたフォーマットなので、そんなものを人間が直接手打ちで書いていくなんて馬鹿馬鹿しいよなと。まだ人間でも分かり易くて、比較的よく使う機能だけをまとめた簡単なルールで、一旦、元になる文書を書いて、それを HTML や PDF に変換すればええやん ―― という発想で、wiki記法だの、Markdownだの、色々な軽量マークアップ言語が次々に発明されてきたわけで。その中でも、テキスト形式の状態で何が書いてあるかが「見た目」「パッと見」で分かり易い Markdown が、徐々に人気を得て席巻してきた、という状況があって。

そのあたりを考えると、GUIレイアウトについても、とりあえずコレで書いとけば他のGUIライブラリでも流用できる、人間が直接手打ちすることも不可能ではない程度には分かり易いし、みたいなフォーマットがあったりはしないのかなあ、と。

もっとも、そういった分野のデファクトスタンダードを狙って、各社・各組織・各ライブラリが、その手のフォーマットを提示してきたから、こうして乱立してるのだろうけど…。

ライブラリ毎に持ってる機能が違うので、共通化できない面もあるのだろうな。時々、「Markdown は機能が少な過ぎる」と文句が出たりもするけれど、「分かり易くすると、できることも少なくなる」というか…。何でもそうだけど、結局はトレードオフ、なのかも。

#4 [prog][neta] オレオレGUIレイアウトフォーマット

Markdown みたいなGUIレイアウトフォーマットを作れないかなと妄想。Markdown の売りは、テキスト形式の状態でも既に見た目で分かり易い、というところなので、そのあたりを…。

top:wxFrame ----------------------------------------------------+
|                                                               |
| panel_1:wxPanel -------------------------------------------+  |
| |                                                          |  |
| | hbox:wxSizer -----------------------------------------+  |  |
| | |                                                     |  |  |
| | |  button_1:wxButton ----+   button_2:wxButton ----+  |  |  |
| | |  | New                 |   | Open                |  |  |  |
| | |  +---------------------+   +---------------------+  |  |  |
| | +-----------------------------------------------------+  |  |
| +----------------------------------------------------------+  |
+---------------------------------------------------------------+

ダメだ…。どう考えても書くのが面倒臭い…。専用のツールが欲しくなる、ってソレなら既存のRAD使えば済むやんという話に…。

手打ちなら、QMLのように「{〜}」を使ったり、.kv のようにインデントを使って階層を記述するほうが妥当というか現実的だよなと再認識。

さすがに xml を書くのは今時厳しい。

以上、1 日分です。

過去ログ表示

Prev - 2019/11 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project