المحتويات

أدوات متقدمة فى مكتبات WinForms

فى هذا الجزء من الدرس سوف يتم التعرض إلى شرح بعض الأداوت المتقدمة فى مكتبات WinForms مثل صندوق القائمة ListBox أو ListView قائمة و لكن بها خصائص زائدة أو الشجرة TreeView .

صندوق القائمة ListBox

الأاة ListBox تستخدم لعرض قائمة من العناصر و يمكن للمستخدم تحديد أو تظليل عنصر أو أكثر بالضغط على العنصر.

listbox.py

#!/usr/bin/ipy

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, StatusBar
from System.Windows.Forms import ListBox, DockStyle
from System.Drawing import Size


class IForm(Form):

    def __init__(self):
        self.Text = "ListBox"
        
        lb = ListBox()
        lb.Parent = self

        lb.Items.Add("Jessica")
        lb.Items.Add("Rachel")
        lb.Items.Add("Angelina")
        lb.Items.Add("Amy")
        lb.Items.Add("Jennifer")
        lb.Items.Add("Scarlett")

        lb.Dock = DockStyle.Fill
        lb.SelectedIndexChanged += self.OnChanged

        self.sb = StatusBar()
        self.sb.Parent = self

        self.Size = Size(220, 220)
        self.CenterToScreen()
    

    def OnChanged(self, sender, event):
        self.sb.Text = sender.SelectedItem


Application.Run(IForm())

Our example shows a listbox with six names. The selected item is shown in the statusbar.

 lb = ListBox()
 lb.Parent = self

تم إنشاء صندوق القائمة.

 lb.Items.Add("Jessica")

الكود السابق يبين كيفية إضافة عنصر إلى القائمة فالأداة تحتوى على الخاصية Items و هذه الخاصية عبارة عن مرجعية للعناصر فى القائمة و بإستخدامها يمكننا إضافة أو حذف أو حساب مجموع العناصر فى القائمة.

 lb.SelectedIndexChanged += self.OnChanged

عد تحديد أو تظليل عنصر من القائمة يتم تنشيط الحدث SelectedIndexChanged .

 def OnChanged(self, sender, event):
     self.sb.Text = sender.SelectedItem

بداخل الدالة OnChange() تأخذ القيمة المحدد من القائمة و نضعها فى شريط الحالة.


ListBox

Figure: ListBox

ListView

الأداة ListView تستخدم لعرض مجموعة من العناصر و بها مميزات زائدة عن أختها ListBox و يمكنها أن تعرض عناصرها بأشكال متنوعة و الأكثر إستخداماً من هذه الأشكال هو شكل الأعمدة المتعددة.

listview.py

#!/usr/bin/ipy

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, StatusBar
from System.Windows.Forms import ListView, View, ColumnHeader
from System.Windows.Forms import ListViewItem, DockStyle, SortOrder
from System.Drawing import Size


class IForm(Form):

    def __init__(self):
        self.Text = 'ListBox'
       

        actresses = { 'Jessica Alba' : '1981', 'Angelina Jolie' : '1975', 
            'Natalie Portman' : '1981', 'Rachel Weiss' : '1971', 
            'Scarlett Johansson' : 1984 }


        name = ColumnHeader()
        name.Text = 'Name'
        name.Width = -1
        year = ColumnHeader()
        year.Text = 'Year'

        self.SuspendLayout()

        lv = ListView()
        lv.Parent = self
        lv.FullRowSelect = True
        lv.GridLines = True
        lv.AllowColumnReorder = True
        lv.Sorting = SortOrder.Ascending
        lv.Columns.AddRange((name, year))
        lv.ColumnClick += self.OnColumnClick

        for act in actresses.keys():
            item = ListViewItem()
            item.Text = act
            item.SubItems.Add(str(actresses[act]))
            lv.Items.Add(item)
        

        lv.Dock = DockStyle.Fill
        lv.Click += self.OnChanged

        self.sb = StatusBar()
        self.sb.Parent = self
        lv.View = View.Details

        self.ResumeLayout()

        self.Size = Size(350, 300)
        self.CenterToScreen()
    

    def OnChanged(self, sender, event):

        name = sender.SelectedItems[0].SubItems[0].Text
        born = sender.SelectedItems[0].SubItems[1].Text
        self.sb.Text = name + ', ' + born
    

    def OnColumnClick(self, sender, event):

        if sender.Sorting == SortOrder.Ascending:
            sender.Sorting = SortOrder.Descending
        else: 
            sender.Sorting = SortOrder.Ascending


Application.Run(IForm())

فى المثال ليدنا قائمة عرض listview بعمودين و فى العمود الأول نعرض اسم الممثل أما فى العمود الثانى فنعرض تاريخ ميلادة و البيانات سوف تخرن فى مجموعة قائمة List و بتحديد صف معين سوف تظهر بياناته على شريط الحالة و أيضاً عند الضغط على رأس العمود سوف تخزن البيانات.

 actresses = { 'Jessica Alba' : '1981', 'Angelina Jolie' : '1975', 
     'Natalie Portman' : '1981', 'Rachel Weiss' : '1971', 
     'Scarlett Johansson' : 1984 }

نخزن البيانات فى قاموس dictionary.

 name = ColumnHeader()
 name.Text = 'Name'
 name.Width = -1

ننشأ ColumHeader لك عمود فى القائمة و نغير قيمة العرض Width إلى -1 و بذلك سوف يكون عرض العمود هو طول أكبر عنصر فيه.

 lv = ListView()
 lv.Parent = self

تم إنشاء الأدة ListView.

 lv.FullRowSelect = True
 lv.GridLines = True
 lv.AllowColumnReorder = True
 lv.Sorting = SortOrder.Ascending

هنا تم تفعيل أربعة خصائث لهذه الأداة و هى تفعيل تظليل الصف بكامله و ظهور خطوط فاصلة و تفعيل إعادة ترتيب العمود عن طريق سحب العمود و ترتيب البيانات ترتيباً معيناُ.

 lv.Columns.AddRange((name, year))

هنا أضفنا رأسى عمود ColumnHeaders لقائمة العرض ListView.

 for act in actresses.keys():
     item = ListViewItem()
     item.Text = act
     item.SubItems.Add(str(actresses[act]))
     lv.Items.Add(item)

فى هذا التكرار تتم إضافة الصف فى القائمة كفئة ListViewItem.

 lv.View = View.Details

هذه الأداة يمكنها عرض البيانات فى أشكال متعددة و مختلفة مثل Details .

 name = sender.SelectedItems[0].SubItems[0].Text
 born = sender.SelectedItems[0].SubItems[1].Text
 self.sb.Text = name + ', ' + born

فى داخل الدالة OnChange() نأخذ البيانات من الصف المظلل و نعرضها فى شريط الحالة.

 if sender.Sorting == SortOrder.Ascending:
     sender.Sorting = SortOrder.Descending
 else: 
     sender.Sorting = SortOrder.Ascending

و هنا نفعل الترتيب التلقائى للعمود.


ListView

Figure: ListView

الشجرة TreeView

الأداة TreeView تعرض مجموعة العناصر بداخلها على شكل شجرى و تفرعات و كل عنصر فى هذه الأداة يعبر عنه بكائن TreeNode.

treeview.py

#!/usr/bin/ipy

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, StatusBar
from System.Windows.Forms import TreeView, TreeNode, DockStyle
from System.Drawing import Size


class IForm(Form):

    def __init__(self):
        self.Text = 'TreeView'
        
        tv = TreeView()

        root = TreeNode()
        root.Text = 'Languages'

        child1 = TreeNode()
        child1.Text = 'Python'

        child2 = TreeNode()
        child2.Text = 'Ruby'

        child3 = TreeNode()
        child3.Text = 'Java'

        root.Nodes.AddRange((child1, child2, child3))

        tv.Parent = self
        tv.Nodes.Add(root)
        tv.Dock = DockStyle.Fill
        tv.AfterSelect += self.AfterSelect

        self.sb = StatusBar()
        self.sb.Parent = self

        self.Size = Size(220, 220)
        self.CenterToScreen()
    

    def AfterSelect(self, sender, event):    
        self.sb.Text = event.Node.Text
    

Application.Run(IForm())

الكود السابق عبارة عن تمثيل بسيط للأداة TreeView فلدينا عنصر جذر أساسى و ثلاثة عناصر متفرعين منه.

 tv = TreeView()

تم إنشاء الأداة TreeView.

 root = TreeNode()
 root.Text = 'Languages'
 ...
 tv.Nodes.Add(root)

هنا أنشأنا العنصر الأساسى (المنبت الأساسى للعناصر).

 child1 = TreeNode()
 child1.Text = 'Python'

العنصر الابن يتم إنشائه بنفس الطريقة.

 root.Nodes.AddRange((child1, child2, child3))

العناصر الفرعية يتم ربطها بالخاصية Nodes فى العنصر الجذر الأساسى.


TreeView

Figure: TreeView

المجلداتDirectories

سوف نشرح فى الكود التالى مثال أكثر عمقاً عن الأداة TreeView.

directories.py

#!/usr/bin/ipy

import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, StatusBar
from System.Windows.Forms import Button, TreeView, TreeNode
from System.Windows.Forms import DockStyle, AnchorStyles
from System.Drawing import Size, Point
from System.IO import Directory, DirectoryInfo


HOME_DIR = '/home/vronskij'

class IForm(Form):

    def __init__(self):
        self.Text = 'Directories'
        self.Size = Size(400, 400)
        
        self.tv = TreeView()

        self.SuspendLayout()

        self.tv.Parent = self
        self.tv.Location = Point(10,10)
        self.tv.Size = Size(self.ClientSize.Width - 20, self.Height - 200)
        self.tv.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right 


        self.tv.FullRowSelect = False
        self.tv.ShowLines = True
        self.tv.ShowPlusMinus = True
        self.tv.Scrollable = True  
        self.tv.AfterSelect += self.AfterSelect

        expand = Button()
        expand.Parent = self
        expand.Location = Point(20, self.tv.Bottom + 20)
        expand.Text = 'Expand'
        expand.Anchor = AnchorStyles.Left | AnchorStyles.Top
        expand.Click += self.OnExpand

        expandAll = Button()
        expandAll.Parent = self
        expandAll.Location = Point(20, expand.Bottom + 5)
        expandAll.Text = 'Expand All'
        expandAll.Anchor = AnchorStyles.Left | AnchorStyles.Top
        expandAll.Click += self.OnExpandAll

        collapse = Button()
        collapse.Parent = self
        collapse.Location = Point(expandAll.Right + 5, expand.Top)
        collapse.Text = 'Collapse'
        collapse.Anchor = AnchorStyles.Left | AnchorStyles.Top
        collapse.Click += self.OnCollapse

        collapseAll = Button()
        collapseAll.Parent = self
        collapseAll.Location = Point(collapse.Left, collapse.Bottom + 5)
        collapseAll.Text = 'Collapse All'
        collapseAll.Anchor = AnchorStyles.Left | AnchorStyles.Top
        collapseAll.Click += self.OnCollapseAll

        self.sb = StatusBar()
        self.sb.Parent = self

        self.ShowDirectories(self.tv.Nodes, HOME_DIR)

        self.ResumeLayout()

        self.CenterToScreen()
    
    def AfterSelect(self, sender, event):
  
        self.sb.Text = event.Node.Text
        
    def ShowDirectories(self, trvNode, path):
    
        dirInfo = DirectoryInfo(path)
        if (dirInfo != None):
      
          subDirs = dirInfo.GetDirectories()
          tr = TreeNode(dirInfo.Name)

          if (subDirs.Length > 0):
          
              for dr in subDirs: 
                  if not dr.Name.StartsWith("."):
                      self.ShowDirectories(tr.Nodes, dr.FullName)
                        
          trvNode.Add(tr)    

      
    def OnExpand(self, sender, event):
        self.tv.SelectedNode.Expand()
  

    def OnExpandAll(self, sender, event):
        self.tv.ExpandAll()
  

    def OnCollapse(self, sender, event):
        self.tv.SelectedNode.Collapse()
  

    def OnCollapseAll(self, sender, event):
        self.tv.CollapseAll()


Application.Run(IForm())

المثال يعرض المجلدات للمجلد الأب لهذا المجلدات داخل الأداة TreeView و التطبيق سوف يبدأ متأخراً قليلاً لأنه يوقم بقراءة هيكلة المجلدات للمجلد الأب أولاً و لدينا أربعة ازرار على النافذة زر للفرد العنصر المحدد و الزر الآخر لطيه و زر لفرد الكل و الزر الآخر لطى الكل..

 self.tv.Scrollable = True 

هنا جعلنا الأداة قابلة لأشرطة التمرير لأن الأداة سوف تعرض الكثير من المجلدات.

 self.ShowDirectories(self.tv.Nodes, HOME_DIR)

الدالة ShowDirectories() تملأ القائمة الشجرة بالمجلدات الموجود داخل المجلد الأب.

 if (subDirs.Length > 0):
     ...

هنا نفحص إذا كان هناك أى مجلدات فرعية.

 for dr in subDirs: 
     if not dr.Name.StartsWith("."):
         self.ShowDirectories(tr.Nodes, dr.FullName)

هنا نقوم بحلقة تكرار loop على جميع المجلدات و لذلك نسخدم خوارزمية أو طريقة العودة و أيضاً نتجاهل المجلدات المخفية و فى أنظمة اليونكس Unix تبدأ هذه المجلدات بنقطة.

 trvNode.Add(tr)     

هذا السطر من الكود يضيف المجلد إلى القائمة الشجرة.

 def OnExpand(self, sender, event):
     self.tv.SelectedNode.Expand()

الأربعة ازرار مرتبطين بهذه الدالة و هناك دالة للفرد تسمى Expand() و هى خاصية بالعنصر المظلل الذى تم تحديدة.


Directories

Figure: Directories

فى هذا الجزء من الدرس تكلمنا عن العديد من الأداوت المتقدمة المتاحة فى مكتبات WinForms.


المحتويات