wiki:PyGTK

Version 6 (modified by atzm, 18 years ago) (diff)

--

PyGTK

適当メモ.主に日記からの転載.

TextView

textField  = gtk.TextView()
textBuffer = textField.get_buffer()

[startIter, endIter] = textBuffer.get_bounds()
# [最初の位置, 最後の位置]

print textBuffer.get_text(startIter, endIter)
  • 最初の位置と最後の位置を取得し,中の文字列を得る

ある処理を x 秒後に裏で実行

def __init__(self):
    self.id = gtk.timeout_add(1000, self.run)

def run(self):
    ... # process
    return True

def stop(self):
    if self.id:
        gtk.timeout_remove(self.id)
  • run が True を返し続ける限りは繰り返し実行される.False が返ると止まる.

×ボタンが押された時にウィジェットを破壊せずに hide する

window = gtk.Widnow(gtk.WINDOW_TOPLEVEL)
window.connect("delete-event", close)
open(window)

def close(w):
    w.hide()
    return True

def open(w):
    w.show()

注意点は以下の通り.

  • destroy イベントでなく delete-event をフックする
  • close メソッドで True を返す

TextView 内の文字に色づけなど

textview = gtk.TextView()
buffer = textview.get_buffer()

tag = buffer.create_tag('tag_name')
tag.set_property('foreground', 'blue')
# tag_name という名前の,字の色を青にするタグの生成

buffer.insert_with_tags_by_name(buffer.get_end_iter(),
                                'hogehoge', 'tag_name')

TextView 内にハイパーリンク的なものを作ってみる

DnD は未実装.

#!/usr/bin/env python

import gtk
import gobject
import pango

class HyperTextView(gtk.TextView):
    __gtype_name__ = 'HyperTextView'
    __gsignals__ = {
        'anchor-clicked': (gobject.SIGNAL_RUN_LAST, None, (str, str, int)),
        }
    __gproperties__ = {
        'link':  (gobject.TYPE_PYOBJECT, 'link color', 'link color of TextView', gobject.PARAM_READWRITE),
        'active':(gobject.TYPE_PYOBJECT, 'active color', 'active color of TextView', gobject.PARAM_READWRITE),
        'hover': (gobject.TYPE_PYOBJECT, 'link:hover color', 'link:hover color of TextView', gobject.PARAM_READWRITE),
        }
    def do_get_property(self, prop):
        try:
            return getattr(self, prop.name)
        except AttributeError:
            raise AttributeError, 'unknown property %s' % prop.name
    def do_set_property(self, prop, val):
        if prop.name in self.__gproperties__.keys():
            setattr(self, prop.name, val)
        else:
            raise AttributeError, 'unknown property %s' % prop.name

    def __init__(self, buffer=None):
        gtk.TextView.__init__(self, buffer)
        self.link   = {'background': 'white', 'foreground': 'blue', 'underline': pango.UNDERLINE_SINGLE}
        self.active = {'background': 'light gray', 'foreground': 'red', 'underline': pango.UNDERLINE_SINGLE}
        self.hover  = {'background': 'light gray', 'foreground': 'blue', 'underline': pango.UNDERLINE_SINGLE}

        self.set_editable(False)
        self.set_cursor_visible(False)

        self.__tags = []

        self.connect('motion-notify-event', self._motion)
        self.connect('focus-out-event', lambda w, e: self.get_buffer().get_tag_table().foreach(self.__tag_reset, e.window))

    def insert(self, text, _iter=None):
        b = self.get_buffer()
        if _iter is None:
            _iter = b.get_end_iter()
        b.insert(_iter, text)

    def insert_with_anchor(self, text, anchor=None, _iter=None):
        b = self.get_buffer()
        if _iter is None:
            _iter = b.get_end_iter()
        if anchor is None:
            anchor = text

        tag = b.create_tag(None, **self.get_property('link'))
        tag.set_data('is_anchor', True)
        tag.connect('event', self._tag_event, text, anchor)
        self.__tags.append(tag)
        b.insert_with_tags(_iter, text, tag)

    def _motion(self, view, ev):
        window = ev.window
        x, y, _ = window.get_pointer()
        x, y = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y)
        tags = view.get_iter_at_location(x, y).get_tags()
        for tag in tags:
            if tag.get_data('is_anchor'):
                for t in set(self.__tags) - set([tag]):
                    self.__tag_reset(t, window)
                self.__set_anchor(window, tag, gtk.gdk.Cursor(gtk.gdk.HAND2), self.get_property('hover'))
                break
        else:
            tag_table = self.get_buffer().get_tag_table()
            tag_table.foreach(self.__tag_reset, window)

    def _tag_event(self, tag, view, ev, _iter, text, anchor):
        _type = ev.type
        if _type == gtk.gdk.MOTION_NOTIFY:
            return
        elif _type in [gtk.gdk.BUTTON_PRESS, gtk.gdk.BUTTON_RELEASE]:
            button = ev.button
            cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
            if _type == gtk.gdk.BUTTON_RELEASE:
                self.emit('anchor-clicked', text, anchor, button)
                self.__set_anchor(ev.window, tag, cursor, self.get_property('hover'))
            elif button in [1, 2]:
                self.__set_anchor(ev.window, tag, cursor, self.get_property('active'))

    def __tag_reset(self, tag, window):
        if tag.get_data('is_anchor'):
            self.__set_anchor(window, tag, None, self.get_property('link'))

    def __set_anchor(self, window, tag, cursor, prop):
        window.set_cursor(cursor)
        for key, val in prop.iteritems():
            tag.set_property(key, val)

gobject.type_register(HyperTextView)

if __name__ == '__main__':
    def clicked(widget, text, anchor, button):
        print widget, text, anchor, button

    t = HyperTextView()
    t.connect('anchor-clicked', clicked)
    t.link['foreground'] = 'dark blue'
    t.insert_with_anchor('Google', 'http://www.google.com/')
    t.insert('\n')
    t.insert_with_anchor('Yahoo!', 'http://www.yahoo.com/')

    w = gtk.Window()
    w.set_default_size(200, 100)
    w.connect('destroy', lambda w: gtk.main_quit())
    w.add(t)

    w.show_all()
    gtk.main()