mieki256's diary



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

#1 [python][windows][pygtk] PyGTK関係をインストール

pycairo の勉強をする関係で、Windows10上で、PyGTK 関係をインストールした。Web上で見かけたサンプルコードが、PyGTK を使って pycairo の描画結果を表示していたので、コレは入れたほうがいいのかな、と。

_PyCairo backends

ちなみに、今回の作業環境は、Windows10 x64 1903 + Python 2.7.17 / 3.8.0。

Python 2.7 の場合。 :

Windows + Python 2.7 で PyGTK を使いたいなら、GIMP 2.6.x Windows版 + Python-Fu を動かすために、PyGTK関係が一通り入ったインストーラが用意されているので、ソレをインストールすればいい。

_Index of /pub/GNOME/binaries/win32/pygtk/2.24

pygtk-all-in-one というのがソレ。Python 2.6用(py26)と、Python 2.7用(py27)があるので、既にインストール済みのPythonのバージョンに合わせて、インストールすればいい。

自分の環境では、Python 2.7.17 + pygtk-all-in-one-2.24.2.win32-py2.7.msi がインストール済みだった。

ただ、前述の、 pycairo用のサンプルコードは動かない。PyGTK の種類(?)がそもそも違うので…。

Python 3.5以降の場合。 :

PyGTK は、Python 3用としては用意されなくなって、代わりに PyGObject というものに置き換わっているらしい。

_PyGTK - Wikipedia

前述の pycairo用サンプルコードは、Python 3.x + PyGObject を使うことが前提のソースなので、Python 2.7.x + PyGTK 上では動かない。

Python 2.7, 3.1 - 3.4 までなら、「Windows環境でもコレをインストールすれば、PyGObject だの pycairo だの、そのへんが一通り全部入るよ」という便利なインストーラがあったらしいのだけど。

_PyGObject for Windows download | SourceForge.net

しかし、このインストーラは、Python 3.5以降には対応していない。

公式ドキュメントによると…。

_Getting Started - PyGObject

「Windows環境 + Python 3.5以降で PyGObject を使いたいなら、msys2 を使えるようにして、その上で色々インストールしろ」ということになってるっぽい。

一応、自分の環境にも msys2 はインストール済みだったので、その上で作業した。

  1. MSYS2 MSYS (64bit) を起動。
  2. pacman -Syu
  3. pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject

これで必要なパッケージは入った。

MSYS2 MSYS (64bit) は一旦閉じて、MSYS2 MinGW 64-bit (64bit) を起動。MSYS用の環境と MinGW用の環境は、それぞれ、呼び出される Python が違うようで、後者じゃないと先ほどインストールしたパッケージが使えない。

この msys2 の bash上で gtk3-demo を実行。gtk3 でこんなことができる、と提示するデモウインドウが開いた。たしかに、gtk3 関係はインストールされたらしい。

公式ドキュメントで提示されていた以下の内容を hello.py として保存して、python hello.py を実行したところ、gtk3 のウインドウが開いてくれた。

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

window = Gtk.Window(title="Hello World")
window.show()
window.connect("destroy", Gtk.main_quit)
Gtk.main()

また、前述の、pycairo + PyGObject を使用したスクリプトも動いてくれた。

コレで一応、Windows上でも PyGTK、というか PyGObject関係のサンプルを動かせる状態になった。

しかし…。msys2 をインストールしないと動かないというのは、HDDの容量的になかなか厳しい話だなと…。msys2 だけで、約9GB近くも容量を消費している…。全然お手軽ではない…。

PyGTK と PyGObject の違い。 :

ざっと見たところ、記述については、以下のような違いがあるように思えた。

import については…。
# Python 2.7 + PyGTK
import pygtk
import gtk
pygtk.require("2.0")
import cairo
# Python 3.7 + PyGObject
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import cairo

gtk.xxx については…。
  • PyGTK は gtk.xxx ―― 全部小文字で「gtk.」と書く。
  • PyGObject は Gtk.xxx ―― 最初の1文字を大文字にして「Gtk.」と書く。

定数名も違っていた。

# Python 2.7 + PyGTK
self.window.set_position(gtk.WIN_POS_CENTER)
# Python 3.7 + PyGObject
self.window.set_position(gtk.WindowPosition.CENTER)

他にも細かいところで違いがあるはず。

#2 [python][pycairo] pycairoについて勉強中

以下のサイトのサンプルコードを動かしながら勉強中。

_PyCairo backends
_Basic drawing in PyCairo

環境は、Windows10 x64 1903 + Python 2.7.17 + PyGTK 2.24.0 + pycairo 1.8.10。

PyGTK を使ってテスト。 :

gtk2を使って、pycairo の描画結果を表示してみる。元のサンプルは、以下のページにある。

_PyCairo backends

件のサンプルコードは Python 3.x + PyGObject 用だけど、自分の環境は、Python 2.7.x + PyGTK なので、記述を変えないといけない。

手元の環境で動くように変更した版。

_04_gtkwindow.py
# Python 2.7 + PyGTK
import pygtk
import gtk
import cairo
pygtk.require("2.0")

# Python 3.x + PyGObject
# import gi
# gi.require_version('Gtk', '3.0')
# from gi.repository import Gtk


class MyDrawingArea(gtk.DrawingArea):
    """My DrawingArea."""

    def __init__(self):
        super(MyDrawingArea, self).__init__()
        self.connect("size-allocate", self.on_self_size_allocate)
        self.connect("expose-event", self.on_self_expose_event)

    def on_self_size_allocate(self, widget, allocation):
        """Resize."""
        print("resize")
        self.__width = allocation.width
        self.__height = allocation.height

    def on_self_expose_event(self, widget, event):
        """Draw for pycairo."""
        print("draw")
        ctx = widget.window.cairo_create()

        ctx.set_source_rgb(0, 0, 0)
        ctx.select_font_face("Sans", cairo.FONT_SLANT_NORMAL,
                             cairo.FONT_WEIGHT_NORMAL)
        ctx.set_font_size(40)

        ctx.move_to(10, 50)
        ctx.show_text("Disziplin ist Macht.")


class MyApp(object):

    def __init__(self):
        self.window = gtk.Window()

        self.darea = MyDrawingArea()
        self.window.add(self.darea)

        self.window.connect("delete-event", self.on_delete_event)

        self.window.set_title("GTK window")
        self.window.resize(420, 140)

        # Python 2.7 + PyGTK
        self.window.set_position(gtk.WIN_POS_CENTER)

        # Python 3.7 + PyGObject
        # self.window.set_position(gtk.WindowPosition.CENTER)

    def on_delete_event(self, window, event, data=None):
        gtk.main_quit()
        return False

    def main(self):
        self.window.show_all()
        gtk.main()


if __name__ == "__main__":
    app = MyApp()
    app.main()

  • import 関係を変更。
  • Gtk. は、gtk. に書き換え。
  • drawイベントは、expose-event に置き換えた。

結果表示。

04_gtkwindow_ss01.png

lineの表示。 :

pycairo を使って line を描画してみる。元サンプルは以下。

_Basic drawing in PyCairo

手元の環境で動くように修正した版。

_05_lines.py
# Python 2.7 + PyGTK
import pygtk
import gtk
import cairo
pygtk.require("2.0")

# Python 3.x + PyGObject
# import gi
# gi.require_version('Gtk', '3.0')
# from gi.repository import Gtk


class MouseButton:
    LEFT_BUTTON = 1
    RIGHT_BUTTON = 3


class MyDrawingArea(gtk.DrawingArea):
    """My DrawingArea."""

    def __init__(self):
        super(MyDrawingArea, self).__init__()

        self.connect("size-allocate", self.on_self_size_allocate)
        self.connect("expose-event", self.on_self_expose_event)

        self.set_events(gtk.gdk.BUTTON_PRESS_MASK)
        # self.connect("button_press_event", self.on_button_press)
        self.connect("button-press-event", self.on_button_press)

        self.coords = []

    def on_self_size_allocate(self, widget, allocation):
        print("resize")
        self.__width = allocation.width
        self.__height = allocation.height

    def on_button_press(self, w, e):
        if e.type == gtk.gdk.BUTTON_PRESS:
            if e.button == MouseButton.LEFT_BUTTON:
                print("LEFT BUTTON")
                self.coords.append([e.x, e.y])
            elif e.button == MouseButton.RIGHT_BUTTON:
                print("RIGHT BUTTON")
                self.queue_draw()

    def on_self_expose_event(self, widget, event=None):
        """Draw for cairo."""
        print("on_draw")
        c = widget.window.cairo_create()
        c.set_source_rgb(0, 0, 0)
        c.set_line_width(0.5)

        for i in self.coords:
            for j in self.coords:
                c.move_to(i[0], i[1])
                c.line_to(j[0], j[1])
                c.stroke()
        del self.coords[:]


class MyApp(gtk.Window):

    def __init__(self):
        super(MyApp, self).__init__()
        self.connect("destroy", gtk.main_quit)

        self.darea = MyDrawingArea()
        self.add(self.darea)
        self.set_title("Lines")

        # Python 2.7 + PyGTK
        self.set_size_request(512, 512)
        self.set_position(gtk.WIN_POS_CENTER)

        # Python 3.7 + PyGObject
        # self.resize(300, 200)
        # self.set_position(gtk.WindowPosition.CENTER)

        self.show_all()


if __name__ == "__main__":
    app = MyApp()
    gtk.main()

ウインドウ内で何ヶ所か左クリックしてから右クリックすると、クリックした位置を全て繋ぐ線が描かれる。

結果表示。

05_lines_ss01.png

ちょっとハマったのは、マウスクリックイベントを取得するあたり。クリックしてもイベントが発生しなくておかしいなと思っていたら、以下の一行が抜けていた…。

        self.set_events(gtk.gdk.BUTTON_PRESS_MASK)

この一行が無いと、マウスクリックを取得できない模様。

_python - Mouse event in DrawingArea with PyGtk - Stack Overflow

以上、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