原文: http://zetcode.com/tutorials/ironpythontutorial/dragdrop/

IronPython Mono Winforms 教程的这一部分将专门用于拖放操作。

在计算机图形用户界面中,拖放是单击虚拟对象并将其拖动到其他位置或另一个虚拟对象上的动作(或支持以下动作)。 通常,它可用于调用多种动作,或在两个抽象对象之间创建各种类型的关联。 (维基百科)

拖放功能是图形用户界面最明显的方面之一。 拖放操作使您可以直观地完成复杂的事情。

拖动按钮

在第一个示例中,我们将在按钮控件上执行拖放操作。 该示例在拖放&放置协议之外执行作业。

dragbutton.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, Button
  6. from System.Drawing import Size, Point
  7. class IForm(Form):
  8. def __init__(self):
  9. self.Text = 'Drag & Drop'
  10. button = Button()
  11. button.Parent = self
  12. button.Text = 'Button'
  13. button.MouseDown += self.OnMousDown
  14. button.MouseUp += self.OnMousUp
  15. button.MouseMove += self.OnMousMove
  16. button.Location = Point(20, 20)
  17. self.isDragging = False
  18. self.CenterToScreen()
  19. def OnMousDown(self, sender, event):
  20. self.isDragging = True
  21. self.oldX = event.X
  22. self.oldY = event.Y
  23. def OnMousMove(self, sender, event):
  24. if self.isDragging:
  25. sender.Top = sender.Top + (event.Y - self.oldY)
  26. sender.Left = sender.Left + (event.X - self.oldX)
  27. def OnMousUp(self, sender, event):
  28. self.isDragging = False
  29. Application.Run(IForm())

该代码示例将一个常规按钮控件放在表单容器上。 通过单击按钮表面并同时用鼠标拖动它,我们可以重新放置按钮。

我们的示例中有一些支持变量。 isDragging变量告诉我们是否正在拖动对象。 oldXoldY变量在拖动过程开始之前存储 x,y 坐标。

  1. button.MouseDown += self.OnMousDown
  2. button.MouseUp += self.OnMousUp
  3. button.MouseMove += self.OnMousMove

我们为按钮插入了三种不同的鼠标处理器。 它们实现了拖放过程的三个不同阶段。 当我们单击按钮时,过程开始。 这由OnMousDown()方法处理。 第二部分是机芯。 这是当我们将对象移动到新位置时。 它以OnMousMove()方法处理。 最后一部分是过程停止的时间。 当我们释放鼠标按钮时会发生这种情况。 适当的任务委托给OnMousUp()方法。

  1. def OnMousDown(self, sender, event):
  2. self.isDragging = True
  3. self.oldX = event.X
  4. self.oldY = event.Y

OnMousDown()方法实现了过程的第一部分。 它设置了三个必要的变量。

  1. def OnMousMove(self, sender, event):
  2. if self.isDragging:
  3. sender.Top = sender.Top + (event.Y - self.oldY)
  4. sender.Left = sender.Left + (event.X - self.oldX)

OnMousMove()方法中,我们重新定位按钮。 我们计算存储的 x,y 坐标与鼠标指针的新坐标之间的差。 差异将添加到按钮的TopLeft属性中,从而将其移动到新位置。

Mono Winforms 中的拖放 - 图1

图:拖动按钮

拖动文字

在前面的示例中,我们确实拖动了控件上的&拖放。 接下来,我们将对文本数据进行拖放操作。 在这里,我们将使用 Winforms 库提供的拖放协议。

拖放操作是 Winforms 中的标准通信协议。 我们有两个基本对象。 拖动源和放置目标。

dragtext.py

  1. #!/usr/bin/ipy
  2. import clr
  3. clr.AddReference("System.Windows.Forms")
  4. clr.AddReference("System.Drawing")
  5. from System.Windows.Forms import Application, Form, Button
  6. from System.Windows.Forms import TextBox, DragDropEffects, DataFormats
  7. from System.Drawing import Size, Point
  8. class IForm(Form):
  9. def __init__(self):
  10. self.Text = 'Drag & Drop'
  11. self.AllowDrop = True
  12. button = Button()
  13. button.Parent = self
  14. textBox = TextBox()
  15. textBox.Parent = self
  16. button.AllowDrop = True
  17. button.Location = Point(150, 50)
  18. button.DragDrop += self.OnDragDrop
  19. button.DragEnter += self.OnDragEnter
  20. textBox.Location = Point(15, 50)
  21. textBox.MouseDown += self.OnMousDown
  22. self.ClientSize = Size(250, 200)
  23. self.CenterToScreen()
  24. def OnMousDown(self, sender, event):
  25. sender.SelectAll()
  26. sender.DoDragDrop(sender.Text, DragDropEffects.Copy)
  27. def OnDragEnter(self, sender, event):
  28. if event.Data.GetDataPresent(DataFormats.Text):
  29. event.Effect = DragDropEffects.Copy
  30. def OnDragDrop(self, sender, event):
  31. sender.Text = event.Data.GetData(DataFormats.Text)
  32. Application.Run(IForm())

我们在表单上有两个控件。 一个按钮和一个文本框。 我们将文本从文本框中拖放到按钮上。

  1. self.AllowDrop = True

我们将AllowDrop属性设置为true。 默认情况下不启用删除。

  1. button.DragDrop += self.OnDragDrop
  2. button.DragEnter += self.OnDragEnter
  3. ...
  4. extBox.MouseDown += self.OnMousDown

同样,拖放过程分为三个步骤。 对于每个特定步骤,我们有三种方法。

  1. def OnMousDown(self, sender, event):
  2. sender.SelectAll()
  3. sender.DoDragDrop(sender.Text, DragDropEffects.Copy)

OnMousDown()方法中,我们初始化了拖放过程。 我们使用DoDragDrop()方法启动该过程。 DragDropEffects.Copy参数指定操作的类型。 实质上,我们可以在拖放操作期间复制文本或移动文本。

  1. def OnDragEnter(self, sender, event):
  2. if event.Data.GetDataPresent(DataFormats.Text):
  3. event.Effect = DragDropEffects.Copy

当鼠标指针进入放置目标控件的区域时,将启动DragEnter事件。 必须设置Effect属性。 拖动源和放置目标的DragDropEffects必须相等。 否则,该操作将无法进行。

  1. def OnDragDrop(self, sender, event):
  2. sender.Text = event.Data.GetData(DataFormats.Text)

最后,我们有OnDragDrop()方法。 在这里,我们从事件对象获取数据并将其设置为按钮Text属性。

Mono Winforms 中的拖放 - 图2

图:文本拖放

拖动图像

在最后一个示例中,我们将&拖放图像拖到窗体上。

dragimage.py

  1. #!/usr/bin/ipy
  2. import sys
  3. import clr
  4. clr.AddReference("System.Windows.Forms")
  5. clr.AddReference("System.Drawing")
  6. from System.Windows.Forms import Application, Form, PictureBox, PictureBoxSizeMode
  7. from System.Windows.Forms import Cursors
  8. from System.Drawing import Size, Point, Rectangle, Brushes, Bitmap
  9. class IForm(Form):
  10. def __init__(self):
  11. self.ClientSize = Size(350, 250)
  12. self.Text = "Dragging Images"
  13. self.Paint += self.OnPaint
  14. self.isDragging = False
  15. self.dropRect = Rectangle(10, 10, 200, 160)
  16. self.brush = Brushes.Gray
  17. picBox = PictureBox()
  18. self.loadImage()
  19. self.isDragging = False
  20. self.CenterToScreen()
  21. picBox.Parent = self
  22. picBox.Location = Point(100, 50)
  23. picBox.Size = Size(self.image.Width, self.image.Height)
  24. picBox.Image = self.image
  25. picBox.MouseDown += self.OnMousDown
  26. picBox.MouseUp += self.OnMousUp
  27. picBox.MouseMove += self.OnMousMove
  28. picBox.Cursor = Cursors.Hand
  29. def loadImage(self):
  30. try:
  31. self.image = Bitmap("image.jpg")
  32. except Exception, e:
  33. print "Error reading image"
  34. print e.msg
  35. sys.exit(1)
  36. def OnMousMove(self, sender, event):
  37. if self.isDragging:
  38. sender.Top = sender.Top + (event.Y - self.oldY)
  39. sender.Left = sender.Left + (event.X - self.oldX)
  40. def OnMousUp(self, sender, event):
  41. self.isDragging = False
  42. if self.dropRect.Contains(sender.Bounds):
  43. self.brush = Brushes.Gold
  44. else:
  45. self.brush = Brushes.Gray
  46. self.Refresh()
  47. def OnMousDown(self, sender, event):
  48. self.isDragging = True
  49. self.oldX = event.X
  50. self.oldY = event.Y
  51. def OnPaint(self, event):
  52. g = event.Graphics
  53. g.FillRectangle(self.brush, self.dropRect)
  54. Application.Run(IForm())

在我们的示例中,我们有一个PictureBox,并绘制了一个灰色矩形。 如果将图片放在矩形内,则矩形的颜色变为金色。

  1. self.brush = Brushes.Gray

self.brush变量保存矩形的笔刷。 默认情况下为灰色。

  1. def loadImage(self):
  2. try:
  3. self.image = Bitmap("image.jpg")
  4. except Exception, e:
  5. print "Error reading image"
  6. print e.msg
  7. sys.exit(1)

loadImage()方法为PictureBox控件加载位图。

  1. if self.dropRect.Contains(sender.Bounds):
  2. self.brush = Brushes.Gold
  3. else:
  4. self.brush = Brushes.Gray

OnMousUp()方法中,我们确定矩形的笔刷。 如果图片框的边界在矩形内,则画笔为金色;否则,画笔为金色。 否则为灰色。

  1. self.Refresh()

我们必须调用Refresh()方法来激活新的画笔颜色。

Mono Winforms 中的拖放 - 图3

图:拖放图像

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