سؤال

أنا أعمل حاليا على بعض رمز Java الذي يحتوي على الكثير من ActionListeners المحددة فيه (واحد لكل منها JButton) وهناك حوالي 60 أزرار. يتم تعريف جميعها جميع الفصول الداخلية المجهولة في JButton.addActionListener طريقة. لقد كنت أفكر في طرق إعادة تكوين هذا لإنشاء التعليمات البرمجية أن هذا هو جعلها تبدو تشوش شديد. فكرت في متناول المستمعين في فئة منفصلة تتمتع بشكل أساسي بتحميل من الأساليب الثابتة التي تعود كل مستمع. هذا يعني أن الشفرة سوف تبدو مثل addActionListener(GetActionListener.addActionListener()). وبعد في حين أن هذا سيجعله ناطور أشعر أنه ليس حل أنيق حقا. اعتقدت أيضا خريطة نهائية ثابتة عقد أزواج KV مع اسم المستمع إلى المستمع نفسه. ولكن مرة أخرى لا يزال هذا لا يبدو وكأنه حل أنيق للغاية. كنت أتساءل ما إذا كان أي شخص لديه أي أفكار؟ يجب أن أقول أيضا أن جميع ActionListeners مختلفة جدا.

هل كانت مفيدة؟

المحلول

أود أن أقترح عدم إضافة إجراءات مباشرة باستخدام ActionListener. وبعد إذا فعلت بهذه الطريقة تصبح غير قابلة لإعادة الاستخدام. بدلا من ذلك لف أفعالك في javax.swing.Action صف دراسي. بحيث يمكنك إعادة استخدام الإجراء أينما تريد. على سبيل المثال، يمكنك الآن استخدام الإجراء نفسه لتقول اختصار قائمة لإجراء نسخ وزر "نسخ" في شريط الأدوات. في الأساس الفكرة ليست إخراج إجراءات روعة مباشرة مع عناصر GUI.

الآن القادمة إلى سؤالك. أود أن أجعل repository of actions في فصل دراسي يسمى، قل، ActionRepsoory مع طريقة عامة عامة Action getAction(String). وبعد سيتم تحديد كل عمل من الإجراءات الخاصة بك بواسطة سلسلة ثابتة تستخدمها لاسترداد الإجراء من المستودع. عادة أن هذه السلسلة ستكون actionCommand للعنصر. كيف تدير الإجراءات في ActionRepository، عبر Hasmap أو أيا كان ذلك، تعتمد تماما عليك.

هذه هي الطريقة التي قام بها Doin في معظم الكود البروفي، AFAIK.

نصائح أخرى

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

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

أن يقال ... 60 أزرار على واجهة المستخدم؟! حقا! أوتش! هل هم جميعا على شاشة واحدة أم القيام به مع علامات التبويب أو شيء من هذا؟ (إذا كانت علامات التبويب أو أي شيء لدي المزيد من العرض في الإجابة).

يمكنك جعل فرعية خاصة من ActionListener يستخدم هذا التفكير لاستدعاء اسم طريقة معينة، ثم يمكنك تطبيق جميع الإجراءات 60 الخاصة بك كطرق طبيعية.

package com.example;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodAsActionListener implements ActionListener {

    private Object receiver;
    private Method method;

    public MethodAsActionListener(Object receiver, String name) {
        this.receiver = receiver;
        try {
            this.method = receiver.getClass().getDeclaredMethod(name);
        } catch (SecurityException e) {
           throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        try {
            method.invoke(receiver);
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

}

ثم إذا كنت طريقة call إلى صفك

private call(String name) {
    return new MethodAsActionListener(this, name);
}

ثم يمكنك إضافة أفعالك على النحو التالي

button1.addActionListener(call("methodName1"));
button2.addActionListener(call("methodName2"));
button3.addActionListener(call("methodName3"));
button4.addActionListener(call("methodName4"));
button5.addActionListener(call("methodName5"));

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

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

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

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

في الواقع - اسمحوا لي أن أنظر.

نعم، احتفظت بالفصول الموجودة في Google Doc :) تم تحديد البيانات مثل هذا:

final static String[] menus = { "File:*", "Save:save", "Load:load", "(", "Print:-", "Preview:preview", ")", "Quit:quit" };

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

هذه السلسلة يمكن أن تنشئ وربط قائمة بأكملها مع مكالمة واحدة.

هنا شفرة المصدر الخاصة بي إذا كنت ترغب في اللعب معها.

فئة "TestMenu" في الأعلى هي فئة اختبار توضح كيفية استخدام طريقة BuildMenus.

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

قد تكون واجهة برمجة تطبيقات أفضل طريقة للربط مثل هذا:

bind(this, new JButton("Save"), "save", this);

حيث يؤدي الضغط على زر حفظ الأسلوب "حفظ" في هذا (أو أي كائن آخر مررته). يمكنك حتى إجراء المعلمة "حفظ" اختياري واستخدام JButton.getText (). tolower (). كطريقة الاتصال إذا لم تكن هناك معلمة (أعتقد أن هذه الاتفاقية قبل التكوين)

لم أفعل ذلك بهذه الطريقة مع القائمة لأنني أردت أيضا التخلص من إنشاء القائمة وعلاقات القائمة في بياناتي.

لاحظ أن الترميز بهذه الطريقة هو وسيلة رهيبة للحصول على فصل MVC الخاص بك في Java - يمكن إزالة جميع رمز وحدة التحكم من وجهة نظرك.

package hEvil;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

public class JDial extends JDialog {

private static final long serialVersionUID = -26565050431585019L;
private final JPanel contentPanel = new JPanel();

public static void main(String[] args) {
    try {

        JDial dialog = new JDial();
        dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        dialog.setVisible(true);
        dialog.setTitle("Heavy Evil");
        dialog.setBackground(Color.WHITE);

    } catch (final Exception e) {
        e.printStackTrace();
    }
}

public JDial() {
    setBounds(0, 0, 1300, 800);
    getContentPane().setLayout(new BorderLayout());
    contentPanel.setLayout(new FlowLayout());
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    getContentPane().add(contentPanel, BorderLayout.CENTER);

    JPanel windowPane = new JPanel();
    windowPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
    getContentPane().add(windowPane, BorderLayout.SOUTH);

    {
        JButton cancelButton = new JButton("Exit");
        cancelButton.setActionCommand("Exit");
        windowPane.add(cancelButton);
        cancelButton.setBounds(0, 0, 1200, 700);

    }

    {
        JPanel textPane = new JPanel();
        textPane.setLayout(new FlowLayout(FlowLayout.LEFT));
        getContentPane().add(textPane, BorderLayout.NORTH);
        textPane.setVisible(true);

        {
            JTextArea textArea = new JTextArea("Username", 2, 15);
            textPane.add(textArea);
            textArea.setWrapStyleWord(true);
            textArea.setEditable(true);
            textArea.setFont(Font.getFont(Font.SANS_SERIF));
            textArea.setVisible(true);
            textArea.enableInputMethods(isEnabled());
            textArea.computeVisibleRect(getBounds());
            textArea.setBackground(Color.GRAY);

            JTextArea textArea2 = new JTextArea("Password", 2, 15);
            textPane.add(textArea2);
            textArea2.setWrapStyleWord(true);
            textArea2.setEditable(true);
            textArea2.setFont(Font.getFont(Font.SANS_SERIF));
            textArea2.setVisible(true);
            textArea2.enableInputMethods(isEnabled());
            textArea2.computeVisibleRect(getBounds());
            textArea2.setBackground(Color.GRAY);

        }
        {

            JButton registerButton = new JButton("Register");
            textPane.add(registerButton);

        }
        {
            JButton newButton = new JButton("Submit");
            textPane.add(newButton);
            newButton.setEnabled(true);
            getRootPane().setDefaultButton(newButton);
            newButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {

                    JFrame newFrame = new JFrame("Welcome");
                    newFrame.setVisible(true);
                    newFrame.setBackground(Color.BLACK);
                    newFrame.setBounds(0, 0, 580, 200);

                    JPanel newPanel = new JPanel();
                    newFrame.add(newPanel);
                    dispose();

                    JButton nuButton = new JButton("Mario");
                    newPanel.add(nuButton);

                    JButton nuButton2 = new JButton("Kirby");
                    newPanel.add(nuButton2);

                    JButton nuButton3 = new JButton("Mew Two");
                    newPanel.add(nuButton3);

                    JButton nuButton4 = new JButton("Vegeta");
                    newPanel.add(nuButton4);

                    JButton nuButton5 = new JButton("Tidus");
                    newPanel.add(nuButton5);

                    JButton nuButton6 = new JButton("Link");
                    newPanel.add(nuButton6);

                    JButton nuButton7 = new JButton("Master Chief");
                    newPanel.add(nuButton7);

                    JButton nuButton8 = new JButton("Snake");
                    newPanel.add(nuButton8);

                    JButton nuButton9 = new JButton("Cash");
                    newPanel.add(nuButton9);

                    JButton nuButton10 = new JButton("Lara");
                    newPanel.add(nuButton10);

                    JButton nuButton11 = new JButton("Max");
                    newPanel.add(nuButton11);

                    JButton nuButton12 = new JButton("Spyro");
                    newPanel.add(nuButton12);

                    JButton nuButton13 = new JButton("Sephiroth");
                    newPanel.add(nuButton13);

                    JButton nuButton14 = new JButton("Scorpion");
                    newPanel.add(nuButton14);

                }
            });

        }

    }

}

}
//AND I WANT TO BE ABLE TO IMPLEMENT EACH BUTTON FROM ANOTHER CLASS
//FROM ACTIONEVENT WITH SOMETHINGS SIMILAR TO nuButtonX.actionImplemented...
//CALLING THE SAME ACTIONLISTENER IF I CAN AND THEN CREATING A CLASS FOR
//MODIFICATIONS AT EACH INSTANCE. 
enter code here
package hEvil;

import java.awt.event.ActionEvent;

import javax.swing.JFrame;

public class ActoEve extends ActionEvent {

/**
 * 
 */
private static final long serialVersionUID = -2354901917888497068L;
public ActoEve(Object arg0, int arg1, String arg2) {
    super(ActionEvent.ACTION_PERFORMED, arg1, "flame_001.jpg");
    // TODO Auto-generated constructor stub
}
public void actionImplemented(ActionEvent evt1) {


    JFrame nuFrame = new JFrame();
    nuFrame.setVisible(true);
    nuFrame.setBounds(0, 0, 300, 200);



    // TODO Auto-generated constructor stub
}

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top