原文: http://zetcode.com/tutorials/ironpythontutorial/dragdrop/
IronPython Mono Winforms 教程的这一部分将专门用于拖放操作。
在计算机图形用户界面中,拖放是单击虚拟对象并将其拖动到其他位置或另一个虚拟对象上的动作(或支持以下动作)。 通常,它可用于调用多种动作,或在两个抽象对象之间创建各种类型的关联。 (维基百科)
拖放功能是图形用户界面最明显的方面之一。 拖放操作使您可以直观地完成复杂的事情。
拖动按钮
在第一个示例中,我们将在按钮控件上执行拖放操作。 该示例在拖放&放置协议之外执行作业。
dragbutton.py
#!/usr/bin/ipyimport clrclr.AddReference("System.Windows.Forms")clr.AddReference("System.Drawing")from System.Windows.Forms import Application, Form, Buttonfrom System.Drawing import Size, Pointclass IForm(Form):def __init__(self):self.Text = 'Drag & Drop'button = Button()button.Parent = selfbutton.Text = 'Button'button.MouseDown += self.OnMousDownbutton.MouseUp += self.OnMousUpbutton.MouseMove += self.OnMousMovebutton.Location = Point(20, 20)self.isDragging = Falseself.CenterToScreen()def OnMousDown(self, sender, event):self.isDragging = Trueself.oldX = event.Xself.oldY = event.Ydef OnMousMove(self, sender, event):if self.isDragging:sender.Top = sender.Top + (event.Y - self.oldY)sender.Left = sender.Left + (event.X - self.oldX)def OnMousUp(self, sender, event):self.isDragging = FalseApplication.Run(IForm())
该代码示例将一个常规按钮控件放在表单容器上。 通过单击按钮表面并同时用鼠标拖动它,我们可以重新放置按钮。
我们的示例中有一些支持变量。 isDragging变量告诉我们是否正在拖动对象。 oldX和oldY变量在拖动过程开始之前存储 x,y 坐标。
button.MouseDown += self.OnMousDownbutton.MouseUp += self.OnMousUpbutton.MouseMove += self.OnMousMove
我们为按钮插入了三种不同的鼠标处理器。 它们实现了拖放过程的三个不同阶段。 当我们单击按钮时,过程开始。 这由OnMousDown()方法处理。 第二部分是机芯。 这是当我们将对象移动到新位置时。 它以OnMousMove()方法处理。 最后一部分是过程停止的时间。 当我们释放鼠标按钮时会发生这种情况。 适当的任务委托给OnMousUp()方法。
def OnMousDown(self, sender, event):self.isDragging = Trueself.oldX = event.Xself.oldY = event.Y
OnMousDown()方法实现了过程的第一部分。 它设置了三个必要的变量。
def OnMousMove(self, sender, event):if self.isDragging:sender.Top = sender.Top + (event.Y - self.oldY)sender.Left = sender.Left + (event.X - self.oldX)
在OnMousMove()方法中,我们重新定位按钮。 我们计算存储的 x,y 坐标与鼠标指针的新坐标之间的差。 差异将添加到按钮的Top和Left属性中,从而将其移动到新位置。

图:拖动按钮
拖动文字
在前面的示例中,我们确实拖动了控件上的&拖放。 接下来,我们将对文本数据进行拖放操作。 在这里,我们将使用 Winforms 库提供的拖放协议。
拖放操作是 Winforms 中的标准通信协议。 我们有两个基本对象。 拖动源和放置目标。
dragtext.py
#!/usr/bin/ipyimport clrclr.AddReference("System.Windows.Forms")clr.AddReference("System.Drawing")from System.Windows.Forms import Application, Form, Buttonfrom System.Windows.Forms import TextBox, DragDropEffects, DataFormatsfrom System.Drawing import Size, Pointclass IForm(Form):def __init__(self):self.Text = 'Drag & Drop'self.AllowDrop = Truebutton = Button()button.Parent = selftextBox = TextBox()textBox.Parent = selfbutton.AllowDrop = Truebutton.Location = Point(150, 50)button.DragDrop += self.OnDragDropbutton.DragEnter += self.OnDragEntertextBox.Location = Point(15, 50)textBox.MouseDown += self.OnMousDownself.ClientSize = Size(250, 200)self.CenterToScreen()def OnMousDown(self, sender, event):sender.SelectAll()sender.DoDragDrop(sender.Text, DragDropEffects.Copy)def OnDragEnter(self, sender, event):if event.Data.GetDataPresent(DataFormats.Text):event.Effect = DragDropEffects.Copydef OnDragDrop(self, sender, event):sender.Text = event.Data.GetData(DataFormats.Text)Application.Run(IForm())
我们在表单上有两个控件。 一个按钮和一个文本框。 我们将文本从文本框中拖放到按钮上。
self.AllowDrop = True
我们将AllowDrop属性设置为true。 默认情况下不启用删除。
button.DragDrop += self.OnDragDropbutton.DragEnter += self.OnDragEnter...extBox.MouseDown += self.OnMousDown
同样,拖放过程分为三个步骤。 对于每个特定步骤,我们有三种方法。
def OnMousDown(self, sender, event):sender.SelectAll()sender.DoDragDrop(sender.Text, DragDropEffects.Copy)
在OnMousDown()方法中,我们初始化了拖放过程。 我们使用DoDragDrop()方法启动该过程。 DragDropEffects.Copy参数指定操作的类型。 实质上,我们可以在拖放操作期间复制文本或移动文本。
def OnDragEnter(self, sender, event):if event.Data.GetDataPresent(DataFormats.Text):event.Effect = DragDropEffects.Copy
当鼠标指针进入放置目标控件的区域时,将启动DragEnter事件。 必须设置Effect属性。 拖动源和放置目标的DragDropEffects必须相等。 否则,该操作将无法进行。
def OnDragDrop(self, sender, event):sender.Text = event.Data.GetData(DataFormats.Text)
最后,我们有OnDragDrop()方法。 在这里,我们从事件对象获取数据并将其设置为按钮Text属性。

图:文本拖放
拖动图像
在最后一个示例中,我们将&拖放图像拖到窗体上。
dragimage.py
#!/usr/bin/ipyimport sysimport clrclr.AddReference("System.Windows.Forms")clr.AddReference("System.Drawing")from System.Windows.Forms import Application, Form, PictureBox, PictureBoxSizeModefrom System.Windows.Forms import Cursorsfrom System.Drawing import Size, Point, Rectangle, Brushes, Bitmapclass IForm(Form):def __init__(self):self.ClientSize = Size(350, 250)self.Text = "Dragging Images"self.Paint += self.OnPaintself.isDragging = Falseself.dropRect = Rectangle(10, 10, 200, 160)self.brush = Brushes.GraypicBox = PictureBox()self.loadImage()self.isDragging = Falseself.CenterToScreen()picBox.Parent = selfpicBox.Location = Point(100, 50)picBox.Size = Size(self.image.Width, self.image.Height)picBox.Image = self.imagepicBox.MouseDown += self.OnMousDownpicBox.MouseUp += self.OnMousUppicBox.MouseMove += self.OnMousMovepicBox.Cursor = Cursors.Handdef loadImage(self):try:self.image = Bitmap("image.jpg")except Exception, e:print "Error reading image"print e.msgsys.exit(1)def OnMousMove(self, sender, event):if self.isDragging:sender.Top = sender.Top + (event.Y - self.oldY)sender.Left = sender.Left + (event.X - self.oldX)def OnMousUp(self, sender, event):self.isDragging = Falseif self.dropRect.Contains(sender.Bounds):self.brush = Brushes.Goldelse:self.brush = Brushes.Grayself.Refresh()def OnMousDown(self, sender, event):self.isDragging = Trueself.oldX = event.Xself.oldY = event.Ydef OnPaint(self, event):g = event.Graphicsg.FillRectangle(self.brush, self.dropRect)Application.Run(IForm())
在我们的示例中,我们有一个PictureBox,并绘制了一个灰色矩形。 如果将图片放在矩形内,则矩形的颜色变为金色。
self.brush = Brushes.Gray
self.brush变量保存矩形的笔刷。 默认情况下为灰色。
def loadImage(self):try:self.image = Bitmap("image.jpg")except Exception, e:print "Error reading image"print e.msgsys.exit(1)
loadImage()方法为PictureBox控件加载位图。
if self.dropRect.Contains(sender.Bounds):self.brush = Brushes.Goldelse:self.brush = Brushes.Gray
在OnMousUp()方法中,我们确定矩形的笔刷。 如果图片框的边界在矩形内,则画笔为金色;否则,画笔为金色。 否则为灰色。
self.Refresh()
我们必须调用Refresh()方法来激活新的画笔颜色。

图:拖放图像
本章专门使用 Mono Winforms 库拖放操作。
