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。
_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 の種類(?)がそもそも違うので…。
_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 はインストール済みだったので、その上で作業した。
これで必要なパッケージは入った。
MSYS2 MSYS (64bit) は一旦閉じて、MSYS2 MinGW 64-bit (64bit) を起動。MSYS用の環境と MinGW用の環境は、それぞれ、呼び出される Python が違うようで、後者じゃないと先ほどインストールしたパッケージが使えない。
この msys2 の bash上で gtk3-demo を実行。gtk3 でこんなことができる、と提示するデモウインドウが開いた。たしかに、gtk3 関係はインストールされたらしい。
公式ドキュメントで提示されていた以下の内容を hello.py として保存して、python hello.py を実行したところ、gtk3 のウインドウが開いてくれた。
また、前述の、pycairo + PyGObject を使用したスクリプトも動いてくれた。
コレで一応、Windows上でも PyGTK、というか PyGObject関係のサンプルを動かせる状態になった。
しかし…。msys2 をインストールしないと動かないというのは、HDDの容量的になかなか厳しい話だなと…。msys2 だけで、約9GB近くも容量を消費している…。全然お手軽ではない…。
_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 はインストール済みだったので、その上で作業した。
- MSYS2 MSYS (64bit) を起動。
- pacman -Syu
- 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 については…。
gtk.xxx については…。
定数名も違っていた。
他にも細かいところで違いがあるはず。
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。
_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
結果表示。
_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 に置き換えた。
結果表示。
◎ lineの表示。 :
pycairo を使って line を描画してみる。元サンプルは以下。
_Basic drawing in PyCairo
手元の環境で動くように修正した版。
_05_lines.py
ウインドウ内で何ヶ所か左クリックしてから右クリックすると、クリックした位置を全て繋ぐ線が描かれる。
結果表示。
ちょっとハマったのは、マウスクリックイベントを取得するあたり。クリックしてもイベントが発生しなくておかしいなと思っていたら、以下の一行が抜けていた…。
この一行が無いと、マウスクリックを取得できない模様。
_python - Mouse event in DrawingArea with PyGtk - Stack Overflow
_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()
ウインドウ内で何ヶ所か左クリックしてから右クリックすると、クリックした位置を全て繋ぐ線が描かれる。
結果表示。
ちょっとハマったのは、マウスクリックイベントを取得するあたり。クリックしてもイベントが発生しなくておかしいなと思っていたら、以下の一行が抜けていた…。
self.set_events(gtk.gdk.BUTTON_PRESS_MASK)
この一行が無いと、マウスクリックを取得できない模様。
_python - Mouse event in DrawingArea with PyGtk - Stack Overflow
[ ツッコむ ]
以上、1 日分です。