Paepoi

Paepoi » Gjs Tips » Gtk(Gjs) Tips

Gtk(Gjs) Tips

# 最終更新日 2020.08.02

GtkWindow
PyGObject では Python の class がそのまま使えますが Gjs では違います
ウインドウクラスを登録という C 言語の方法でバインドされているので注意
GTK+ バインドについては PyGObject とほぼ同様 PyGObject Tips
#!/usr/bin/gjs

/**
 * 複数のバージョンがある場合は指定が必要
 */
imports.gi.versions.Gtk = '3.0';

/**
 * 必要な Gir をインポートする
 */
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const System = imports.system;

/**
 * ウインドウクラスの登録、言語の class という意味では無い
 * GObject.registerClass は何も考えずこう書く
 * 継承は必ず var 宣言で行う必要がある
 */
var MyWindow = GObject.registerClass({
    GTypeName: 'MyWindow'
}, class MyWindow extends Gtk.ApplicationWindow {
    /**
     * 初期化は constructor ではなく _init を使う
     */
    _init(app) {
        /**
         * 継承の場合は親クラスの _init を呼ぶ
         * _init や new の引数はプロパティをオブジェクト形式で指定
         */
        super._init({
            application: app,
            title: 'はろー Gjs!'
        });
        /**
         * 変数は基本的に let 宣言で行う
         * 後で呼び出す場合は this.button と this にくっつける
         */
        let button = new Gtk.Button({
            label: 'ボタンを押してみてね(_B)',
            use_underline: true
        });
        /**
         * シグナルハンドラを無名関数で行う場合はアロー関数にする
         * function() で書くと this が呼び出し元に変わってしまう
         */
        button.connect('clicked', (widget)=> {
            widget.label = 'ハローワールド!';
        });
        this.add(button);
        this.show_all();
    }
});

/**
 * アプリケーションクラスの作成
 * メインループを受け持ち管理するウインドウが無くなると終了します
 */
var MyApplication = GObject.registerClass({
    GTypeName: 'MyApplication'
}, class MyApplication extends Gtk.Application {
    _init() {
        super._init();
    }
    /**
     * オーバーライドは
     * [ vfunk_メソッド名 ]
     * で予約されているので上書き注意
     */
    vfunc_activate() {
        let window = new MyWindow(this);
    }
});

/**
 * 実行、argv の指定はこうする
 */
let app = new MyApplication();
app.run([System.programInvocationName].concat(ARGV));

GdkEvent
PyGObject とはいくつか違っているところがあります
GdkEvent についてはまったく違うので注意
#!/usr/bin/gjs

imports.gi.versions.Gtk = '3.0';

const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const System = imports.system;

/*
 * クリックすると位置をラベルに書き出すアプリ
 */
var MyWindow = GObject.registerClass({
    GTypeName: 'MyWindow'
}, class MyWindow extends Gtk.ApplicationWindow {
    _init(app) {
        super._init({
            application: app,
            title: 'はろー Gjs!'
        });
        this.label = new Gtk.Label({
            label: 'x=*** y=***',
        });
        /**
         * PyGObject では値は GdkEvent のメソッドで得ることができる
         *  if event.type == Gdk.EventType.BUTTON_PRESS:
         *      self.label.props.label = f'x={event.x} y={event.y}'
         * Gjs では関数で値を取得する必要がある。
         */
        this.connect('button-press-event', (widget, event)=> {
            let type = event.get_event_type();
            if (type == Gdk.EventType.BUTTON_PRESS) {
                let [res, x, y] = event.get_coords();
                x = Math.round(x);
                y = Math.round(y);
                this.label.label = `x=${x} y=${y}`;
            }
        });
        this.add(this.label);
        this.resize(300, 300);
        this.show_all();
    }
});

var MyApplication = GObject.registerClass({
    GTypeName: 'MyApplication'
}, class MyApplication extends Gtk.Application {
    _init() {
        super._init();
    }
    vfunc_activate() {
        let window = new MyWindow(this);
    }
});

let app = new MyApplication();
app.run([System.programInvocationName].concat(ARGV));

プロパティ
プロパティアクセスに props のようなアクセス修飾子は無いので注意
/**
 * widget 作成、PyGObject はデフォルト引数で指定
 * button = Gtk.Button(label='ボタンを押してみてね(_B)', use_underline=True)
 */
let button = new Gtk.Button({
    label: 'ボタンを押してみてね(_B)',
    use_underline: true
});

/**
 * PyGObject は props アクセス修飾子を介するが Gjs にはそんなもの無い
 * button.props.label = 'スズキのバイクはカッコイイ'
 */
button.label = 'スズキのバイクはカッコイイ';

Copyright(C) sasakima-nao All rights reserved 2002 --- 2023.