메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

자바 스윙: 메뉴와 툴바 - 제 6편

한빛미디어

|

2003-06-19

|

by HANBIT

15,547

저자: Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole, 역 한빛리포터 이상화

본 기사는『Java Swing, 2nd Edition』의 메뉴와 툴바에 대한 내용을 다룬 챕터를 요약한 기사 중 여섯번째 글이다. 이번 시간에는 좀더 복잡한 메뉴 아이템인 라디오 버튼 메뉴와 체크박스 메뉴를 배워보자.


이전기사 보기

선택 가능한(Selectable) 메뉴 아이템들

이전에 우리는 간단하고 텍스트 기반의 라벨을 가지는 일반적인 메뉴 아이템을 다루었다. 하지만 사용자에게 친근한 메뉴는 일반적인 메뉴 이외에도 더 존재한다. 스윙은 체크박스 메뉴 아이템과 라디오 버튼 메뉴 아이템 같이 선택 가능한 두 가지 메뉴 아이템을 제공하고 있다.

JcheckBoxMenuItem 클래스

체크박스 메뉴 아이템들은 JCheckBoxMenuItem 클래스에 의해서 표현된다. 클래스 이름에서 알 수 있듯이 이 객체는 JCheckBox 객체와 비슷하다. 체크박스 메뉴 아이템을 클릭하면 UI에 의해 정의된 메뉴 아이템 라벨 왼쪽에 나타나는 체크마크를 선택할 수 있다. 인접한 객체들 사이에는 어떠한 상호 간섭을 받지 않기 때문에 사용자는 다른 메뉴들의 상태에 영향 받지 않고 어떤 아이템이라도 선택할 수 있다. [표 14-14]는 JCheckBoxMenuItem 컴포넌트의 다이어그램을 보여주고 있다. 그림


[표 14-4] JCheckBoxMenuItem 클래스 다이어그램

속성

[표 14-9]는 JCheckBoxMenuItem 클래스의 속성들을 보여주고 있다. JCheckBoxMenuItemJMenuItem 모델(ButtonModel)과 JMenuItem의 상위 클래스를 상속받는다. 또한 JCheckBoxMenuItem 클래스는 두 개의 부가적인 컴포넌트 속성을 갖는다. state 속성은 메뉴아이템이 현재 체크된 상황이면 true 값을 반환한다. selectedObjects 속성은 현재 체크된 상태의 메뉴아이템 텍스트를 가지고 있는 크기가 1인 Object 배열을 포함하고 있다. 만약 체크된 상태가 아니라면 getSelectedObjects( )null 값을 반환한다. getSelectedObjects( ) 메소드는 AWT의 ItemSelectable 인터페이스와 호환하기 위해 존재하는 메소드이다.

[표 14-9] JCheckBoxMenuItem 속성
속성 데이터 타입 get is set 디폴트 값
accessibleContexto AccessibleContext ·     JCheckBoxMenuItem.
  AccessibleJCheckBoxMenuItem(  )
selectedObjectso Object[ ] ·      
state boolean ·   · false
UIb CheckBoxMenuItemUI ·   · From L&F
UIClassIDo String ·     "CheckBoxMenuItem"

bbound, ooverridden
JmenuItem 클래스를 보려면 [표14-4] 참조.



생성자
public JCheckBoxMenuItem(  )
public JCheckBoxMenuItem(Action action)
public JCheckBoxMenuItem(Icon icon)
public JCheckBoxMenuItem(String text) 
public JCheckBoxMenuItem(String text, Icon icon)
public JCheckBoxMenuItem(String text, boolean checked)
public JCheckBoxMenuItem(String text, Icon icon, boolean checked)
버전 1.3 이후부터 이러한 생성자들은 특화된 작업, 아이콘, 문자열을 가진 JcheckBoxMenuItem을 초기화 한다. 부가적인 boolean 값은 메뉴가 화면에 보여질 때 메뉴 아이템의 체크 여부 나타내는 state 속성을 초기화 한다.

기타
public void updateUI(  )
현재의 UI 매니저와 컴포넌트를 위한 대리자(delegate)를 초기화 하고 L&F을 갱신한다.

체크박스 메뉴 아이템 사용하기

아래는 JCheckBoxMenuItem 클래스를 사용하는 간단한 프로그램이다. 체크박스를 가지고 있다는 점을 제외하면 앞에서 살펴본 JMenu 예제와 유사하다. 상호간섭에 관한 내용은 다음에 다루기로 하고, 이번 예제에서는 밑줄 단축키 보다는 키보드 단축키를 사용하여 코드를 재작성 해보았다. C는 이미 Copy에 할당되어 있으므로 체크박스 메뉴를 위해 M을 사용하였다. [그림 14-15]는 예제를 실행시킨 것이다.
// CheckBoxMenuItemExample.java
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class CheckBoxMenuItemExample extends JPanel {
    public JTextPane pane;
    public JMenuBar menuBar;
    public JToolBar toolBar;

    public CheckBoxMenuItemExample(  ) {
        menuBar = new JMenuBar(  );
        JMenu justifyMenu = new JMenu("Justify");
        ActionListener actionPrinter = new ActionListener(  ) {
            public void actionPerformed(ActionEvent e) {
                try { pane.getStyledDocument(  ).insertString(0 ,
                      "Action ["+e.getActionCommand(  )+"] 
					     performed!\n", null);
                } catch (Exception ex) { ex.printStackTrace(  ); }
            }
        };
        JCheckBoxMenuItem leftJustify = new
               JCheckBoxMenuItem("Left", new ImageIcon("left.gif"));
        leftJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        leftJustify.setAccelerator(KeyStroke.getKeyStroke("L",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        leftJustify.addActionListener(actionPrinter);
        JCheckBoxMenuItem rightJustify = new
               JCheckBoxMenuItem("Right", new ImageIcon("right.gif"));
        rightJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        rightJustify.setAccelerator(KeyStroke.getKeyStroke("R",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        rightJustify.addActionListener(actionPrinter);
        JCheckBoxMenuItem centerJustify = new
               JCheckBoxMenuItem("Center", new ImageIcon("center.gif"));
        centerJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        centerJustify.setAccelerator(KeyStroke.getKeyStroke("M",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        centerJustify.addActionListener(actionPrinter);
        JCheckBoxMenuItem fullJustify = new
               JCheckBoxMenuItem("Full", new ImageIcon("full.gif"));
        fullJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        fullJustify.setAccelerator(KeyStroke.getKeyStroke("F",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        fullJustify.addActionListener(actionPrinter);

        justifyMenu.add(leftJustify);
        justifyMenu.add(rightJustify);
        justifyMenu.add(centerJustify);
        justifyMenu.add(fullJustify);

        menuBar.add(justifyMenu);
        menuBar.setBorder(new BevelBorder(BevelBorder.RAISED));

    }
    public static void main(String s[ ]) {
        CheckBoxMenuItemExample example = new CheckBoxMenuItemExample(  );
        example.pane = new JTextPane(  );
        example.pane.setPreferredSize(new Dimension(250, 250));
        example.pane.setBorder(new BevelBorder(BevelBorder.LOWERED));

        JFrame frame = new JFrame("Menu Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(example.menuBar);
        frame.getContentPane(  ).add(example.pane, BorderLayout.CENTER);
        frame.pack(  );
        frame.setVisible(true);
    }
}


[그림 14-15] 체크박스 메뉴 아이템 예제


Java Swing, 2nd Edition

참고 도서

Java Swing, 2nd Edition
David Wood, Marc Loy, James Elliott, Brian Cole, Robert Eckstein


JradioButtonMenuItem 클래스

스윙은 JradioButtonMenuItem 클래스를 가지고 라디오 버튼 메뉴 아이템을 실행 시킬 수 있다. 클래스 이름에서 알 수 있듯이 JRadioButton 클래스의 성질을 공유하며 상호간섭이 가능한 선택 그룹을 나타낼 수 있다. († 역자 주 : 그룹으로 묶인 라디오 버튼은 한번에 하나의 선택만 가능하다. 체크버튼과 달리 라디오 버튼은 인접한 객체 상호간 간섭이 가능하다.) 보통 몇몇 L&F에서는 선택 가능한 아이템 왼쪽에 원형의 "버튼"을 보여 준다.

팁: L&F는 체크박스와 라디오 버튼 아이템의 차이점을 시각적으로 보여준다. 그렇긴 하지만 그 차이는 이해하기 어렵고 사용자에게 친숙하지 않을 수 있다. 따라서 메뉴 안에서 아이템들이 그룹화 되어있다는 것을 나타내기 위해 다른 시각적인 표현과 구분자를 사용하는 것도 좋은 방법이 될 것이다.

또한 라디오 버튼 메뉴 자체로는 상호간섭이 불가능하기 때문에 사용자가 단일 선택 만을 할 수 있도록 ButtonGroup 객체를 사용할 수 있다. [그림 14-16]는 JRadioButtonMenuItem 컴포넌트의 클래스 다이어그램을 보여주고 있다.


[그림 14-16] 라디오 버튼 메뉴 아이템 클래스 다이어그램

속성

[표 14-10]는 클래스의 속성을 보여주고 있다. JCheckBoxMenuItem과는 다르게 현재 선택된 메뉴 아이템의 상태를 나타내는 state 속성은 없다. 대신 ButtonGroup과의 결합을 통해 getSelected( ) 메소드를 가지고 특정한 객체를 참조할 수 있다.

[표14-10] JRadioButtonMenuItem 속성들
속성 데이터 타입 get is set 디폴트 값
accessibleContexto AccessibleContext ·     JRadioButtonMenuItem.
  AccessibleJRadioButtonMenu-Item(  )
UIb RadioButtonMenuItemUI ·   · From L&F
UIClassIDo String ·     "CheckBoxMenuItem"

bbound, ooverridden
JmenuItem 클래스를 보려면 [표14-4] 참조.



생성자
public JRadioButtonMenuItem(  )
public JRadioButtonMenuItem(Action action)
public JRadioButtonMenuItem(Icon icon)
public JRadioButtonMenuItem(String text)
public JRadioButtonMenuItem(String text, Icon icon)
버전 1.3 이후 이러한 생성자들은 특화된 작업, 아이콘, 문자열을 가진 JRadioButtonMenuItem을 초기화 한다.

기타
public void updateUI(  )
현재의 UI 매니저와 컴포넌트를 위한 대리자(delegate)를 초기화 하고 L&F을 갱신한다.

상호 간섭 설정하기

다음 프로그램은 라디오 버튼 메뉴 아이템의 상호 간섭적인 성질을 어떻게 실행시키는지 보여준다.
//  RadioButtonMenuItemExample.java
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class RadioButtonMenuItemExample extends JPanel {

    public JTextPane pane;
    public JMenuBar menuBar;
    public JToolBar toolBar;

    public RadioButtonMenuItemExample(  ) {
        menuBar = new JMenuBar(  );
        JMenu justifyMenu = new JMenu("Justify");
        ActionListener actionPrinter = new ActionListener(  ) {
            public void actionPerformed(ActionEvent e) {
                try { pane.getStyledDocument(  ).insertString(0 ,
                      "Action ["+e.getActionCommand(  )+"] 
					     performed!\n", null);
                } catch (Exception ex) { ex.printStackTrace(  ); }
            }
        };
        JRadioButtonMenuItem leftJustify = new
               JRadioButtonMenuItem("Left", new ImageIcon("left.gif"));
        leftJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        leftJustify.setAccelerator(KeyStroke.getKeyStroke("L",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        leftJustify.addActionListener(actionPrinter);
        JRadioButtonMenuItem rightJustify = new
               JRadioButtonMenuItem("Right", new ImageIcon("right.gif"));
        rightJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        rightJustify.setAccelerator(KeyStroke.getKeyStroke("R",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        rightJustify.addActionListener(actionPrinter);
        JRadioButtonMenuItem centerJustify = new
               JRadioButtonMenuItem("Center", new ImageIcon("center.gif"));
        centerJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        centerJustify.setAccelerator(KeyStroke.getKeyStroke("M",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        centerJustify.addActionListener(actionPrinter);
        JRadioButtonMenuItem fullJustify = new
               JRadioButtonMenuItem("Full", new ImageIcon("full.gif"));
        fullJustify.setHorizontalTextPosition(JMenuItem.RIGHT);
        fullJustify.setAccelerator(KeyStroke.getKeyStroke("F",
                        Toolkit.getDefaultToolkit(  ).getMenuShortcutKeyMask(  )));
        fullJustify.addActionListener(actionPrinter);

        ButtonGroup group = new ButtonGroup(  );
        group.add(leftJustify);
        group.add(rightJustify);
        group.add(centerJustify);
        group.add(fullJustify);

        justifyMenu.add(leftJustify);
        justifyMenu.add(rightJustify);
        justifyMenu.add(centerJustify);
        justifyMenu.add(fullJustify);

        menuBar.add(justifyMenu);
        menuBar.setBorder(new BevelBorder(BevelBorder.RAISED));
    }
    public static void main(String s[ ]) {
        RadioButtonMenuItemExample example = new
                                        RadioButtonMenuItemExample(  );
        example.pane = new JTextPane(  );
        example.pane.setPreferredSize(new Dimension(250, 250));
        example.pane.setBorder(new BevelBorder(BevelBorder.LOWERED));

        JFrame frame = new JFrame("Menu Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setJMenuBar(example.menuBar);
        frame.getContentPane(  ).add(example.pane, BorderLayout.CENTER);
        frame.pack(  );
        frame.setVisible(true);
    }
}
[그림 14-17]은 예제를 실행시킨 것이다. JradioButtonMenuItems의 상호 간섭을 보여주기 위해 ButtonGroup 객체를 사용했다. 하나의 메뉴를 선택하면 다른 메뉴의 선택이 해제된다.


[그림 14-17] 라디오 버튼 메뉴 아이템 예제

JSeparator 클래스

JMenuJPopupMenu는 메뉴에 구분자를 추가하기 위한 메소드를 가지고 있다. 이것을 위해 각 클래스는 JSeparator 객체를 인스턴스화 시켜야 하며 메뉴 안에서 구분자의 위치를 정해줘야 한다. JSeparatorJComponent를 상속 받고 있기 때문에 메뉴 외부에서 컴포넌트로 존재하며 다른 스윙 컴포넌트처럼 컨테이너 내부에 위치할 수 있다. JSeparator는 메뉴 아이템의 논리적인 그룹 사이를 구분하는 간단한 컴포넌트이다. 어떤 L&F에서는 메뉴의 가로 크기 정도의 수평선을 보여주며 다른 L&F에서는 메뉴 아이템 사이에 빈칸만을 삽입하는 경우도 있다.

속성

[표14-11]은 JSeparator의 속성을 보여주고 있다.

[표14-11] JSeparator 속성
속성 데이터 타입 get is set 디폴트 값
accessibleContexto AccessibleContext ·     JSeparator.accessibleJSeparator(  )
orientation int ·   · SwingConstants.HORIZONTAL
UIb SeparatorUI ·   · From L&F
UIClassIDo String ·     "SeparatorUI"

bbound, ooverridden
Jcomponent 클래스를 보려면 [Table 3-6] 참조



생성자
JSeparator(  )
JSeparator(int orientation)
구분자를 생성한다. 기본적으로 구분자는 수평이지만 SwingConstants.HORIZONTAL 또는 SwingConstants.VERTICAL을 통해 방향을 조정할 수 있다.

기타
public void updateUI(  )
현재의 UI 매니저와 컴포넌트를 위한 대리자(delegate)를 초기화 하고 L&F을 갱신한다.

메뉴 외부에서 구분자 사용하기

지금까지 우리는 메뉴 아이템을 논리적으로 그룹화 하기 위해 구분자를 사용하였다. 그러나 구분자 자체가 컴포넌트이기 때문에 다양한 작업에 사용될 수도 있다. 다음 프로그램은 버튼간에 구분자를 추가하는 예제이다.
// SeparatorExample.java
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class SeparatorExample extends JPanel {

    public SeparatorExample(  ) {
        super(true);

        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        Box box1 = new Box(BoxLayout.X_AXIS);
        Box box2 = new Box(BoxLayout.X_AXIS);
        Box box3 = new Box(BoxLayout.X_AXIS);

        box1.add(new JButton("Press Me"));
        box1.add(new JButton("No Me!"));
        box1.add(new JButton("Ignore Them!"));
        box2.add(new JSeparator(  ));
        box3.add(new JButton("I"m the Button!"));
        box3.add(new JButton("It"s me!"));
        box3.add(new JButton("Go Away!"));

        add(box1);
        add(box2);
        add(box3);
    }
    public static void main(String s[ ]) {

        SeparatorExample example = new SeparatorExample(  );

        JFrame frame = new JFrame("Separator Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(example);
        frame.pack(  );
        frame.setVisible(true);
    }
}
아래 [그림 14-18]은 예제를 실행시킨 것이다. 구분자가 보이지 않는 플랫폼상에서는 이러한 방법으로는 구분자를 나타내기가 까다로울 뿐만 아니라 쉽지도 않다. (심지어 본 예제에서도 구분자는 잘 보이지 않는다.)


[그림 14-18] 두개의 버튼 그룹사이에 독립적인 구분자

MenuElement 인터페이스

이전 예제들에서 살펴본 것과 같이 스윙 메뉴의 장점은 메뉴에 문자열 이외의 것을 사용할 수 있다는 것이다. 아이콘 뿐만 아니라 자바 컴포넌트를 상속 또는 새롭게 개발함으로써 메뉴 아이템을 확장할 수 있다. 새로운 메뉴 아이템은 MenuElement 인터페이스를 상속 받으면 된다. 스윙은 다양한 작업들이 발생할 때 스윙의 내부 MenuSelectionManager에 의해서 호출되는 5개의 메소드를 가지고 있다.

왜 이런 것이 필요할까? 일반적인 Edit 메뉴에 포함되어 있는 Paste 아이템을 살펴보자. 사용자는 Edit 메뉴를 선택하고 Paste 메뉴 아이템으로 마우스를 가져가게 된다. 선택된 메뉴는 화면이 반전되거나 다른 배경색을 가진다. 이것은 사용자에게 Paste 버튼을 선택할 수 있다는 것을 의미한다. 마우스를 메뉴 아이템으로부터 다른 방향으로 이동한다면 다시 원래의 배경색으로 변한다. 그러나 배경색을 반전시키는 것이 아니라 아이템 문자열을 강조하고 싶을 때는 어떻게 할 것인가? 마우스가 해당 메뉴로 이동하면 다른 아이콘 이미지로 대체하게 변형시키고 싶을 때는 어떻게 할 것인가? 인터페이스의 메소드를 상속함으로써 메뉴 아이템은 다양한 행동을 수행 할 수 있다.

메소드
public void processMouseEvent(MouseEvent event,MenuElement path[ ], 
     MenuSelectionManager manager)
이 메소드는 마우스에 의해 발생된 이벤트를 처리한다. MouseEvent 이외에 추가적으로 선택된 메뉴 요소의 현재 경로 뿐만 아니라 현재 메뉴 매니저의 참조자를 제공한다. 대부분의 작업에 이 메소드는 필수이다.
public void processKeyEvent(KeyEvent event, MenuElement path[ ], 
     MenuSelectionManager manager)
이 메소드는 키보드에 의해 발생된 이벤트를 처리한다. MouseEvent 이외에 추가적으로 선택된 메뉴 요소의 현재 경로 뿐만 아니라 현재 메뉴 매니저의 참조자를 제공한다. 대부분의 작업에 이 메소드는 필수적이다.
public void menuSelectionChanged(boolean isIncluded)
메뉴 요소가 현재 작업 메뉴에 추가되거나 제거되었을 때 호출된다.
public MenuElement[ ] getSubElements(  )
현재 작업하는 MenuElement를 위한 하위요소의 배열을 반환한다. 특정 메뉴 요소가 하위 요소를 가질 때 필요한 메소드이다.
public Component getComponent(  )
메뉴 아이템을 화면에 나타내주는 컴포넌트의 참조자를 반환한다.

메뉴 요소 속에 임의의 컴포넌트 만들기

대부분의 스윙 컴포넌트를 메뉴 요소로 변환시키거나 메뉴에 포함하는 것은 쉽다. 아래 예제는 JSlider를 팝업 메뉴에 포함시키고 그것을 현재 컴포넌트를 위한 이면의 제어 작업으로 사용할 수 있다.

//  MenuElementExample.java
//
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;

public class MenuElementExample extends JPanel {

    public JPopupMenu popup;
    SliderMenuItem slider;
    int theValue = 0;

    public MenuElementExample(  ) {

        popup = new JPopupMenu(  );
        slider = new SliderMenuItem(  );

        popup.add(slider);
        popup.add(new JSeparator(  ));

        JMenuItem ticks = new JCheckBoxMenuItem("Slider Tick Marks");
        ticks.addActionListener(new ActionListener(  ) {
            public void actionPerformed(ActionEvent event) {
                slider.setPaintTicks(!slider.getPaintTicks(  ));
            }
        });
        JMenuItem labels = new JCheckBoxMenuItem("Slider Labels");
        labels.addActionListener(new ActionListener(  ) {
            public void actionPerformed(ActionEvent event) {
                slider.setPaintLabels(!slider.getPaintLabels(  ));
            }
        });
        popup.add(ticks);
        popup.add(labels);
        popup.addPopupMenuListener(new PopupPrintListener(  ));

        addMouseListener(new MousePopupListener(  ));
    }
    // 내부 클래스는 마우스 이벤트가 팝업 트리거 인지 조사한다.
class MousePopupListener extends MouseAdapter {
        public void mousePressed(MouseEvent e) { checkPopup(e); }
        public void mouseClicked(MouseEvent e) { checkPopup(e); }
        public void mouseReleased(MouseEvent e) { checkPopup(e); }
        private void checkPopup(MouseEvent e) {
            if (e.isPopupTrigger(  )) {
                popup.show(MenuElementExample.this, e.getX(  ), e.getY(  ));
            }
        }
    }
    // 내부 클래스는 팝업 이벤트에 대응하는 정보를 출력한다.
    class PopupPrintListener implements PopupMenuListener {
        public void popupMenuWillBecomeVisible(PopupMenuEvent e) { }
        public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
            theValue = slider.getValue(  );
            System.out.println("The value is now " + theValue);
        }
        public void popupMenuCanceled(PopupMenuEvent e) {
            System.out.println("Popup menu is hidden!");
        }
    }
  
    public static void main(String s[ ]) {
        JFrame frame = new JFrame("Menu Element Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new MenuElementExample(  ));
        frame.setSize(300, 300);
        frame.setVisible(true);
    }
    // 내부 클래스는 슬라이더 메뉴 아이템을 정의한다.
    class SliderMenuItem extends JSlider implements MenuElement {

        public SliderMenuItem(  ) {
            setBorder(new CompoundBorder(new TitledBorder("Control"),
                                  new EmptyBorder(10, 10, 10, 10)));

            setMajorTickSpacing(20);
            setMinorTickSpacing(10);
        }
        public void processMouseEvent(MouseEvent e, MenuElement path[ ],
                                      MenuSelectionManager manager) {}
        public void processKeyEvent(KeyEvent e, MenuElement path[ ],
                                    MenuSelectionManager manager) {}
        public void menuSelectionChanged(boolean isIncluded) {}
        public MenuElement[ ] getSubElements(  ) {return new MenuElement[0];}
        public Component getComponent(  ) {return this;}
    }
}
이전 팝업 예제 PopupMenuExample와 같이 MouseListener를 상속받고 팝업 출력 여부를 보기 위해 입력되는 마우스 이벤트를 검사한다. 내부 클래스 SliderMenuItemMenuElement 인터페이스를 상속 받았다는 것이 이번 예제의 핵심이다. 이러한 방법은 쉬운 편이다. 메뉴 슬라이더는 하위 요소를 가지지 않을 뿐더러 선택의 개념도 없고 마우스나 키보드 이벤트에 대해서 특별한 작업을 수행하지도 않기 때문이다.

예제를 실행시키면 [그림 14-19]와 같다. 예제는 JSlider 객체, 하나의 구분자, 슬라이더의 상태를 조정하기 위한 두 개의 JCheckBoxMenuItem 객체를 가지고 있다. 또한 슬라이더는 타이틀 있는 경계선으로 둘러싸여 있다. 팝업을 없애거나 슬라이더를 움직이면 현재 슬라이더의 값을 표준 출력창(도스창)으로 출력한다. 이러한 방법으로 팝업 메뉴를 통해 어느 작업이라도 할 수 있다. 물론 이러한 것들이 사용자에게는 혼란스러울 수 있기 때문에 주의해서 사용해야 한다.


[그림 14-19] 두개의 L&F에서 팝업 메뉴 요소 같은 JSlider

다음 기사에서는 툴바에 대해 살펴볼 예정이다.
TAG :
댓글 입력
자료실

최근 본 책0