Programming」カテゴリーアーカイブ

GtkGestureDrag

GtkGesture ラスト、GtkGestureDrag を。
マウスでドラッグすると文字列が着いてくるサンプルコード。

#!/usr/bin/env python3
 
import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        GtkGestureDrag Sample Code
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.offset_x = 50
        self.offset_y = 50
        self.draw_x = 0
        self.draw_y = 0
        # gesture drag
        drag = Gtk.GestureDrag()
        drag.connect('drag-begin', self.on_gesture_drag_begin)
        drag.connect('drag-update', self.on_gesture_drag_update)
        drag.connect('drag-end', self.on_gesture_drag_end)
        self.add_controller(drag)
        # view
        self.view = Gtk.DrawingArea()
        self.view.set_draw_func(self.view_draw_func)
        self.set_child(self.view)
        # resize
        self.set_default_size(400, 300)

    def view_draw_func(self, da, cr, width, height):
        cr.move_to(self.draw_x + self.offset_x, self.draw_y + self.offset_y)
        cr.set_font_size(36)
        cr.show_text('Drag and Drop')

    def on_gesture_drag_begin(self, ges, offset_x, offset_y):
        pass

    def on_gesture_drag_end(self, ges, offset_x, offset_y):
        self.offset_x += offset_x
        self.offset_y += offset_y

    def on_gesture_drag_update(self, ges, offset_x, offset_y):
        self.draw_x = offset_x
        self.draw_y = offset_y
        self.view.queue_draw()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

app = App()
app.run(sys.argv)

drag

それと残りに GtkGestureStylus なんてのがあるけど。
どう考えてもスタイラスペン用途だよなって。
持っていないし GNOME てか Linux での使い道も思いつかない。
クリスタが Linux 対応するはずがないし、適材適所だよ。
なので無視でいいかなって。

ところでコレはファイルマネージャからのドロップではない。
GTK4 は drag_dest_add_uri_targets が使えないね。

Drag & dropping files with GTK4 – Platform – GNOME Discourse

こんなのを見つけたけど同じ所でクラッシュする。
うーん、今日もゲンナリするくらい進まない。

GtkGestureSwipe on Macbook

GTK4 ページを作ろうとしていますが、進んでいない。
てゆーか GtkGestureSwipe が Macbook で動作しません。

1

そもそも Eye of GNOME にて上記が動作がしません。
ちなみに X11 でログインすると拡大や回転もできなくなります。

2

Macbook Air 2011 でも Wayland がデフォルトになります。
この状態でスワイプ以外は全部動く、やはり X11 ではズームできません。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        Fedora 34 on Macbook Air 2011
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.mem_pan = -1
        # touch || mouse button
        click = Gtk.GestureClick()
        click.connect('released', self.on_gesture_click_released)
        # long press
        lpress = Gtk.GestureLongPress()
        lpress.connect('pressed', self.on_gesture_long_press_pressed)
        # pan
        pan = Gtk.GesturePan(orientation=Gtk.Orientation.VERTICAL)
        pan.connect('pan', self.on_gesture_pan)
        # swipe (no...)
        swipe = Gtk.GestureSwipe(touch_only=True)
        swipe.connect('swipe', self.on_gesture_swipe_swipe)
        # zoom
        zoom = Gtk.GestureZoom()
        zoom.connect('scale-changed', self.on_gesture_scale_change)
        #
        self.label = Gtk.Label(label='start')
        self.label.add_controller(click)
        self.label.add_controller(lpress)
        self.label.add_controller(pan)
        self.label.add_controller(swipe)
        self.label.add_controller(zoom)
        # resize
        self.set_child(self.label)
        self.set_default_size(600, 600)

    def on_gesture_pan(self, ges, direction, offset):
        if direction != self.mem_pan:
            self.mem_pan = direction
            if direction == Gtk.PanDirection.UP:
                self.label.props.label += '\npan up'
            else:
                self.label.props.label += '\npan down'

    def on_gesture_long_press_pressed(self, ges, x, y):
        self.label.props.label += '\nlong press'

    def on_gesture_click_released(self, ges, n_press, x, y):
        if n_press == 2:
            self.label.props.label += '\ndouble clicked'

    def on_gesture_swipe_swipe(self, ges, x, y):
        self.label.props.label += f'\nswipe x={round(x)} y={round(y)}'

    def on_gesture_scale_change(self, zoom, scale):
        w = round(600 * scale)
        h = round(600 * scale)
        self.set_default_size(w, h)

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

app = App()
app.run(sys.argv)

3

ちなみに Macbook に Fedora 34 を入れた場合。
以下のトラックパッドジェスチャがデフォルト状態の GNOME 40 で可能。

三本指の上スワイプでアクティビティ画面。
もう一度同じ動作でアプリケーションランチャ。
三本指の横スワイプで仮想デスクトップの異動。
Eye of GNOME にて画像の拡大縮小と回転。

探せばジェスチャを追加できるサードパーティ拡張もあるんだけど。
上記のデフォルトとコンフリクトすると思う、試していないけど。
X11 でログインするとやはり何も動作しません。

考えてみれば二本指ジェスチャってスクロール動作と同じだし。
スワイプジェスチャと両立している macOS ってスゲェんだなって。
サーフェスとかは触ったことすら無いので知らない。

しかし本当に思う、やっぱり Macbook は macOS で使うのが一番だよ。
Fedora で使うと command と control キーの違いをどうしても間違えるし。

GtkGestureRotate

今回は GtkGestureRotate で画像を回転してみる。

ただコレはタッチパネルか対応トラックパッドが必要なんだな。
筆者は古い Macbook Air 2011 に Fedora を入れているのでソレで。
多分 Windows で対応ノートに入れても結果は同じ、だと思う。

それと、回転のピボットポイントを指定する方法が見つからなかった。
今回は下記ページ中心あたりにある一度ズラして元の位置に戻す方法で。

Cairo samples

もしかして cairo だけだとソレしか手段が無いのかな?
Clutter が使えるなら簡単なんだけど、GTK4 には乗せられないし。
とにかく上手くいったコード。

#!/usr/bin/env python3
 
import gi, sys, cairo
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

FILENAME = '300x225.png'

class Win(Gtk.ApplicationWindow):
    '''
        GtkGestureRotate Sample Code
        TouchPanel or Trackpad
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.view_angle = 0.0
        # gesture
        rotate = Gtk.GestureRotate()
        rotate.connect('angle-changed', self.on_angle_changed)
        self.add_controller(rotate)
        # view
        self.surface = cairo.ImageSurface.create_from_png(FILENAME)
        self.view = Gtk.DrawingArea()
        self.view.set_draw_func(self.view_draw_func)
        # self
        self.set_child(self.view)
        self.set_size_request(400, 300)
        self.present()

    def view_draw_func(self, da, cr, width, height):
        cr.translate(200, 150)
        cr.rotate(self.view_angle) # 0.0 - 1.0
        cr.translate(-200, -150)
        cr.set_source_surface(self.surface)
        cr.paint()

    def on_angle_changed(self, gesture, angle, delta):
        self.view_angle = angle
        self.view.queue_draw()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        pass

app = App()
app.run(sys.argv)

rotate

Mac では上手くいった。

後は再回転させる時に前回の回転位置から開始する処理だ。
eog を参考にしようと思ったらコレ 90 度ずつしか回転しないのねん。。。

そんなことよりさ。
M1 Mac に慣れてしまって 2011 Air が遅くてもどかしい。。。。。

GtkGestureClick

前回 GtkPan って何だよ GtkGesturePan だろ。
まあいいか、自戒を込めてそのままのタイトルにしておこう。

ところで、ウソを書いてごめんなチャイ。
ダブルクリック検出は n_press パラメータで判別できました。
あの時は何をやっても 1 だったんだけど、実験コードを間違えていただけっぽい。

#!/usr/bin/env python3
 
import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        Double Click is Destroy
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # Mouse Button Press
        ges = Gtk.GestureClick()
        #ges.set_button(0) # zero is All Mouse Button
        ges.connect('released', self.on_gesture_click_released)
        self.add_controller(ges)
        # resize
        self.set_default_size(400, 300)
        # activate
        self.present()

    def on_gesture_click_released(self, ges, n_press, x, y):
        print(n_press)
        if n_press == 2:
            self.close()
        else:
            print(x)
            print(y)

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        pass

app = App()
app.run(sys.argv)

button プロパティでどのボタンを使うか選択、デフォルトは 1 なのか。
ゼロをセットでどのボタンにも反応する、なるほど。

いやそれはいいんだ。

HANDLES_COMMAND_LINE 指定で activate が発行されないまんまじゃないか!
GtkApplication は GTK3 と何も変わっていないってどうよ。
いやまあ、コイツは GLib::GApplication のサブクラスだし。
GLib 側がどうにかしてくれないとこのまんまってことだろう。

連休でイケると思ったけど全然進まなかった、今月中には。。。。。

GtkPan

困った。
Gtk ? 4.0: Migrating from GTK 3.x to GTK 4

GTK4 Python のページを作っているんだが。
GtkWdget の draw シグナルが廃止されていたのを忘れていた。

つまり枠無しウインドウで背景透過させる手段が無くなった。
これじゃ萌え萌えなデスクトップマスコットが作れないじゃん。
いや作る気は全然無いんだけど。

それと button-press-event 等が GtkGesture を使いなさいに変わった。
GtkGestureClick を試してみたけどダブルクリックの検出ができないみたい。
パンやスワイプが AppKit なんかより簡単に実装できるようになっているけど。

#!/usr/bin/env python3
 
import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        GtkPan Sample Code
        TouchPanel and Mouse
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.mem_pan = -1
        # pan
        pan = Gtk.GesturePan(orientation=Gtk.Orientation.VERTICAL)
        pan.connect('pan', self.on_pan)
        self.add_controller(pan)
        # resize
        self.set_default_size(400, 300)

    def on_pan(self, ges, direction, offset):
        '''
            Pan Up on Quit
        '''
        if direction != self.mem_pan:
            self.mem_pan = direction
            if direction == Gtk.PanDirection.UP:
                self.close()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

app = App()
app.run(sys.argv)

てか GTK4 はマジでタッチパネル前提ってことですね。
過去のを残すと WindowsForm みたいに誰も WPF を使わない、みたいになるし。
AppKit もネットで見つけたコードは非推奨ばかり、みたいになるし。
GTK4 は正常進化に見えて実は過去をバッサリって感じです。

ついでに、GTK+ のドキュメントはプロパティのデフォルト値を書いていない。
GtkPan::orientation のデフォルトは HORIZONTAL だった。
自分で確かめるしか今は手段が無い、面倒なんですけど。

GTK3 のをそのまま書き換えしようと思っていたけど無理だ。
どういう感じでまとめよう?あぁまた更新が滞る。。。。。