Gtk4でのドラッグアンドドロップ
Gtk4でファイルをWidgetに何かをドラッグアンドドロップされた場合の処理の追加するのには、Gtk.DropTargetを使用します。このWidgetを使用すると、特定のWidgetにファイルなどをドロップした時の動作を指定できるようになります。
今回は、Gtk.DropTargetの使用方法について紹介します。
今回紹介する内容
・Widgetにファイルをドラッグされた場合の処理の追加方法
Gtk4でのドラッグアンドドロップの設定方法
- Gtk.DropTargetを作成するして、Widgetに追加する。
- Gtk.DropTargetを定義する。
- Gtk.DorpTargetのdropシグナルに、関数を紐付ける。
- ドラッグアンドドロップに対応させるWidgetにGtk.Widget.add_controller()で追加する。
- dropシグナルに紐付けた関数に処理を記入する。
1. Gtk.DropTargetを作成するして、Widgetに追加する。
Gtk.DropTargetを定義する。
Gtk.DropTargetの引数はtypeとactionであり、今回はファイル名を取得するもの作成するので、typeにはGtk.FileList、actionにはGdk.DragAction.COPYを指定します。
drop_target = Gtk.DropTarget.new(Gdk.FileList, Gdk.DragAction.COPY)
Gtk.DorpTargetのdropシグナルに、関数を紐付ける。
対象のWidgetにファイルをドロップした場合に、関数を実効するために、以下のようにdropシグナルと関数(self._drop)を紐付けます。
drop_target.connect("drop", self._drop)
ドラッグアンドドロップに対応させるWidgetにGtk.Widget.add_controller()で追加する。
Widgetをドラッグアンドドロップに対応させるために、作成したGtk.DropTargetをWidgetにGtk.Widget.add_controller()を使用して追加します。
self.picture.add_controller(drop_target)
2. dropシグナルに紐付けた関数に処理を記入する。
dropシグナルに紐付けた関数の引数は以下のとおりです。
- drag_target(Gtk.DropTarget) : シグナルを受信したオブジェクト
- value (GObject.Value): ドロップされる GValue
- x (float): 現在のポインター位置の x 座標
- y (float): 現在のポインター位置の y 座標
drop_targetの定義においてtypeにGdk.FileListを指定しているため、valueはGdk.FileListの値になっています。そのため、ドラッグアンドドロップしたファイルの名前のリストは、valueにGdk.FileList.get_files()を使用することで取得できます。
def _drop(self, drop_target, value, x, y):
files = value.get_files()
サンプルプログラム
サンプルプログラムを実行すると、Gtk.Pictureが載ったウィンドウが表示されます。Gtk.Pictureにjpgファイルをドラッグアンドドロップすると、Gtk.Pictureにそのjpgファイルの画像が表示されます。
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.17.0 -->
<interface>
<!-- interface-name ui_file.ui -->
<requires lib="gtk" version="4.10"/>
<template class="window" parent="GtkApplicationWindow">
<property name="default-height">420</property>
<property name="default-width">340</property>
<child>
<object class="GtkPicture" id="picture">
<property name="margin-bottom">20</property>
<property name="margin-end">20</property>
<property name="margin-start">20</property>
<property name="margin-top">20</property>
</object>
</child>
</template>
</interface>
import os
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gdk
APPID = 'com.github.taniyoshima.test_gtk4_picture'
@Gtk.Template(filename=os.path.dirname(__file__) + '/ui_file.ui')
class Gtk4TestTest(Gtk.ApplicationWindow):
__gtype_name__ = "window"
picture = Gtk.Template.Child()
def __init__(self, app):
Gtk.Window.__init__(self, application=app)
drop_target = Gtk.DropTarget.new(Gdk.FileList, Gdk.DragAction.COPY)
drop_target.connect("drop", self._drop)
self.picture.add_controller(drop_target)
def _drop(self, drop_target, value, x, y):
files = value.get_files()
# ファイル数の確認
if len(files) == 1:
filename = files[0].get_path()
# 拡張子の確認 *jpg
if filename.find('.jpg') > 0:
self.picture.set_file(files[0])
class Gtk4TestApp(Gtk.Application):
def __init__(self):
Gtk.Application.__init__(self, application_id=APPID)
def do_activate(self):
window = Gtk4TestTest(self)
window.present()
def main():
app = Gtk4TestApp()
app.run()
if __name__ == '__main__':
main()