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アプリのウインドウ内に表示したくて、アレコレ試しているところだったりするのでした。

以上です。

過去ログ表示

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