pythonで画像表示
pythonのGUIモジュールであるpygtkを使うと、簡単にウィンドウアプリケーションが作成できます。
しかもRADツールであるgladeインターフェース・デザイナを使えば、GUIの構成もサクサクです。
ということで、指定した画像を表示するアプリケーションを作ってみます。
環境はpythonとpygtkが動けばOKです。
まずは、pythonのコードです。
simage.pyファイルとして、保存して下さい。
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
# インポート
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
# メインウィンドウクラスの定義
class MainWindow:
# コンストラクタ
def __init__(self):
# gladeファイルから一発でGUIを構築
self.widgets = gtk.glade.XML("simage.glade", "window")
# イベントハンドラの割り当て
self.auto_connects()
# GtkImageをscrolledwindowに追加する
self.image = gtk.Image()
self["scrolledwindow"].add_with_viewport(self.image)
# MainWindowを表示する
self["window"].show_all()
# イベントハンドラの追加(gtk_ではじまるメソッドを登録)
def auto_connects(self):
event_handlers = {}
for (itemname, value) in self.__class__.__dict__.items():
if callable(value) and itemname.startswith('gtk_'):
event_handlers[itemname[4:]] = getattr(self, itemname)
self.widgets.signal_autoconnect(event_handlers)
# 指定されたアイテムが見つからない時に呼び出す(widgetの呼び出しを簡単にする)
def __getitem__(self, key):
return self.widgets.get_widget(key)
# ウィンドウの「閉じる」ボタンを押したときのイベントハンドラ
def gtk_on_window_delete_event(self, widget, event=None):
gtk.main_quit()
# メニューの「終了」を選んだときのイベントハンドラ
def gtk_on_quit_menu_item_activate(self, widget):
gtk.main_quit()
# メニューの「開く」を選んだときのイベントハンドラ
def gtk_on_open_menu_item_activate(self, widget):
dlg = gtk.FileChooserDialog(
"画像を開く",
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,gtk.RESPONSE_OK
)
)
dlg.set_default_response(gtk.RESPONSE_OK)
# 画像ファイルのフィルタを作る
filter = gtk.FileFilter()
filter.set_name("Images")
filter.add_mime_type("image/jpeg")
filter.add_mime_type("image/gif")
filter.add_mime_type("image/png")
filter.add_pattern("*.jpg")
filter.add_pattern("*.gif")
filter.add_pattern("*.png")
dlg.add_filter(filter)
# すべてのファイルのフィルタも作る
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dlg.add_filter(filter)
# ダイアログの表示
res = dlg.run()
# 「OK」ボタンを押したら、画像ファイルを開く
if res == gtk.RESPONSE_OK:
self.open_image(dlg.get_filename())
# ダイアログの破棄
dlg.destroy()
# 指定された画像を開く
def open_image( self, filename ):
self.image.set_from_file(filename)
# スタートアップ
if __name__ == "__main__":
window = MainWindow()
gtk.main()
続いて、gladeファイルです。
simage.gladeファイルとして保存して下さい。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.5 on Thu Apr 30 17:55:07 2009 -->
<glade-interface>
<widget class="GtkWindow" id="window">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">Simple Image Viewer</property>
<property name="default_width">350</property>
<property name="default_height">350</property>
<signal name="destroy" handler="on_window_destroy"/>
<signal name="delete_event" handler="on_window_delete_event"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">ファイル(_F)</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkImageMenuItem" id="open_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">開く(_O)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_open_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image2">
<property name="stock">gtk-open</property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit_menu_item">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">終了(_Q)</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_quit_menu_item_activate"/>
<child internal-child="image">
<widget class="GtkImage" id="menu-item-image5">
<property name="stock">gtk-quit</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">1</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="spacing">2</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
このgladeファイルは、gladeインターフェース・デザイナver3で作成しましたので、そのまま読み込むことができます。
よって、このXMLファイルは理解していなくても、gtkモジュールが勝手に解釈してくれます。
pythonコードをみると、22行目でGtkImageをロードしています。
gladeインターフェース・デザイナにもGtkImageはありますので、そこで設置しておけば良いはず。
しかし、設置して実行してみると、gladeの初期化(16行目)で警告が表示され、
ウィンドウのスクロールが正常に動作しませんでした。
./simage.py:16: GtkWarning: gtk_scrolled_window_add(): cannot add non scrollable widget use gtk_scrolled_window_add_with_viewport() instead
self.widgets = gtk.glade.XML(“simage.glade”, “window”)
とりあえず、プログラムでGtkImageを設置すると大丈夫です。
ということで、100行も書かずに画像ビューワが完成です。