الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

بناء صفوف جافا المقادة بالأحداث

بدأه Speed_Of_Light في 3 فبراير 2010 · 8 رد · 1,280 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

هناك الكثير من الأحداث التي قد يرغب المبرمج في ربط كود لاحق معها. أمثلة: عند إغلاق النافذة أظهر رسالة تأكيد للمستخدم، عند ضغط الزر أظهر النافذة الفلانية، إلخ ...

ويتم ذلك عادة بإضافة متنصتات الأحداث كما هو معروف.

ولكن ماذا لو أردت أن تصنع أنت نظام أحداث خاص بك ؟

حسناً، إحدى الطرق هي المذكورة بشكل رائع في مدونة الأخ علاء الصالحي.

لكن مهلاً ! هناك طريقة أكثر ديناميكية وأناقة، وهي تستخدم بشكل قياسي مع الـ JavaBeans، وهي التنصت على الخصائص.

الأمر بسيط جداً، فلدعم التنصت على تغير الخصائص في برنامجك عليك القيام بمايلي:

• إنشاء غرض من الفئة PropertyChangeSupport

• إعلان أي تغيرات على الخصائص عند حدوثها باستخدام firePropertyChange

• تحقيق الطريقتين addPropertyChangeListener و removePropertyChangeListener لإضافة وإزالة المتنصتات

وهذا مثال توضيحي:

package PropertyChange;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
// هذا الصف هو JavaBean تمثل سيارة
public class Car implements Serializable {
    // ننشئ غرض من فئة PropertyChangeSupport لكي ندعم الأحداث عند تغير الخصائص
    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private String color = "Red"; // اللون
    private int speed = 0; // السرعة
    private int number = 1000000; // الرقم

    public Car() {
    }

    public String getColor() {
        return color;
    }

    public int getNumber() {
        return number;
    }

    public int getSpeed() {
        return speed;
    }
    // لاحظ كيف نقوم باستدعاء الطريقة/الدالة firePropertyChange ونمرر لها ثلاث موسطات (parameters):
    // اسم الخاصة التي يتم تغييرها
    // القيمة القديمة قبل التعديل
    // القيمة الجديدة بعد التعديل
    public void setColor(String color) {
        String old = this.color;
        this.color = color;
        this.pcs.firePropertyChange("color", old, color);
    }

    public void setNumber(int number) {
        int old = this.number;
        this.number = number;
        this.pcs.firePropertyChange("number", old, number);
    }

    public void setSpeed(int Speed) {
        int old = this.speed;
        this.speed = Speed;
        this.pcs.firePropertyChange("speed", old, speed);
    }
    // نقم هنا بتحقيق الطريقتين addPropertyChangeListener و removePropertyChangeListener لإضافة وإزالة المتنصتات
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        this.pcs.removePropertyChangeListener(listener);
    }
}

الآن دعنا نرى كيف يمكننا التنصت على تلك الأحداث ... هذا صف اختبار:

package PropertyChange;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class Test {

    public static void main(String[] args) {
        Car car = new Car();
        car.addPropertyChangeListener(new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent e) {
                String propertyName = e.getPropertyName();
                if ("color".equals(propertyName)) {
                    System.out.println("لقد تم تغيير اللون من " + e.getOldValue() + " إلى " + e.getNewValue());
                } else if ("number".equals(propertyName)) {
                    System.out.println("لقد تم تغيير الرقم من " + e.getOldValue() + " إلى " + e.getNewValue());
                } else if ("speed".equals(propertyName)) {
                    System.out.println("لقد تم تغيير السرعة من " + e.getOldValue() + " إلى " + e.getNewValue());
                }
            }
        });

        car.setColor("yellow");
        car.setSpeed(80);
        car.setNumber(65879464);
    }
}

سحر أليس كذلك ! :wink:

تم تعديل هذه المشاركة بواسطة Speed_Of_Light في 3 فبراير 2010 في 21:14

2
#2

رائع

جزاك الله خير الجزاء

#3

شيء جميل فعلا.

ممكن عمل ال data binding بهاته الطريقة على ما أظن.

ملاحظة خارج الموضوع، أظن أن ترجمة class إلى صف ليست جيدة، من الأفضل استعمال صنف أو فئة. لكن لست خبيرا بالترجمة، ممكن أكون مخطئ :unsure:

#4

فعلا موضوع جميل جدا ,,,

جزيتم خيرا و بارك ربي فيكم

#5

أهلاً بكم

اقتباس
ممكن عمل ال data binding بهاته الطريقة على ما أظن.

يمكن نعم ... لكن إذا كنت تتكلم عن عمل Data Binding للبيانات مع المكونات المرئية فهناكطريقة جاهزة للقيام بذلك وأظنها أفضل (وأسهل)

لكن فوائدها ليست محصورة في الـ Data Binding حيث أن استخدامها شائع جداً في الحزم الضخمة والمعقدة.

أما بالنسبة لتسمية الفئات بصفوف، فهي بالفعل ليست بترجمة دقيقة ... لكن هكذا تسمى في بلدي !

سأحاول أن أستخدم اسم "فئة" أو "صنف" في المستقبل - شكراً لك

تم تعديل هذه المشاركة بواسطة Speed_Of_Light في 3 فبراير 2010 في 22:33

#6

للتوضيح فقط

كل الأحداث تتبع نمط المراقب Observer pattern

بما فيها طريقتي التي ذكرتها مسبقاً

بالنسبة لمزايا وعيوب الطريقة التي ذكرتها أنا والطريقة التي يعرضها علينا الأخ Speed_Of_Light

1- الطريقة التي أمامنا اليوم والحق يقال أسهل بكثير من طريقتي

2- طريقتي تعطي مرونة flexibility أكبر في بناء الحزم packages

سأوضح لكم بمثال من حزمة المحرك AAnimation

لدي حدث يحدث يحصل قبل عملية التحريك وحدث يحصل بعد عملية التحريك

3- واضح في المثال الذي طرحته في طريقتي أن الخوارزمية كانت سهلة كل ما تحتاجه هي عملية مقارنة

لكن في واقع الأمر ليس كل الخوارزميات لهم نفس السهولة

(المثال كان يعتمد حدث عندما تكون القيمة الجديدة أكبر من القيمة القديمة يختلف عن الحدث عندما تكون أصغر)

4- أحياناً أخرى أنا أعرف أنه لا وجود للحدث في حالة تغيير الرقم إلى القيمة الأكبر لكن المبرمج الذي يستخدم حزمتي لا يعرف

ستقولون لي تكتب له توثيق documentation سأقول لكم إن كنت تريد أن تكون مبرمج API يجب أن تفكر كيف تريح المبرمجين أكثر من أي شيء آخر

بينما في طريقة اليوم قد لا يعرف مبرمج الحزمة أن هذه العملية غير صحيحة

أشكر الأخ العزيز Speed_Of_Light على المعلومات المفيدة التي قدمها لنا

وأتمنى من الله أن جعلها في ميزان حسناته

بقي أن أقول لكم انتخبوا مرشحكم المستقل AAnimation :lol:

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#7
علاء الصالحي كتب:

بقي أن أقول لكم انتخبوا مرشحكم المستقل AAnimation :lol:

والله ضحكتني اخوى علاء على هذا الشعار ...

اما بالنسبة للحزمة المحرك ... فانا لا اهتم كثيرا بـ swing ، لان اهتمامي هو web

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

#8

أهلاً بك أخي علاء :)

وشكرأ لك على هذه الملاحظات

بالنسبة للقيام بالأحداث قبل حدوث الحدث وبعد حدوثه فهناك عدة حلول:

إما بالاعتماد الكامل على الـ PropertyChangeListeners:

package PropertyChange;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;

public class Car implements Serializable {

    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private String color = "Red";
    private int speed = 0;
    private int number = 1000000;
    private boolean changingSpeed = false;

    ...

    private boolean getChangingSpeed() {
        return changingSpeed;
    }

    private void setChangingSpeed(boolean changingSpeed) {
        boolean old = this.changingSpeed;
        this.changingSpeed = changingSpeed;
        this.pcs.firePropertyChange("changingSpeed", old, changingSpeed);
    }

    ...

    public void setSpeed(int Speed) {
        setChangingSpeed(true);
        int old = this.speed;
        this.speed = Speed;
        this.pcs.firePropertyChange("speed", old, speed);
        setChangingSpeed(false);
    }

    ...

}

وهذا صنف التجربة:

public class Test {

    public static void main(String[] args) {
        Car car = new Car();
        car.addPropertyChangeListener(new PropertyChangeListener() {
            JTable jt = new JTable(new DefaultTableModel(null));
            public void propertyChange(PropertyChangeEvent e) {
                String propertyName = e.getPropertyName();
                if ("color".equals(propertyName)) {
                    System.out.println("لقد تم تغيير اللون من " + e.getOldValue() + " إلى " + e.getNewValue());
                } else if ("number".equals(propertyName)) {
                    System.out.println("لقد تم تغيير الرقم من " + e.getOldValue() + " إلى " + e.getNewValue());
                } else if ("speed".equals(propertyName)) {
                    System.out.println("لقد تم تغيير السرعة من " + e.getOldValue() + " إلى " + e.getNewValue());
                } else if ("changingSpeed".equals(propertyName)) {
                    if((Boolean)e.getNewValue()){
                        System.out.println("سيبدأ الآن تغيير السرعة");
                    }
                }
            }
        });

        car.setColor("yellow");
        car.setSpeed(80);
        car.setNumber(65879464);
    }
}

أو استخدام مزيج من الطريقتين ، وهذا ما أراه في الحزم الضخمة المعقدة.

أو أن يقوم المبرمج بإعادة كتابة overriding الطريقة setXXX (دعه يستفيد من خصائص البرمجة غرضية التوجه !) كما في هذا المثال الصغير:

public class SpeacialCar extends Car {
    public void setSpeed(int Speed) {
        System.out.println("سيبدأ الآن تغيير السرعة");
        super.setSpeed(Speed);
    }
}

لكني لم أفهم النقطة الرابعة

اقتباس
بقي أن أقول لكم انتخبوا مرشحكم المستقل AAnimation

بالطبع! أنا من أول الناخبين :D

#9

أخي العيافي حتى أنا لي فترة طويلة لا أهتم بـ swing

لكني كثير من الأحيان ما أكون مهتم بعمليات المحاكاة simulation وهذا يحتاج إلى تواجد الحجة swing بيننا

على كل كما أقول دائماً في قصة الحزمة الموضوع لم يتعدى محاولتي لمساعدة صديق عزيز علي

تطورت الفكرة في رأسي حتى أصبحت كما ترونها

نفس الموضوع حصل في AChart

بأمانة أجد في ميول لبرمجة الحزم أكثر من البرمجة المرئية بمراحل

طبعاً أرحب بملحوظاتك على الحزمة في أي وقت

أخ Speed_Of_Light

أعجبتني الأفكار بل وفتحت لي أفق جديد

ويبدو لي أن هذه الطريقة تغطي غالبية الحالات التي في بالي

كما يبدو لي أني سأسحب AAnimation من الأسواق :lol:

بالمناسبة الآن انتبهت إلى أنك استخدمت كلمة الأخ أيمن أبو سمرة سحر :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

مواضيع مشابهة