Пробовал рисовать картинки на PyGtk и столкнулся с тем, что в примерах по drap_and_drop картинки размножаются :). Смотрел здесь:http://www.pygtk.org/pygtk2tutorial/sec-DNDMethods.html.
И в примерах, поставляемых с PyGtk - только схематичная реализация drag_and_drop.(./usr/lib/pygtk/2.0/demos/dnd.py)Поискал на форуме, в интернете и ответа не нашел. Пришлось разбираться самому.Вот что получилось. На первый взгляд программа кажется сложной, но если приглядеться, то многое становится интуитивно понятно. В инете встречал вопросы по drag_and_drop, так что думаю кому-нибудь это пригодится.Картинка упакована в gtk.Button. В дальнейшем попробую реализовать для gtk.DrawingArea.
dndimage.py
#!/usr/bin/python
# coding: utf-8
import pygtk
import gtk
import string, time
import gtkxpm
class DNDImageButton:
TARGET_TYPE_TEXT = 80
TARGET_TYPE_PIXMAP = 81
fromImage = [ ( "text/plain", 0, TARGET_TYPE_TEXT ),
( "", 0, TARGET_TYPE_PIXMAP ) ]
toButton = [ ( "text/plain", 0, TARGET_TYPE_TEXT ) ]
toCanvas = [ ( "", 0, TARGET_TYPE_PIXMAP ) ]
################### установки layout-a ###########################
def layout_resize(self, widget, event):
x, y, width, height = widget.get_allocation()
if width > self.lwidth or height > self.lheight:
self.lwidth = max(width, self.lwidth)
self.lheight = max(height, self.lheight)
widget.set_size(self.lwidth, self.lheight)
def makeLayout(self):
self.lwidth = 0
self.lheight = 0
box = gtk.VBox(False,0)
box.show()
table = gtk.Table(2, 2, False)
table.show()
box.pack_start(table, True, True, 0)
layout = gtk.Layout()
self.layout = layout
layout.set_size(self.lwidth, self.lheight)
layout.connect("size-allocate", self.layout_resize)
layout.show()
table.attach(layout, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND,
gtk.FILL|gtk.EXPAND, 0, 0)
################### испускаем сигналы при перетаскивании ##########################
layout.connect('drag_leave', self.target_drag_leave)
layout.connect('drag_motion', self.target_drag_motion)
layout.connect('drag_drop', self.target_drag_drop)
layout.connect("drag_data_received", self.receiveCallback)
################### установки цели ##########################
layout.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT |
gtk.DEST_DEFAULT_DROP,
self.toCanvas, gtk.gdk.ACTION_MOVE )
self.addImage(gtkxpm.gtk_xpm, 0, 0)
return box
####################### устанавл. виджет в коорд. xd, yd ##########################
def addImage(self, xpm, xd, yd):
hadj = self.layout.get_hadjustment()
vadj = self.layout.get_vadjustment()
style = self.window.get_style()
pixmap, mask = gtk.gdk.pixmap_create_from_xpm(
self.window.window, style.bg[gtk.STATE_NORMAL], "/home/mike/Desktop/lena.jpg") #<-----------
image = gtk.Image()
image.set_from_pixmap(pixmap, mask)
button = gtk.Button()
button.add(image)
####################### соединяем виджет ##########################
button.connect("drag_data_get", self.sendCallback)
button.connect('drag_data_delete', self.delete_cb)
###################### установки источника ##########################
button.drag_source_set(gtk.gdk.BUTTON1_MASK, self.fromImage,
gtk.gdk.ACTION_MOVE )
button.show_all()
self.layout.put(button, int(xd+hadj.value), int(yd+vadj.value))
return
####################### функции CALLBACK ##########################
def sendCallback(self, widget, context, selection, targetType, eventTime):
print "send_cb "
if targetType == self.TARGET_TYPE_PIXMAP:
selection.set(selection.target, 8,
string.join(gtkxpm.gtk_xpm, '\n'))
def receiveCallback(self, widget, context, x, y, selection, targetType,
time):
print "receive_cb "
if targetType == self.TARGET_TYPE_PIXMAP:
self.addImage(gtkxpm.gtk_xpm, x, y)
###################### функция удаления прежнего виджета ##########################
def delete_cb(self, widget, context):
print "delete_cb "
widget.destroy()
def target_drag_leave(self, widget, context, time):
print 'leave'
def target_drag_motion(self, widget, context, x, y, time):
print 'motion'
def target_drag_drop(self, widget, context, x, y, time):
print 'drop'
########################################################################################
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_default_size(400, 400)
self.window.connect("destroy", lambda w: gtk.main_quit())
self.window.show()
layout = self.makeLayout()
self.window.add(layout)
########################################################################################
DNDImageButton()
gtk.main()
Попутный вопрос: кто-нибудь реализовывал метод rotate() для PyGtk ?
Если есть решение, отпишите пожалуйста, буду признателен.
The Gray Cardinal
По-моему качество изображения ничуть не хуже, чем в PyQt. Правда не знаю, как поведут себя картинки
при повороте. Если удастся решить вашу задачу на PyGtk, обязательно отпишу. :)
P.S. Для правильной работы примера см. посты ниже