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

Swing Application Framework

بدأه Dr.Robert في 10 مارس 2010 · 14 رد · 2,840 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

والصلاة والسلام على سيد البشر اشرف خلق الله اجمعين سيدنا محمد ابن عبدالله الصادق الأمين.

اما بعد:

اتحدث في موضوعي هذا عن إطار العمل الخاص بتطوير الواجهات بإستخدام عناصر Swing

Swing Application Framework

هذا الإطار او الهيكل يندرج تحت الحزمة org.jdesktop وبالإمكان تضمين الحزمة للبرنامج في NetBeans من خلال خصائص البرنامج properties ومن ثم النافذة الفرعية libraries واضافة الحزمة من القائمة بعد النقر على add library .

الفئة الرئيسية في هذة الحزمة هي org.jdesktop.Application وهي القاعدة الاساسية لبرامج Swing في الهيكل

تقوم هذة الفئة بتعريف دورة حياة البرنامج Swing application life-cycle من خلال الدوال التالية:

1. initialize() وتستخدم لتهيئة خصائص البرنامج قبل الشروع في انشاء واجهة المستخدم GUI

2. الدالة startup() وتستخدم لإنشاء وإظهار واجهة المستخدم الرئيسية

3. Ready() وتستخدم لأي مهام اضافية بسيطة بعد ان تصبح الواجهة جاهزة للإستخدام.

4. Shutdown() لإخفاء الواجهة واي مهام اخيرة cleanup قبل اغلاق البرنامج.

يتم استدعاء هذة الدوال بالترتيب اعلاة . عند تشغيل البرنامج بإستدعاء الدالة lunch وحتى استدعاء دالة الخروج من البرنامج exit .

جميع دوال هذة الفئة يتم (ويجب)استدعائها من خلال event dispatch thread أو EDT فقط وهي الthread المسؤولة عن التعامل مع عناصر Swing .

(بالنسبة لي مصطلح "خيط" غير دقيق ابدا وسأستخدم الكلمة كما هي في اللغة الانجليزية).

هذا مثال على استخدام الفئة Application :

public class MyApplication extends Application {

    JFrame mainFrame = null;

    @Override
    protected void initialize(String[] args) {
       //
    }

    @Override
    protected void startup() {
        mainFrame = new JFrame("Hello World");
        mainFrame.add(new JLabel("Hello World"));
        mainFrame.addWindowListener(new MainFrameListener());
        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        mainFrame.pack();
        mainFrame.setVisible(true);

    }

    @Override
    protected void ready() {
       //
    }

    @Override
    protected void shutdown() {
        mainFrame.setVisible(false);
    }

    private class MainFrameListener extends WindowAdapter {

        @Override
        public void windowClosing(WindowEvent e) {
            exit();
        }
    }

    public static void main(String[] args) {
        launch(MyApplication.class, args);
    }
}

لاحظ اننا قمنا بوضع القيمة DO_NOTHING_ON_CLOSE للخاصية defaultCloseOperation التابعة للواجهة MainFrame وذلك لأننا نستخدم الدالة exit() للخروج من البرنامج.

بالإمكان استخدام ميزة "الحقن" لتهيئة خصائص البرنامج properties injection بإستخدام الفئة ApplicationContext .

لإستخدام اسلوب حقن الخصائص يجب علينا:

اولا تعريف ملف خصائص properties .

هذا الملف يجب ان يحمل نفس إسم الفئة ويوضع في حزمة فرعية بإسم resources وإلا لن يتعرف عليها البرنامج.

resources/ApplicationName.properties

وهذا هو المثال السابق مع إستخدام اسلوب الحقن لكل من خصائص الفئة وخصائص مكونات Swing .

public class MyApplication2 extends MyApplication {
   \\حقل قابل للحقن private @Resource Image icon;


    @Override
    protected void initialize(String[] args) {
    //
    }

    @Override
    protected void startup() {
        mainFrame = new JFrame();
        mainFrame.setName("mainFrame");
        JLabel label=new JLabel();
        label.setName("label");

        mainFrame.add(label);
        mainFrame.addWindowListener(new MainFrameListener());
        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

//حقن لخصائص الواجهة وخصائص محتوياتها        

        getContext().getResourceMap( MyApplication2.class).injectComponents(mainFrame);

//حقن لحقول الفئة  

  getContext().getResourceMap( MyApplication2.class).injectFields(this);
        mainFrame.setIconImage(icon);
        mainFrame.pack();
        mainFrame.setVisible(true);

    }


    @Override
    protected void shutdown() {
        mainFrame.setVisible(false);
    }

    private class MainFrameListener extends WindowAdapter {

        @Override
        public void windowClosing(WindowEvent e) {
            exit();
        }
    }

    public static void main(String[] args) {
        launch(MyApplication2.class, args);
    }
}

ملف الخصائص MyApplication2.properties

mainFrame.title=Hello World
label.text=Hello World
MyApplication2.icon = busy-icon9.png

لاحظ ان كل عنصر Swing نود حقن خصائصة يجب اولا تحديد خاصية الاسم لة

component.setName("someName")

ومن ثم استخدام هذا الاسم في ملف الخصائص متبوعا بإسم الخاصية لتحديد قيمتها:

someName.propertyName=value

المثال السابق يمكن اعادة كتابتة بإستخدام الفئة SingleFrameApplication وهي حالة خاصة من الفئة Application

تستخدم للبرامج التي تحتوي على واجهة رئيسية واحدة فقط.

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

public class MyApplication3 extends SingleFrameApplication {

    @Override
    protected void startup() {
       JLabel label = new JLabel();
         label.setName("label");
         show(label);

    }


    public static void main(String[] args) {
        launch(MyApplication3.class, args);
    }

}

ملف الخصائص MyApplication3.properties

Application.id = MyApplication
 Application.title = My Hello World Application
 Application.version = 1.0
 Application.vendor = Sun Microsystems, Inc.
 Application.vendorId = Sun
 Application.homepage = http://www.javadesktop.org
 Application.description =  An example of SingleFrameApplication
 Application.lookAndFeel = system

 mainFrame.title = ${Application.title} ${Application.version}
 mainFrame.iconImage=busy-icon9.png
label.text = Hello World

الدالة show الموضحة في المثال هي –عادة- ما يتم استدعائها من خلال الدالة startup بعد انشاء وتجهيزاللوحة الرئيسية لبرنامجك main panel ومن ثم فإن استدعاء الدالة show مع اللوحة سينشيء واجهة البرنامج الرئيسية main frame, ويحقن خصائص اللوحة الرئيسية وخصائص عناصرها ثم يضعها على الواجهة الرئيسية ويعرضها.

في المثال استخدمتها لعرض label على الواجهة الرئيسية فقط لتوضيح استخدامها .

نهاية الجزء الاول من الموضوع.

SwingFrameworkExamples.rar

تم تعديل هذه المشاركة بواسطة Dr.Robert في 10 مارس 2010 في 20:23

4

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#2

هل هذا هو كل ما تقدمه هذه المكتبة؟ لأنه ليس بالشيء الكثير.

--------------

لم أنتبه أنه الجزء الأول فقط :blush:.

شكرا وبانتظار الأجزاء التالية.

تم تعديل هذه المشاركة بواسطة herch في 10 مارس 2010 في 20:40

#3
اقتباس
بانتظار الأجزاء التالية

+1

#4

الجزء الثاني

السلام عليكم ورحمة الله وبركاتة. اعتذر عن وضع الموضوع في اجزاء لإنشغالي.

بالإضافة للواجهة JFrame هناك واجهة اخرى تستخدم بشكل رئيسي في اطار Swing Application Framework هذة الواجهة ممثلة بالفئة View .

لا فرق مقنع بينها وبين JFrame ولكن سأتحدث عنها بإختصار لأستخدامها بشكل واسع بين المبرمجين الذين يستخدمون هذة الحزمة (وخاصة للواجهة الرئيسية للبرنامج).

خصائص الفئة الرئيسية هي اربعة :

component ويمثل الكائن الرئيسي في الواجهة .و menuBarوstatusBar وtoolBar

هذة الخصائص تمثل الكائنات الاساسية للواجهة وهي اختيارية Optional ( لكن من المنطقي تعريف الكائن الرئيسي component على الاقل).

وهذا مثال بسيط لطريقة استخدامها عادة.

واضفت للمثال استخدام ميزة جميلة موجودة في الفئة SingleFrameApplication وهي ممثلة بالفئة الفرعية ExitListener .

public class MyApplication4 extends MyApplication3 {

    private JLabel statusMessageLabel;
    private JProgressBar progressBar;

    @Override
    protected void startup() {

        View view = this.getMainView();
        view.setComponent(createMainComponent());
        view.setMenuBar(createMenuBar());
        view.setStatusBar(createStatusBar());
        show(view);

        this.addExitListener(new ExitListener() {

            public boolean canExit(EventObject event) {
                int a = JOptionPane.showConfirmDialog(getMainFrame(), "Are you sure?", "Exit", JOptionPane.OK_CANCEL_OPTION);
                return a == JOptionPane.OK_OPTION ? true : false;
            }

            public void willExit(EventObject event) {

            }
        });

    }

    JComponent createMainComponent() {
        JPanel mainPanel = new JPanel();
        mainPanel.setName("mainPanel");
        JLabel label = new JLabel();
        label.setName("label");
        mainPanel.add(label);
        return mainPanel;
    }

    JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        menuBar.setName("menuBar");
        JMenu menu = new JMenu();
        menu.setName("menu");

        JMenuItem exitMenuItem = new JMenuItem();
        exitMenuItem.setName("exitMenuItem");

        exitMenuItem.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                exit();
            }
        });
        menu.add(exitMenuItem);
        menuBar.add(menu);
        return menuBar;
    }

    JComponent createStatusBar() {
        JPanel statusPanel = new JPanel();
        statusMessageLabel = new JLabel();
        statusMessageLabel.setName("statusMessageLabel");
        progressBar = new JProgressBar();
        JSeparator statusPanelSeparator = new JSeparator();
        GroupLayout statusPanelLayout = new GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
                statusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(statusPanelSeparator, GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE).addGroup(statusPanelLayout.createSequentialGroup().addContainerGap().addComponent(statusMessageLabel).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 230, Short.MAX_VALUE).addComponent(progressBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addContainerGap()));

        statusPanelLayout.setVerticalGroup(
                statusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(statusPanelLayout.createSequentialGroup().addComponent(statusPanelSeparator, GroupLayout.PREFERRED_SIZE, 2, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addGroup(statusPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(statusMessageLabel).addComponent(progressBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)).addGap(3, 3, 3)));


        return statusPanel;

    }

    public JLabel getStatusMessageLabel() {
        return statusMessageLabel;
    }

    public JProgressBar getProgressBar() {
        return progressBar;
    }

    public static void main(String[] args) {
        launch(MyApplication4.class, args);
    }
}

ملف الخصائص MyApplication4.properties

menu.text=File
 exitMenuItem.text=Exit
statusMessageLabel.text=idle..

ستلاحظ ان تموضع الكائنات الاساسية على View يتم اوتوماتيكيا.

في NetBeans يمكنك استخدام designer لتصميم الواجهات من نوع View تماما مثل JFrame .

عبر انشاء ملف جديد New-->Swing GUI Forms-->Bean Form ثم تحديد Superclass ك org.jdesktop.application.FrameView .

ويمكنك ايضا انشاء هيكل لبرنامج بسيط من خلال New Project-->Java-->Java Desktop Application

(وهذة هي اسهل طريقة للبدء في استخدام هذا الاطار لبرمجة الواجهات).

عرفنا من السابق ان الفئة ApplicationContext تستخدم لحقن خصائص الكائنات في الواجهات.

في الحقيقة هذة الفئة مسؤولة عن جميع الموارد التي يحتاجها البرنامج اثناء دورة حياتة.

هذة الموارد تتضمن خصائص الكائنات , الإجراءات المخزنة (الخلفية والامامية forground & background actions ), وموارد التخزين المحلية local storage وغيرها.

تكلمنا عن الاولى وسنتكلم عن البقية ان شاء الله.

تعريف الاجراء action في هذا الاطار يتم عبر استخدام الرمز @Action اعلى الدوال التي تمثل تلك الاجراءات

(هذة الدوال تستخدم لتعريف الدالة

javax.swing.Action.ActionPerforemd(ActionEvent)

اثناء run-time )

الدوال التي من الممكن تعريفها كإجراءاتactions هي:

التي تأخذ قيمة واحدة من نوع ActionEvent او لا تأخذ اي قيمة. و تعيد قيمة من نوع org.jdesktop.application.Task او void

اذا قامت الدالة بإعادة Task فسيتم تفيذة في Thread منفصلة عن EDT

(Action's background task).

الفئة org.jdesktop.application.Task

هذة الفئة تمثل عملية خلفية Background process وهي مصممة للعمليات الطويلة نسبيا و المدارة او المحفزة عبر الواجهات GUI فقط.

في هذة الفئة , الدالة doInBackground() هي التي تمثل العملية.

هذة الفئة تقوم بإطلاق احداث PropertyChangeEvent متعددة ومختلفة تساعد الواجهة GUI على مراقبة العملية وابقاء المستخدم على اطلاع حتى انتهاءها.

في هذا الاطار يتم استخدام غرض واحد من الفئة TaskMonitor لمراقبة جميع الاجراءات المخزنة في البرنامج.

وهذا مثال يوضح المسألة.

public class MyApplication5 extends MyApplication4{



    @Override
    protected void startup() {
       show(new MyView(this));

    }

public static MyApplication5 getApplication() {
        return Application.getInstance(MyApplication5.class);
    }
 public static void main(String[] args) {
        launch(MyApplication5.class, args);
    }
}

الواجهة

public class MyView extends FrameView {

    boolean enabled = true;
    private JProgressBar progressBar;
    private JLabel statusMessageLabel;

    public MyView(MyApplication5 app) {
        super(app);
        initComponent();
    }

    void initComponent() {
        MyApplication5 app = MyApplication5.getApplication();
        JComponent mainComponent = app.createMainComponent();
        JMenuBar menuBar = app.createMenuBar();
        JComponent statusBar = app.createStatusBar();
        progressBar = app.getProgressBar();
        progressBar.setVisible(false);
        statusMessageLabel = app.getStatusMessageLabel();

        TaskMonitor taskMonitor = new TaskMonitor(app.getContext());

تنصت على احداث العمليات الخلفية في البرنامج
        taskMonitor.addPropertyChangeListener(new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if (propertyName.equals("started")) {
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if (propertyName.equals("done")) {
                    progressBar.setValue(0);
                    progressBar.setVisible(false);
                } else if (evt.getPropertyName().equals("message")) {
                    String text = (String) (evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                }
            }
        });


        JButton button1 = new JButton();
        button1.setAction(app.getContext().getActionMap(this).get("myAction"));
        mainComponent.add(button1);


        setComponent(mainComponent);
        setMenuBar(menuBar);
        setStatusBar(statusBar);

    }

    @Action(enabledProperty = "enabled")
    public Task myAction() {
        setEnabled(false);
        return new MyTask(this);
    }

    public void setEnabled(boolean enabled) {
        boolean old = this.enabled;
        this.enabled = enabled;
        this.firePropertyChange("enabled", old, enabled);
    }

    public boolean isEnabled() {
        return enabled;
    }
}

الإجراء الخلفي

class MyTask extends Task {

    private final MyView view;
    private int faild;
    private int finished;

    public MyTask(MyView view) {

        super(view.getApplication());
        this.view = view;
    }

    @Override
    protected Object doInBackground() throws Exception {

        message("startMessage", 1);

        Thread.sleep(1000);


        finished = 1;
        return null;
    }

    @Override
    protected void failed(Throwable cause) {
        message("errorMessage");
        faild = 1;
    }

    @Override
    protected void finished() {
        message("finishedMessage", finished, faild);
        view.setEnabled(true);
    }
}

ملف الخصائص MyView.properties

myAction.Action.text = action
myAction.Action.shortDescription = Tooltip text for myAction

ملف الخصائصMyTask.properties

 title = My Task
 description = A task of mine for my own purposes.

startMessage = Starting: working on %s subtasks...
 errorMessage = An unexpected error occurred, skipping subtask
 finishedMessage = Finished: completed %s subtasks, %s failures

تلاحظ انة - في الواجهة MyView - تم تعريف خاصية enabledProperty للAction , هذة الخاصية وخواص اخرى تعتبر اختيارية optional ووظيفتها كالتالي:

block وتستخدم لتحديد الجزء المراد تعطيلة في الواجهة اثناء تنفيذ الاجراء في الخلفية.

name ويستخدم لتحديد اسم الاجراء (ولكن اسم الاجراء هو بالفعل اسم الدالة ولا اعلم المغزى من هذة الخاصية).

enabledProperty لتعريف اسم الخاصية (من الفئة نفسها) المستخدمة في تمكين\تعطيل الاجراء.

selectedProperty لا اعلم فائدتها حتى الان.

لاحظ ان الخاصية المستخدمة كenabledProperty يجب ان تكون bound property (أي تطلق PropertyChangeEvent عند تغير قيمتها )

قم بتغيير الكود الخاص بالإجراء في المثال اعلاة كالتالي:

 @Action(block=MyTask.BlockingScope.ACTION)
    public Task myAction() {
        return new MyTask(this);
    }

وستحصل على نفس النتيجة.

سيتبقى لنا في -اطار موارد البرنامج- مسألة حفظ واستعادة حالة الواجهات عند ايقاف واعادة تشغيل البرنامج وسأتكلم عنها في الجزء القادم ان شاء الله.

(الامثلة في المرفقات)

تم تعديل هذه المشاركة بواسطة Dr.Robert في 11 مارس 2010 في 22:33

1

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#5

l

تم تعديل هذه المشاركة بواسطة Dr.Robert في 11 مارس 2010 في 08:26

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#6

الجزء الثالث

السلام عليكم ياشباب العرب.

قد تحتاج في بعض الاحيان لإستعادة واجهة المستخدم الى ما كانت علية في الجلسة السابقة.

وذلك بقرائة خصائص كائنات الواجهة من القرص الصلب حيث تم وضعها مسبقا.

هذا الاسلوب قد يساعدك في تجنب تعقيدات الكود المسؤول عن تعقب إعدادت المستخدم على وجة الخصوص.

اذا كانت واجهة برنامجك معقدة التركيب وتفاعلية مع المستخدم الى الحد الذي يمكنة من تغيير مواقع او خصائص الكائنات المرئية (واجهة فوتوشوب كمثال). فإن سؤال مثل "هل تريد حفظ الاعدادات؟" في كل مرة يقوم الممستخدم بإغلاق نافذة فرعية للبرنامج. او يقوم بتغييرحجم الجدول في frame داخلي او يغير لون الخط اويعمل سحب وافلات..الخ. هو سؤال غير مرغوب بة.

ولذلك فإن "طرد flush " خصائص الكائنات القابلة للتغيير الى ملف في القرص الصلب ليس بالفكرة السيئة.

في اطار Swing Framework فإن الكائن JComponent الذي تم تعريف خاصية SessionProperty لة , بالإمكان حفظ واستعادة حالتة.

يتم تعريف هذة الخاصية للكائن عبر الدالة

JComponent.putClientProperty(Object key,Object value)

حيث key عبارة عن النوع SessionStorage.Property و value عبارة عن غرض من فئة من ذلك النوع.

او ان يقوم الكائن JComponent بعمل implementation ل SessionStorage.Property مباشرة.

SessionStorage.Property interface

public class MyProperty implements SessionStorage.Property
{
public Object getSessionState(Component c)
{
}

public void setSessionState(Component c,Object state)
{
}

}

الدالة الاولى يتم استدعائها لقراءة قيمة تمثل حالة الكائن المراد حفضها وتسمى sessionState ضمنيا , هذة القيمة قد تكون primitive او non-primitive وفي هذة

الحالة فإن فئة الغرض إما Collection او Java bean (اي فئة تحتوى على no-argument constructor وجميع خواصها متاحة بواسطة setters & getters ) مالم فإن القيمة المقروءة تعتبر غير صالحة .

في JDK6 بالإمكان استخدام الرمز @ConstructorProperties لتعريف اسماء خصائص الفئة وتجنب وضع setters لتلك الخصائص. (وهي الطريقة الموضحة في المثال).

الدالة الثانية تستخدم لتمثيل الحالة المسترجعة على الكائن .

المثال في المرفقات وهناك جائزة عينية عبارة عن "عربية وفيلا في الساحل الشمالي" لأول من يعرف ماهو الكائن Swing المستخدم في البرنامج والذي لانحتاج لتعريف الخاصية SessionStorage.Property لة لنستعيد حالتة ولماذا؟

السؤال الثاني "برضة عربية وفيلا جنب الاولانية" : على اي اساس يتم اختيار مسار حفظ ملف حالة الكائنات في الجهاز؟

1...2...3 GO !

SwingFrameworkExamples2.rar

1

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#7

الجزء الرابع و الأخير.

عرفنا أن الفئة SingleFrameApplication وهي حالة خاصة من الفئة الرئيسية Application تستخدم – كماهوموثق في الحزمة – للبرامج التي لها نافذة واحدة رئيسية (هذا حال اغلب البرامج في نظري) . خلال كتابتي لهذا الموضوع لاحظت انه تم تعريف مجموعة اجراءات Actions في هذة الفئة وهي غير مذكورة ابدا في توثيق الفئة (لسبب غير معروف) ولقد عرفت بوجودها بالصدفة من خلال استعراض اسماء الاجراءات المخزنة في الفئة من خلال ActionMap .

اسماء هذة الاجراءات:

quit ثبت انها تستدعى ضمنيا اثناء الخروج من البرنامج ولذلك لا علاقة لنا بها.

cut, copy, paste, delete ويبدو من اسماءها انها لتحريرالنصوص.

وطبعا لأن الحزمة غير مفتوحة المصدر(وتوثيقها اقل من جيد وحتى غير موجود لبعض الفئات والدوال) فلا سبيل لمعرفة الفائدة من شيء إلا بالتجربة , وقد كتبت المثال التالي واتضح انها بالفعل لتحرير النصوص . اترككم لتحكموا بأنفسكم على النتيجة.

وبهذا نكون قد انتهينا من الموضوع وتكلمنا عن اهم ما فيSwing Framework .والحمد للة.

ملاحظات اخيرة للفائدة:

1-لاحظت اثناء كتابة الامثلة للموضوع اننا لا نحتاج لإنشاء اغراض من اغلب الفئات في الحزمة بشكل صريح . لأن ذلك يتم عبر AplicationContext . وهي فكرة جيدة حيث اننا في الغالب لن نحتاج لأكثر من غرض واحد من كل فئة (مثل ResourceMap وActionMapوTaskMonitor ...) وقد نستخدمة في اكثر من مكان في البرنامج كshared Object وبالتالي نقلل من عدد references المستخدمة.

2-عند استخدام الفئة SingleFrameApplication فالشخص غير مضطر لكتابة كود خاص للتحكم بعرض الواجهات الفرعية للبرنامج ويمكن أن يستخدم الدوال

show(JFrame) و show(JDialog)

لعرضها.

هذة الدوال تقوم ايضا بإسترجاع حالة الواجهة اذا امكن (اذا تم تعريف الخاصية SessionStorage.Property لكائن واحد اواكثر في الواجهة). وكذلك يتم حفظ حالة الواجهة عند اخفائها.

هذا ينطبق ايضا على الواجهة الرئيسية للبرنامج عند استدعاء الدالة

show(View)

من خلال دالة تشغيل البرنامج startup() .

وبالتالي فكل ما على الشخص هو تعريف الخاصية Property للكائنات التي يود حفظ واسترجاع حالتها فقط. اما استدعاء الدوال save وrestore فيتم ضمنيا.

اذا كنت تحتاج لمزيد من التحكم (لجعل حفظ حالة الواجهة يتم حسب شرط مثلا) فبالإمكان تخطي override الدوال show والدالة shutdown . وقد تحتاج لتسجيل WindowListener في هذة الحالة مع النوافذ الفرعية ليعرف البرنامج ماذا يفعل عند اغلاق واجهة فرعية (تماما مثل دور shutdown بالنسبة للواجهة الرئيسية) .

هذا والله من وراء القصد.

السلام عليكم.

SwingFrameworkExamples3.rar

2

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#8

شكرا جزبلا :) ..

لكن أردت ان استفسر عن مشكلة اواجهها

أريد استدعاء JFrame2 في JFrame1 اخر

جميعهم موجودين في نفس الباكج..

حاولت بجميع الطرق لمن لم تجدي!..

تظهر لي مشكلة ان JFrame1 لايمكنه ايجاد JFrame2 ..

#9

ممكن تضيف الكود هنا

تم تعديل هذه المشاركة بواسطة Dr.Robert في 16 مارس 2010 في 18:42

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#10

موضوع أكثر من رائع يا حج مازن

يستحق كل تقدير

لي رجعة وقراءة مفصلة بإذن الله

تحياتي

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

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

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

728x90.png

#11

بدونك لما كان للموضوع وجود يا علاء. وللا نسيت :wink:

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#12

أخجلت تواضعي يا مازن

ثم أنا أرمي صنارتي في كل المياه

فهناك مياه خيرة أصطاد منها وهناك مياه خيرة لكنها بخيلة وهناك مياه تدعي الخيرية وهناك مياه أتأمل أن أستطيع الصيد منها في المستقبل

كل ما هناك أني أرمي الصنارة فهل من حقي أن أقول بأني صاحب الفضل في صيد السمك

أعتقد الجواب الصحيح لا

في انتظار أسماك أخرى يا مازن :lol:

تحياتي

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

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

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

728x90.png

#13

وبإنتظار صنانير اخرى , واذا لم يعجبك السمك في المرة القادمة "ذنبك على جنبك انا ماليش دعوة" :lol:

بحثت عن قلمي البارحة فلم أجدة!

...............

لم أجد سوى لوحة المفاتيح هذة

.............

تتطلع إلي بشفقة..

.............

أكاد أسمعها .. تقول (ألم يسمع بGoogle ؟!؟؟)

#14

موضوع جيد ، لا اعلم كيف فاتني هذا الموضوع ، فانا لم اراه من قبل...

سأقوم بقرائته بتمعن ،، شكرا لك

#15

شكرا اخى الكريم

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

وجميل ايضا جزئيه copy , cut , past

تسلم ايدك

تحياتى

1

Software Developer
Mahmoudkelany.com


 

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