문제

전체 면책 조항 : 저는 CS 학생 이며이 질문은 최근에 지정된 Java 프로그램과 관련이 있습니다. 우리는 콘솔 작업을 수행했지만 GUI 및 SWING 또는 AWT와 함께 일한 것은 이번이 처음입니다. 우리는 텍스트와 다른 색상으로 회전하는 텍스트와 버튼이있는 창을 만든 코드가 주어졌습니다. 그런 다음 대신 색상 용 라디오 버튼을 만들기 위해 프로그램을 수정하라는 요청을 받았습니다. 이는 또한 API를 연구하는 연습을 제공하기위한 것입니다. 나는 이미 과제를 건네 주었고 강사로부터 내 코드를 여기에 게시하도록 허가를 받았습니다.

Java에서 버튼 작업을 구현하는 가장 좋은 방법은 무엇입니까? 약간의 충격을받은 후, 나는 다음과 같은 버튼을 만들었습니다.

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 메소드를 위해 이미 사용하여 사용 방법에 대한 아이디어를 제공했지만 템플릿에 단일 버튼 만 있었기 때문에 여러 버튼을 구현하는 방법이 명확하지 않았습니다. 문자열을 켜고 시도했지만 문자열이 원시 유형이 아니기 때문에 스위치 문에 사용할 수 없다는 것을 빨리 깨달았습니다. 나는 if-else 체인으로 즉흥적으로 만들 수 있었지만 이것이 대신 내가 생각한 것입니다. 우아하지 않은 것처럼 보이며 더 나은 방법이 있어야합니다. 있다면 무엇입니까? 문자열을 켜는 방법이 있습니까? 아니면보다 확장 가능한 방식으로 행동을 선택 하시겠습니까?

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. Mantain 명령 이름에서 색상 인스턴스로의 해시 맵 및지도에서 명령 이름을 찾으십시오.

충분한 접근법 중 하나는 선언하는 것입니다 요소가 당신의 줄과 일치하는 열거 그리고 (str)의 가치를 켜십시오 (링크 된 예제는 상당한 양의 안전으로이를 수행하는 방법을 보여줍니다).

익명의 내부 클래스를 피하는 이유는 아마도 최상의 솔루션 일지라도 클래스에 해당 구성이 아직 없었기 때문일 수 있습니다.

이미 제안 된 바와 같이, 익명의 내부 클래스를 사용하여 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 년 4 월 4 일 : 20)

익명의 내부 클래스 와이 명명 된 내부 클래스 중에서 선택하는 것은 대부분 스타일의 문제이지만,이 버전은 이해하기 쉽고 많은 행동이있을 때 더 명확하다고 생각합니다.

에르. 하나의 메가 클래스에서 관련없는 인터페이스를 구현하지 마십시오. 대신, 무성한 내부 클래스를 사용하십시오. 그것들은 약간의 장점이지만 당신이 원하는 것입니다. 각 이벤트마다 하나를 사용하면 큰 if-else 체인이 필요하지 않습니다. 내부 클래스 내에 충분한 코드를 유지하여 이벤트를 디코딩하고 대상 객체에 맞는 메소드를 호출하는 것이 좋습니다. 또한 내부 클래스를 매개 변수화 할 수 있습니다. 아마도 실제 위젯에 대한 참조를 유지할 필요가 없을 것입니다.

당신의 예에서 당신은 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