La méthode drag_source_set
()
indique un ensemble de types de cibles pour une opération de glisser sur un widget.
widget.drag_source_set(start_button_mask
,targets
,actions
)
Les paramètres ont la signification suivante :
Le paramètre widget
indique le
widget origine du glisser
Le paramètre start_button_mask
indique
un masque de bits des boutons qui peuvent débuter le glisser
(par ex. BUTTON1_MASK
)
Le paramètre targets
indique une liste de
types de données cibles gérées par le glisser
Le paramètre actions
indique un masque
de bits des actions possibles pour un glisser depuis cette fenêtre
Le paramètre targets
est une liste de
tuples semblable à :
(target, flags, info)
... où target
est une chaîne de
caractères représentant le type de glisser
... où flags
limite la portée du
glisser. Il peut prendre la valeur 0 (pas de limitation de la portée)
ou la valeur des constantes suivantes :
gtk.TARGET_SAME_APP # La destination peut être sélectionnée pour un glisser à l'intérieur de la même application gtk.TARGET_SAME_WIDGET # La destination peut être sélectionnée pour un glisser à l'intérieur du même widget
... où info
est un identifiant entier
assigné à l'application.
S'il n'est plus nécessaire qu'un widget continue d'être l'origine
d'une opération de glisser-déposer, la méthode
drag_source_unset
()
widget.drag_source_unset()
Les signaux suivants sont envoyés au widget origine pendant une opération de glisser-déposer :
Tableau 22.1. Signaux du widget origine
drag_begin (début du glisser) | def drag_begin_cb(widget, drag_context, data): |
drag_data_get (obtention des données du glisser) | def drag_data_get_cb(widget, drag_context, selection_data, info, time, data): |
drag_data_delete (suppression des données du glisser) | def drag_data_delete_cb(widget, drag_context, data): |
drag_end (fin du glisser) | def drag_end_cb(widget, drag_context, data): |
Le gestionnaire du signal "drag-begin" peut être utilisé pour
définir des conditions de départ telle que l'icône du glisser en utilisant
une des méthodes suivantes de la classe Widget
:
drag_source_set_icon
(),
drag_source_set_icon_pixbuf
(),
drag_source_set_icon_stock
(). Le gestionnaire
du signal "drag-end" peut servir à annuler les actions du gestionnaire
du signal "drag-begin".
Le gestionnaire du signal "drag-data-get" devrait renvoyer les
données de glisser correspondantes à la destination indiquée par le paramètre
info
. Il fournit à
gtk.gdk.SelectionData
les données du glisser.
Le gestionnaire du signal "drag-delete" est utilisé pour supprimer
les données du glisser d'une action gtk.gdk.ACTION_MOVE
une fois la copie des données effectuée.
La méthode drag_dest_set
() indique que
ce widget peut recevoir le déposer et précise les types de déposer qu'il
peut accepter.
La méthode drag_dest_unset
() indique que ce
widget ne peut plus maintenant recevoir de déposer.
widget.drag_dest_set(flags
,targets
,actions
) widget.drag_dest_unset()
... où le paramètre flags
indique quelles
actions GTK+ doit réaliser pour le widget pour y effectuer le dépot. Voici
les valeurs possibles pour flags
:
gtk.DEST_DEFAULT_MOTION |
Si activé pour un widget, GTK+ vérifiera, pendant le survol
d'un glisser au-dessus de ce widget, si le glisser appartient à la liste
des cibles et actions possibles de ce widget. Alors, GTK+ appellera
la méthode |
gtk.DEST_DEFAULT_HIGHLIGHT |
Si activé pour un widget, GTK+ mettra en évidence ce widget pendant la durée du survol par le glisser, si l'action et le format du widget sont compatibles. |
gtk.DEST_DEFAULT_DROP |
Si activé pour un widget, au moment du déposer, GTK+ vérifiera
si le glisser concorde avec la liste des cibles et action possibles
de ce widget ; si oui, GTK+ appellera la méthode
|
gtk.DEST_DEFAULT_ALL |
Si activé, indique que toutes les actions précédentes doivent être rélisées. |
Le paramètre targets
est une liste de
tuples d'information de cibles décrites précèdemment.
Le paramètre actions
est un masque de bits
des actions possibles à réaliser lors d'un glisser sur ce widget. Les
valeurs possibles, combinables avec l'opérateur OR, sont les suivantes :
gtk.gdk.ACTION_DEFAULT gtk.gdk.ACTION_COPY gtk.gdk.ACTION_MOVE gtk.gdk.ACTION_LINK gtk.gdk.ACTION_PRIVATE gtk.gdk.ACTION_ASK
Les paramètres targets
et
actions
sont ignorés si le paramètre
flags
ne contient pas gtk.DEST_DEFAULT_MOTION
ou gtk.DEST_DEFAULT_DROP
. Dans ce cas, l'application
doit gérer les signaux "drag-motion" et "drag-drop".
Le gestionnaire du signal "drag-motion" doit déterminer si les
données du glisser sont appropriées en comparant les cibles de destination
avec les cibles gtk.gdk.DragContext
. Il peut aussi
étudier les données du glisser en appelant la méthode
drag_get_data
() method. Il faut utiliser la méthode
gtk.gdk.DragContext
.drag_status
()
pour mettre à jour le statut du paramètre drag_context
.
Le gestionnaire du signal "drag-drop" doit déterminer la cible qui
correspond en utilisant la méthode
drag_dest_find_target
() du widget et ensuite réclamer
les données du glisser en utilisant la méthode
drag_get_data
(). Les données
seront disponibles dans le gestionnaire du signal "drag-data-received".
Le programme
dragtargets.py
affiche les cibles possible d'une opération de glisser dans un widget étiquette.
1 #!/usr/local/env python 2 3 import pygtk 4 pygtk.require('2.0') 5 import gtk 6 7 def motion_cb(wid, context, x, y, time): 8 context.drag_status(gtk.gdk.ACTION_COPY, time) 9 return True 10 11 def drop_cb(wid, context, x, y, time): 12 l.set_text('\n'.join([str(t) for t in context.targets])) 13 context.finish(True, False, time) 14 return True 15 16 w = gtk.Window() 17 w.set_size_request(200, 150) 18 w.drag_dest_set(0, [], 0) 19 w.connect('drag_motion', motion_cb) 20 w.connect('drag_drop', drop_cb) 21 w.connect('destroy', lambda w: gtk.main_quit()) 22 l = gtk.Label() 23 w.add(l) 24 w.show_all() 25 26 gtk.main()
Le programme crée une fenêtre et ensuite l'utilise comme
destination d'un glisser sans cible, ni action en fixant les drapeaux à zéro.
Les gestionnaires motion_cb
() et drop_cb
()
sont connectés respectivement aux signaux "drag-motion" et "drag-drop".
Le gestionnaire motion_cb
() se contente de configurer l'état
du glisser pour permettre un déposer. Le gestionnaire drop_cb
()
modifie le texte de l'étiquette pour indiquer les cibles du glisser et termine
le déposer en laissant intacte la source des données.
Pendant une opération de glisser-déposer, les signaux suivants sont transmis au widget destination.
Tableau 22.2. Signaux du widget destination
drag_motion (mouvement du glisser) | def drag_motion_cb(widget, drag_context, x, y, time, data): |
drag_drop (glisser-déposer) | def drag_drop_cb(widget, drag_context, x, y, time, data): |
drag_data_received (données reçues) | def drag_data_received_cb(widget, drag_context, x, y, selection_data, info, time, data): |
Le programme
dragndrop.py
illustre l'utilisation du glisser-déposer dans une application. Un bouton
avec une image
(gtkxpm.py
)
constitue la source du glisser, il fournit en même temps un texte et une
donnée xpm. Un widget layout constituera la destination du déposer du xpm,
un bouton, la destination du texte. La Figure 22.1, « Exemple de glisser-déposer »
montre le programme après le déposer du xpm et du texte, respectivement
sur le layout et sur le bouton.
Voici le code de dragndrop.py :
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 # exemple dragndrop.py 4 5 import pygtk 6 pygtk.require('2.0') 7 import gtk 8 import string, time 9 10 import gtkxpm 11 12 class ExempleDragNDrop: 13 HEIGHT = 600 14 WIDTH = 600 15 TARGET_TYPE_TEXT = 80 16 TARGET_TYPE_PIXMAP = 81 17 fromImage = [ ( "text/plain", 0, TARGET_TYPE_TEXT ), 18 ( "image/x-xpixmap", 0, TARGET_TYPE_PIXMAP ) ] 19 toButton = [ ( "text/plain", 0, TARGET_TYPE_TEXT ) ] 20 toCanvas = [ ( "image/x-xpixmap", 0, TARGET_TYPE_PIXMAP ) ] 21 22 def layout_resize(self, widget, event): 23 x, y, width, height = widget.get_allocation() 24 if width > self.lwidth or height > self.lheight: 25 self.lwidth = max(width, self.lwidth) 26 self.lheight = max(height, self.lheight) 27 widget.set_size(self.lwidth, self.lheight) 28 29 def makeLayout(self): 30 self.lwidth = self.WIDTH 31 self.lheight = self.HEIGHT 32 box = gtk.VBox(False,0) 33 box.show() 34 table = gtk.Table(2, 2, False) 35 table.show() 36 box.pack_start(table, True, True, 0) 37 layout = gtk.Layout() 38 self.layout = layout 39 layout.set_size(self.lwidth, self.lheight) 40 layout.connect("size-allocate", self.layout_resize) 41 layout.show() 42 table.attach(layout, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND, 43 gtk.FILL|gtk.EXPAND, 0, 0) 44 # créer les barres de défilement et les placer dans une table 45 vScrollbar = gtk.VScrollbar(None) 46 vScrollbar.show() 47 table.attach(vScrollbar, 1, 2, 0, 1, gtk.FILL|gtk.SHRINK, 48 gtk.FILL|gtk.SHRINK, 0, 0) 49 hScrollbar = gtk.HScrollbar(None) 50 hScrollbar.show() 51 table.attach(hScrollbar, 0, 1, 1, 2, gtk.FILL|gtk.SHRINK, 52 gtk.FILL|gtk.SHRINK, 53 0, 0) 54 # utiliser les ajustements du layout par les barres de défilement 55 vAdjust = layout.get_vadjustment() 56 vScrollbar.set_adjustment(vAdjust) 57 hAdjust = layout.get_hadjustment() 58 hScrollbar.set_adjustment(hAdjust) 59 layout.connect("drag_data_received", self.receiveCallback) 60 layout.drag_dest_set(gtk.DEST_DEFAULT_MOTION | 61 gtk.DEST_DEFAULT_HIGHLIGHT | 62 gtk.DEST_DEFAULT_DROP, 63 self.toCanvas, gtk.gdk.ACTION_COPY) 64 self.addImage(gtkxpm.gtk_xpm, 0, 0) 65 button = gtk.Button("Text Target") 66 button.show() 67 button.connect("drag_data_received", self.receiveCallback) 68 button.drag_dest_set(gtk.DEST_DEFAULT_MOTION | 69 gtk.DEST_DEFAULT_HIGHLIGHT | 70 gtk.DEST_DEFAULT_DROP, 71 self.toButton, gtk.gdk.ACTION_COPY) 72 box.pack_start(button, False, False, 0) 73 return box 74 75 def addImage(self, xpm, xd, yd): 76 hadj = self.layout.get_hadjustment() 77 vadj = self.layout.get_vadjustment() 78 style = self.window.get_style() 79 pixmap, mask = gtk.gdk.pixmap_create_from_xpm_d( 80 self.window.window, style.bg[gtk.STATE_NORMAL], xpm) 81 image = gtk.Image() 82 image.set_from_pixmap(pixmap, mask) 83 button = gtk.Button() 84 button.add(image) 85 button.connect("drag_data_get", self.sendCallback) 86 button.drag_source_set(gtk.gdk.BUTTON1_MASK, self.fromImage, 87 gtk.gdk.ACTION_COPY) 88 button.show_all() 89 # s'adapter au défilement du layout - la localisation de l'évènement 90 # est relative à la zone visible et non à la taille du layout 91 self.layout.put(button, int(xd+hadj.value), int(yd+vadj.value)) 92 return 93 94 def sendCallback(self, widget, context, selection, targetType, eventTime): 95 if targetType == self.TARGET_TYPE_TEXT: 96 now = time.time() 97 str = time.ctime(now) 98 selection.set(selection.target, 8, str) 99 elif targetType == self.TARGET_TYPE_PIXMAP: 100 selection.set(selection.target, 8, 101 string.join(gtkxpm.gtk_xpm, '\n')) 102 103 def receiveCallback(self, widget, context, x, y, selection, targetType, 104 time): 105 if targetType == self.TARGET_TYPE_TEXT: 106 label = widget.get_children()[0] 107 label.set_text(selection.data) 108 elif targetType == self.TARGET_TYPE_PIXMAP: 109 self.addImage(string.split(selection.data, '\n'), x, y) 110 111 def __init__(self): 112 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) 113 self.window.set_default_size(300, 300) 114 self.window.connect("destroy", lambda w: gtk.main_quit()) 115 self.window.show() 116 layout = self.makeLayout() 117 self.window.add(layout) 118 119 def main(): 120 gtk.main() 121 122 if __name__ == "__main__": 123 ExempleDragNDrop() 124 main()