هل يمكن أن تكون إضافة قائمة ActionListener قصيرة؟ هل يمكنني إضافة حجج إلى Actionperformed؟

StackOverflow https://stackoverflow.com/questions/2515552

  •  22-09-2019
  •  | 
  •  

سؤال

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

tmp.addActionListener(new ActionListener(){
   @Override
   public void actionPerformed(ActionEvent evt) {
      proposition = proposition + action;
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            updatePropositionPanel();
         }
      });
   }
});

في الواقع ، يختلف كل مستمع عمل عن جميع الآخرين من خلال قيمة action. proposition و updatePropositionPanel هي حقل وطريقة للفصل.

  1. أولاً ، اعتقدت أنه يمكنني جعلها أقصر إذا لم أستخدم الفصول الداخلية. لذلك ، قررت برمجة فئة ActionListener جديدة. لكنني أدركت أن "الاقتراح" في هذه الحالة لن يكون مرئيًا لحالات هذه الفئة.

  2. ثم قررت إضافة طريقة ActionPerformed إلى الفصل الحالي والقيام بذلك: addActionListener(this). لكن مما أدركت أنني لا أعرف كيف أعطي حججًا للطريقة التي يتم تشغيلها.

فكيف يعمل. هل يمكنني إضافة مستمع حركة بطريقة قصيرة وأنيقة؟

إضافة:

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

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

المحلول

يمكنك إنشاء فئة خاصة بك وتمرير البيانات إلى المُنشئ. علي سبيل المثال

public class MyActionListener
{
    private int proposition;
    private MyOtherClass moc;

    public MyActionListener(int proposition, MyOtherClass moc) {
        this.proposition = proposition;
        this.moc = moc;
    }

    public void actionPerformed(ActionEvent evt) {
        proposition += moc.action;
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                moc.updatePropositionPanel();
            }
        });
    }
}

ثم يمكنك إضافته كالمعتاد ، ويمرر أي وسيطات تحبها إلى المُنشئ:

tmp.addActionListener( new MyActionListener(proposition, this) );

نصائح أخرى

تعديل: لقد غيرت الفصل لإظهار البناء باستخدام myouterclass.

هنا يتم رسم بعض التعليمات البرمجية. نأمل أن يصل هذا إلى 1 ، وهو ما سأقوم بتنفيذه.

public class MyOuterClass {
    // member variables for MyOuterClass

    public MyOuterClass() {
        // ...constructor stuff here
    }
    // ...outer class stuff here - methods, etc.

    // The code each place you want to add the listener, somewhere in MyOuterClass
    tmp.addActionListener(new MyActionListener(poposition, action));


    // below outer class stuff, although it can really be most places, I usually put
    // it here - personal style preference.  Swing's classes often put inner
    // classes first

    /**
     * An inner class.
     */
    private MyActionListener implements ActionListener {
        /**
      * Object used here as a filler, replace with appropriate
      * class types
      */
        private Object proposition;
        private Object action;

        private MyActionListener(Object proposition, Object action) {
            this.proposition = proposition;
            this.action = action;
        }
        public void actionPerformed(ActionEvent evt) {
          proposition = proposition + action;
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                updatePropositionPanel();
             }
        }
        /**
         * Setters provided in case you need to change proposition and action.  If not,
         * feel free not to have them and to have final members
         */
        private void setProposition(Object proposition) {
            this.proposition = proposition;
        }
        private void setAction(Object action) {
            this.action = action;
        }
    }
}

تعديل: لإنشاء فئة أخرى كما طلبت في تحريرك ، افعل على النحو الوارد أعلاه ولكن إنشاء فئة أخرى غير خاصة في ملف .java آخر والرمز بعيدا.

كما هو مختلف فقط في قيمة action يمكنك وضع الرمز في طريقة ما. (أيضا Override غير ضروري ، و += مفيد هنا.)

public void setup(
    final AbstractButton button,
    final int action
) { 
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            proposition += action;
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                   updatePropositionPanel();
                }
           });
        }
    });
}

ال invokeLater ربما لا معنى لها حيث ستكون على موضوع إرسال حدث AWT (EDT) على أي حال.

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

إذا أردت أن تكون مخترقًا ، فيمكنك إضافة المستمع في مُنشئ فئة فرعية.

    new ActionHandler(button) { public void action() {
        proposition += action;
        updatePropositionPanel();
    }});

نأمل أن تجعل JDK7 بناء جملة Java لهذا النوع من الأشياء أقل تمسحًا. ومع ذلك ، سوف يكون جافا دائمًا مطوّلة إلى حد ما.

الخيار 1 يعمل إذا قمت بعمل proposition قابلة للتغيير (على سبيل المثال StringBuilder بدلاً من String). الخيار 2 يعمل إذا أعلنت لهم final. وبهذه الطريقة يمكن الوصول إليها/مرئية في الفصل الداخلي.

يمكنك إنشاء فئة MyActionListener منفصلة وتمرير اقتراح القيم والعمل مع المُنشئ. إنه يتراجع عن رمز المصدر.

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

إن الدعوة لإضافة المستمع ستظهر بعد ذلك شيئًا مثل هذا:

tmp.addActionListener(new MyActionListenerSubClass(proposition, action));

سأفترض أن متغيرات اقتراحك وعملك هي سلاسل من أجل هذا المثال. تحديد واجهة PropositionupDater ، وواجهة PropositionPanelupDater ، وحامل اقتراح المتعاون:

public interface PropositionUpdater() {
    public void updateProposition(PropositionHolder holder, String action);
}

public interface PropositionHolder() {
    public String getProposition();

    public void setProposition(String proposition);
}

public interface PropositionPanelUpdater() {
    public void updatePropositionPanel();
}

التنفيذ الافتراضي لمحديثات الاقتراح هو ببساطة:

public class DefaultPropositionUpdater implements PropositionUpdater {
    public void updateProposition(final PropositionHolder holder, final String action) {
        holder.setProposition(holder.getProposition() + action);
    }
}

سأترك الافتراضي لمقترح و PropositionPanelupdater لخيالك ؛)

الآن ، إليك مستمعك الإجراء:

public class PropositionUpdaterActionListener implements ActionListener {
    private PropositionHolder holder;

    private PropositionUpdater updater;

    private PropositionPanelUpdater panelUpdater;

    public PropositionUpdaterActionListener(final PropositionHolder holder, final PropositionUpdater updater, final PropositionPanelUpdater panelUpdater) {
        super();
        this.holder = holder;
        this.updater = updater;
        this.panelUpdater = panelUpdater;
    }

    public void actionPerformed(final ActionEvent evt) {
        //Not sure how you *got* the action, but whatever...
        updater.updateProposition(holder, action);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                panelUpdater.updatePropositionPanel();
            }
        });
    }
}

لم تقل عدد الأزرار التي تتحدث عنها.

إذا كان رقمًا صغيرًا مثل لوحة الشطرنج أو أقل ، فإن نهج @juskt يعد جيدًا.

ومع ذلك ، إذا نظرت إلى شيء أكبر ، فسأستخدم هذا النهج:

public class MyActionListener {
      public void actionPerformed(ActionEvent evt) {
          JComponent c = (JComponent)evt.getSoource();
          int prop = (Integer)c.getclientProperty("PROPOSITION");
          int act = (Integer)c.getclientProperty("ACTION");
          SomeClass obj = c.getclientProperty("UPDATE");
          prop += act;
          // If necessary, clientPut("PROPOSITION", prop);
          SwingUtilities.invokeLater(new    Runnable() {
              public void run() {
                  obj.updatePropositionPanel();
              }
          });
      }
}

لا يحمل مستمع العمل أي حالة. نتيجة لذلك ، يمكن استخدام مثيل واحد منه لجميع الأزرار. لشيء مثل لوحة GO (19x19) ، هذا يعمل على كائن واحد بدلاً من 361.

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