سؤال

كامل تنويه:أنا CS الطالب ، هذا السؤال هو الذي عين مؤخرا برنامج جافا البرمجة الشيئية.على الرغم من أننا قد فعلت بعض تحكم الاشياء, هذه هي المرة الأولى لقد عملنا مع واجهة المستخدم الرسومية البديل أو Awt.لقد أعطيت بعض التعليمات البرمجية التي تم إنشاؤها نافذة مع بعض نص و زر تدوير من خلال ألوان مختلفة لهذا النص.كنا ثم طلب تعديل برنامج لإنشاء أزرار الراديو الألوان بدلا من ذلك—كان هذا المقصود أيضا أن تعطينا ممارسة البحث API.لقد سلمت بالفعل في مهمتي وحصل على تصريح من مدرب إلى آخر قانون بلدي هنا.

ما هي أفضل طريقة لتنفيذ الإجراءات زر في جافا ؟ بعد بعض تافه حولها ، أنا خلق الأزرار مثل هذا:

class HelloComponent3 extends JComponent
    implements MouseMotionListener, ActionListener
{
    int messageX = 75, messageY= 175;

    String theMessage;
    String redString = "red", blueString = "blue", greenString = "green";
    String magentaString = "magenta", blackString = "black", resetString = "reset";

    JButton resetButton;
    JRadioButton redButton, blueButton, greenButton, magentaButton, blackButton;
    ButtonGroup colorButtons;

    public HelloComponent3(String message) {

    theMessage = message;

    //intialize the reset button
    resetButton = new JButton("Reset");
    resetButton.setActionCommand(resetString);
    resetButton.addActionListener(this);

    //intialize our radio buttons with actions and labels
    redButton = new JRadioButton("Red");
    redButton.setActionCommand(redString);
    ...

وأضاف عمل المستمعين...

redButton.addActionListener(this);
blueButton.addActionListener(this);
...

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

public void actionPerformed(ActionEvent e){

    if (e.getActionCommand().equals(resetString)) {
        messageX = 75; messageY = 175;
        setForeground(Color.black);
        blackButton.setSelected(true);
        repaint();
        return;
    }

    if ( e.getActionCommand().equals(redString) ) {
        setForeground(Color.red);
        repaint();
        return;
    }

    if ( e.getActionCommand().equals(blueString) ) {
        setForeground(Color.blue);
        repaint();
        return;
    }

    if ( e.getActionCommand().equals(greenString) ) {
        setForeground(Color.green);
        repaint();
        return;
    }

    if ( e.getActionCommand().equals(magentaString) ) {
        setForeground(Color.magenta);
        repaint();
        return;
    }

    if ( e.getActionCommand().equals(blackString) ) {
        setForeground(Color.black);
        repaint();
        return;
    }
}
هل كانت مفيدة؟

المحلول

وبدلا من كتابة هذا:

resetButton.addActionListener(this);

ويمكنك أيضا أن أكتب هذا:

resetButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
        resetButtonActionPerformed(evt);
    }
});

وبدلا من كتابة واحد actionPerformed كبير () لجميع الإجراءات، يمكنك (ولها ثم إلى) أكتب هذا:

public void resetButtonActionPerformed(ActionEvent evt) {
    messageX = 75; messageY = 175;
    setForeground(Color.black);
    blackButton.setSelected(true);
    repaint();
}

وأنا لا أعرف إذا كان هذا هو الحل الأكثر أناقة، ولكن على الأقل لم يعد لديك بهذا الحجم إذا بناء.

نصائح أخرى

اثنين النهج البديلة:

  1. إنشاء فئة جديدة التي تطبق عمل واجهة لها لون الميدانية و actionPerformed الأسلوب الذي يحدد لون
  2. المحافظة على HashMap من أسماء الأوامر إلى اللون الحالات والبحث عن اسم الأمر في الخريطة

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

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

وكما اقترح بالفعل، يمكنك استخدام الطبقات الداخلية مجهول لتنفيذ واجهة ActionListener. وكبديل لذلك، لم يكن لديك لاستخدام الطبقات الداخلية مجهول، ولكن يمكنك استخدام فئة متداخلة بسيطة بدلا من ذلك:

resetButton = new JButton(new ResetAction());
redButton = new JButton(new ColorAction("Red", Color.red));

وبعد ذلك ...

private class ResetAction extends AbstractAction {
    public ResetAction() {
        super("Reset");
    }

    public void actionPerformed(ActionEvent e) {
        messageX = 75; messageY = 175;
        setForeground(Color.black);
        blackButton.setSelected(true);
        repaint();
    }
}

private class ResetAction extends AbstractAction {
    private Color color;

    public ColorAction(String title, Color color) {
        super(title);
        this.color = color;
    }

    public void actionPerformed(ActionEvent e) {
        setForeground(color);
        repaint();
    }
}

لماذا هذا النهج - أو أي نهج تنطوي على الطبقات الداخلية - أفضل من تنفيذ ActionListener في الطبقة الخارجية رؤية "أنماط تصميم":

و"صالح" تكوين الكائن 'على' الطبقة الميراث ". (عصابة الأربعة 1995: 20)

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

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

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

وهكذا على سبيل المثال:

   addColorButton("Green" , Color.GREEN );
   addColorButton("Red"   , Color.RED   );
   addColorButton("Yellow", Color.YELLOW);
   addColorButton("Blue"  , Color.BLUE  );
   ...

private void addColorButton(String label, Color color) {
    JRadioButton button = new JRadioButton(label);
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent event) {
            target.setForeground(color);
            target.repaint();
        } 
    });
    colorGroup.add(button);
    panel.add(button);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top