‡ المحتويات‡
سوف نتحدث فى هذه الجزئية من الدرس عن عمليات السحب و الإفلات.
فى التطبيقات الرسومية فعل السحب و الإفلات عبارة عن النقر على عنصر مرئى و سحبه لمكان آخر أو داخل عنصر مرئى آخر و عموماً يمكن استخدامه لفعل الكثير من الأشياء أو لإنشاء العديد من طرق الربط بين عناصر معينة (إقتباس من الموسوعة الحرة WikiPedia أنظر المقال الأصلى ).
عملية السحب و الإفلات من أكثر الجوانب المهمة فى واجهة المستخدم الرسومية و هى تتيح لك تركيب الأشياء حدسياً.
فى المثال سوف نقوم بعمليات الإدراج و السحب على زر و لكن ليس باستخدام طرق السحب و الإدراج.
dragbutton.py #!/usr/bin/ipy import clr clr.AddReference("System.Windows.Forms") clr.AddReference("System.Drawing") from System.Windows.Forms import Application, Form, Button from System.Drawing import Size, Point class IForm(Form): def __init__(self): self.Text = 'Drag & Drop' button = Button() button.Parent = self button.Text = 'Button' button.MouseDown += self.OnMousDown button.MouseUp += self.OnMousUp button.MouseMove += self.OnMousMove button.Location = Point(20, 20) self.isDragging = False self.CenterToScreen() def OnMousDown(self, sender, event): self.isDragging = True self.oldX = event.X self.oldY = event.Y 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 = False Application.Run(IForm())
The code example puts a regular button control on the form container. By clicking on the button surface and simultaneously dragging it with a mouse we can relocate the button.
There are some supporting variables in our example. The isDragging variable tells us, whether we are in the process of dragging an object. The oldX and oldY variables store the x, y coordinates just before the dragging process begins.
button.MouseDown += self.OnMousDown button.MouseUp += self.OnMousUp button.MouseMove += self.OnMousMove
ربطنا ثلاثة عمليات للفأرة بالزر و قمنا بعمل ثلاثة مراحل لعملية السحب و الإفلات و تبدأ العملية عن النقر على الزر و تستقبلها الدالة OnMouseDown() و المرحلة الثانية هى تحريك الزر و هو عند ازاحته إلى موقع جديد و تسقبلها الدالة OnMouseMove() و المرحلة الأخيرة عند إيقاف العملية و تحدث عندما نحرر الإصبع من على الفأرة و تستقبلها الدالة OnMouseUp().
def OnMousDown(self, sender, event): self.isDragging = True self.oldX = event.X self.oldY = event.Y
تنفذ الدالة OnMouseDown() المرحلة الأولى من عملية السحب و الإفلات و هى تضع القيمة لثلاثة متغيرات ضرورية.
def OnMousMove(self, sender, event): if self.isDragging: sender.Top = sender.Top + (event.Y - self.oldY) sender.Left = sender.Left + (event.X - self.oldX)
فى الدالة OnMouseMove() نعيد تحديد مكان الزر فنحسب الفرق بين الإحداثبات س و ص القديمة و الجديدة لمؤشر الفأرة و الفرق سوف يضاف إلى كل من الخاصيتين Top و Left للزر و بنائاً على ذلك يتم تحريك الزر إلى الموقع الجديد.
Figure: Dragging a button
فى السابق تم تطبيق عمليات السحب و الإفلات على أداة أما فى هذا المثال فسو تكون على بيانات نصية و هنا سوف نستخدم الطرق المتاحة فى مكتبات WinForms للسحب و الإفلات.
عمليات السحب و الإفلات فى مكتبات WinForms تعتمد على طرق إتصال ثابته فهناك عنصرين أساسيين هما مصدر السحب drag source و الهدف المراد الإفلات عنده أو فيه drop target.
dragtext.py #!/usr/bin/ipy import clr clr.AddReference("System.Windows.Forms") clr.AddReference("System.Drawing") from System.Windows.Forms import Application, Form, Button from System.Windows.Forms import TextBox, DragDropEffects, DataFormats from System.Drawing import Size, Point class IForm(Form): def __init__(self): self.Text = 'Drag & Drop' self.AllowDrop = True button = Button() button.Parent = self textBox = TextBox() textBox.Parent = self button.AllowDrop = True button.Location = Point(150, 50) button.DragDrop += self.OnDragDrop button.DragEnter += self.OnDragEnter textBox.Location = Point(15, 50) textBox.MouseDown += self.OnMousDown self.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.Copy def OnDragDrop(self, sender, event): sender.Text = event.Data.GetData(DataFormats.Text) Application.Run(IForm())
هناك أداتين فى النافذة زر و صندوق نص و سوف نسحب النص من صندوق النصوص و نفلته فى الزر.
self.AllowDrop = Trueو هنا قمنا بتفعيل الخاصية AllowDrop لأن السحب غير مفعل إفتراضياً.
button.DragDrop += self.OnDragDrop button.DragEnter += self.OnDragEnter ... extBox.MouseDown += self.OnMousDown
مرة ثانية عملية السحب و الإفلات قسمت إلى ثلاثة مراحل و لدينا دالة معينة لكل مرحلة.
def OnMousDown(self, sender, event): sender.SelectAll() sender.DoDragDrop(sender.Text, DragDropEffects.Copy)
فى الدالة OnMouseDown() بدأنا عملية السحب و الإفلات عن طريق الدالة DoDrageDrop() و الــDragDropEffects.Copyparameter يحدد نوع العملية و التى من خلالها يمكننا نسخ النص أو تحريكه خلال عملية السحب و الإفلات.
def OnDragEnter(self, sender, event): if event.Data.GetDataPresent(DataFormats.Text): event.Effect = DragDropEffects.Copy
يبدأ الحدث DragEnter عندما مؤشر الفأرة فى دخول منطقة الهدف الذى سيتم الإفلات فيه أو عليه و لا بد من تحديد قيمة للخاصية Effect و هنا لا بد من تساوى تأثير السحب و الإفلات DragDropEffect و إلا لن تحدث العملية.
def OnDragDrop(self, sender, event): sender.Text = event.Data.GetData(DataFormats.Text)
و أخيراً لدينا الدالة OnDragDrop() و فيها نأخذ البيانات من عنصر الحدث و نضعها خاصية Text للزر.
Figure: Drag & drop of text
فى هذا المثال سوف نجرى عملية السحب و الإفلات على صورة داخل نافذة التطبيق.
dragimage.py #!/usr/bin/ipy import sys import clr clr.AddReference("System.Windows.Forms") clr.AddReference("System.Drawing") from System.Windows.Forms import Application, Form, PictureBox, PictureBoxSizeMode from System.Windows.Forms import Cursors from System.Drawing import Size, Point, Rectangle, Brushes, Bitmap class IForm(Form): def __init__(self): self.ClientSize = Size(350, 250) self.Text = "Dragging Images" self.Paint += self.OnPaint self.isDragging = False self.dropRect = Rectangle(10, 10, 200, 160) self.brush = Brushes.Gray picBox = PictureBox() self.loadImage() self.isDragging = False self.CenterToScreen() picBox.Parent = self picBox.Location = Point(100, 50) picBox.Size = Size(self.image.Width, self.image.Height) picBox.Image = self.image picBox.MouseDown += self.OnMousDown picBox.MouseUp += self.OnMousUp picBox.MouseMove += self.OnMousMove picBox.Cursor = Cursors.Hand def loadImage(self): try: self.image = Bitmap("image.jpg") except Exception, e: print "Error reading image" print e.msg sys.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 = False if self.dropRect.Contains(sender.Bounds): self.brush = Brushes.Gold else: self.brush = Brushes.Gray self.Refresh() def OnMousDown(self, sender, event): self.isDragging = True self.oldX = event.X self.oldY = event.Y def OnPaint(self, event): g = event.Graphics g.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.msg sys.exit(1)
الدلة loadImage() تحمل صورة نقطية bitmap داخل صندوق الصورة.
if self.dropRect.Contains(sender.Bounds): self.brush = Brushes.Gold else: self.brush = Brushes.Gray
فى الدالة OnMouseUp() نحدد إذا كانت حدود صندوق الصورة داخل المستطيل فيكون لون الفرشاة ذهبى و إذا كان عكس ذلك يكون رمادى.
self.Refresh()لا بد من استدعاء الدالة Refresh() حتى تنشط لون الفرشاة الجديد.
Figure: Drag & drop image
فى هذا الجزء من الدرس تم التعرض إلى عمليات السحب و الإفلات فى مكتبات Mono WinForms.
‡ المحتويات‡