ホーム > python > pythonで画像表示

pythonで画像表示

2009 年 4 月 30 日

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行も書かずに画像ビューワが完成です。

yokoyama python