Welcome to My World (www.dgmayor.com)

소프트웨어 (과거)/자바 GUI & C# 등...

14. 자바 JMenu 사용법

dgmayor 2022. 2. 16. 14:25
728x90
메뉴 만들기
 
  • JMenuBar

이곳에 메뉴항목을 추가할 수 있다.

 

  • JMenu

메뉴바에 추가가능한 메뉴 항목

 

  • JMenuItem

메뉴의 아이템을 구현하기 위한 클래스

 

 

예제소스

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
 
public class test extends JFrame {
 
    test(){
        super("swing test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300,200);
        
        //메뉴바 생성
        JMenuBar mb = new JMenuBar();
        
        //메뉴항목 추가
        JMenu jm = new JMenu("메뉴1");
 
        //메뉴의 아이템 추가
        jm.add(new JMenuItem("빨강"));
        jm.add(new JMenuItem("파랑"));
        jm.addSeparator();    //메뉴 아이템의 구분선 생성
        jm.add(new JMenuItem("노랑"));
        
        
        //메뉴바에 메뉴 추가
        mb.add(jm);
        mb.add(new JMenu("초록"));
        
        //프레임에 메뉴바 붙이기
        setJMenuBar(mb);
        
        
        setVisible(true);
    }
    
    public static void main(String[] args) {
        
        new test();
 
    }
 
}
 
cs

 

 

 

Action 이벤트 달기

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
 
public class test extends JFrame {
 
    JLabel jl = new JLabel("test");
    
    
    test(){
        super("swing test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300,200);
        
        //메뉴바 생성
        JMenuBar mb = new JMenuBar();
        
        //메뉴 생성
        JMenu jm = new JMenu("메뉴1");
        
        //메뉴 아이템 생성
        JMenuItem mi1 = new JMenuItem("빨강");
        JMenuItem mi2 = new JMenuItem("파랑");
        JMenuItem mi3 = new JMenuItem("노랑");
 
        //이벤트 리스너 달기
        mi1.addActionListener(new MenuActionListener());
        mi2.addActionListener(new MenuActionListener());
        mi3.addActionListener(new MenuActionListener());
        
        //메뉴에 아이템 추가
        jm.add(mi1);
        jm.addSeparator();    //메뉴 아이템의 구분선 생성
        jm.add(mi2);
        jm.add(mi3);
        
        
        //메뉴바에 메뉴 추가
        mb.add(jm);
        mb.add(new JMenu("메뉴2"));
        
        
        //프레임에 메뉴바 붙이기
        setJMenuBar(mb);
        
        //라벨 설정
        jl.setSize(200200);
        jl.setFont(new Font("Revie",Font.ITALIC,30));
        add(jl);
        
        setVisible(true);
    }
    
    // 메뉴 클릭시 사용할 리스너 클래스 작성
    class MenuActionListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
            //선택된 메뉴아이템의 문자열 가져오기
            String s = e.getActionCommand();
            if(s == "빨강") {
                jl.setForeground(Color.red);
            }else if(s == "파랑") {
                jl.setForeground(Color.blue);
            }else if(s == "노랑") {
                jl.setForeground(Color.yellow);
            }
        }
    }
    
    public static void main(String[] args) {
        
        new test();
 
    }
 
}
 

 

아마... static 전역 사용 대신... 값을 읽어 와서 하는게 더 효율 적인거 같다.

 

 

그리고 계속하여 메뉴가 묻혀 버리는 경우가 있었다.

계속 고민하다 보니 super.paint(g)를 사용 하지 않았던 것이 원인이었다.

겨우 해결...

 

이 외에 메뉴 표시 정렬 (과제 1 : 써본 적 없음)을 하려고 하여 보니..... 답이 스택 오버 플로우에도 없고.... 있어도 메뉴를 상속 받아서 아예 재구현을 하는 수준이라서..... 메뉴 대신 버튼을 새로 짜야 하나 생각하고 있었는데...... 

독에 아이콘을 넣는 기능 (과제 2 : 써본 적 없음)이 있다고 한다. 더 찾아 봐야 겠다.

어쨌든 JMenu도 완전히 구현된 기능은 아닌거 같고.... 싫으면 있을지도 모를 자바 신버전을 써야 할 거 같은데....

하다가 영 안 되면 나중에 재상속 구현 (과제 3 : 써본 적 없음 )을 생각해 봐야겠다.

어쨌든 밑에는 새로 찾은 참고 자료이다.

 

 

 JMenuBar

 

 

 

메뉴는 공간을 절약함과 동시에 사용자에게 여러 가지 옵션 중에서 하나를 선택하게 하는 컴포넌트이다.

 

다른 컴포넌트와 달리 컨테이너 안에 배치되지 않는다. , 항상 맨 위에 고정적인 자리를 가진다.

 

메뉴바는 프레임에만 부착될 수 있다. 패널은 부착불가.

 

메뉴는 메뉴바에 나타나거나 팝업 메뉴로만 나타난다.

 

- 메뉴바에 메뉴를 나열하고, 메뉴바에 나열된 메뉴들에서 각 메뉴 항목을 가진다.

 

- 메뉴 항목에는 텍스트뿐만 아니라 이미지도 올 수 있고 체크 박스도 올 수 있다. 또한, 폰트나 색상도 변경 가능하다.

 

팝업 메뉴란 사용자가 팝업이 가능한 컴포넌트 위에서 마우스 우클릭을 할 때 등장한다.

 

메뉴는 JAbstractButton 클래스를 상속하고 있으므로 일종의 버튼이라 보면 된다. 따라서 누르면 이벤트가 발생한다.

 

메뉴바는 JMenuBar 객체, 메뉴는 JMenu 객체, 메뉴 항목은 JMenuItem 객체로 만들어진다.

 

- 팝업메뉴는 JPopupMenu라는 객체를, 체크박스 메뉴항목은 JCheckboxMenuItem 객체에 의해 표현된다.

 

- Simple Example

 

...

JFrame frame = new JFrame(“메뉴바 예제”);

 

JMenuBar menuBar; //메뉴바 선언

JMenu menu; //메뉴 선언

JMenuItem menuItem; //메뉴 항목 선언

 

menuBar = new JMenuBar(); //메뉴바 초기화

 

menu = new JMenu(“메뉴1”);

menuBar.add(menu);

 

menuItem = new JMenuItem(“메뉴항목1”); //메뉴항목 선언

//menuItem = new JMenuItem(“메뉴항목1”, KeyEvent.VK_T); ->키보드 단축키 설정 가능

menu.add(menuItem); //메뉴에 메뉴항목 추가

 

frame.setJmenuBar(menuBar); //프레임에 메뉴바 설정

...

 

각 메뉴 항목마다 단축키를 설정하려면 setMenuShortCut 메소드를 불러오면 된다.

 

이벤트 처리 : 메뉴항목(JMenuItem)을 눌렀을 때 발생하는 이벤트를 처리하기 위해 ActionListener 인터페이스를 구현한다.

 

키보드와의 관계 : 메뉴는 기억키(menmontcs)와 가속키(accelerators)의 두 가지 종류의 키보드 선택을 지원한다. 기억키는 모든 사용자를 위한 것이고, 가속키는 고급 사용자를 위한 것이라고 생각하면 된다.

 

기억키는 setMnemonic() 메소드를가속키는 setAccelerator() 메소드를 사용한다.

  • 기억키 : 키보드를 사용하여 이미 표시되어 있는 메뉴 계층을 둘러보는데 이용된다. 주로 메뉴에 단축키를 설정하여 Alt를 누르면 첫 번째 메뉴가 선택되게 한다.

menuItem.setMnemonic(KeyEvent.VK_T);

  • 가속키 : 메뉴 계층 구조를 통하지 않고 직접 메뉴 항목을 선택할 수 있다. , 메뉴 항목이 선택되는 키들의 조합이다. 예를 들어 Alt + 1을 눌렀을 때 Alt 단축키를 가진 메뉴의 서브 메뉴 항목의 첫 번째를 선택하게 된다. 단말 메뉴 항목만이 가속키를 가질 수 있다.

 menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_t, ActionEvent_ALT_MASK));

 

 

예제

public class MenuTest extends JFrame implements ActionListener, ItemListener {
	
	//FIELDS
	private JMenuBar menuBar = new JMenuBar();
	private JMenu firstMenu, secondMenu, submenu;
	private JMenuItem menuItem1, menuItem2;
	private JMenuItem subMenuItem1, subMenuItem2;
	private ButtonGroup group = new ButtonGroup();
	private JRadioButtonMenuItem rbMenuItem1, rbMenuItem2;
	private JCheckBoxMenuItem cbMenuItem1, cbMenuItem2;
	
	MenuTest() {
	
		//첫번째 메뉴 초기화
		firstMenu = new JMenu("first menu");
		firstMenu.setMnemonic(KeyEvent.VK_F); //단축키 설정
		menuBar.add(firstMenu);
		
		//메뉴 항목 생성
		menuItem1 = new JMenuItem("menu item 1", KeyEvent.VK_1);
		menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.ALT_MASK));
		menuItem1.addActionListener(this); //리스너 설정해야 이벤트 처리 가능함
		firstMenu.add(menuItem1); //메뉴항목을 첫번째 메뉴에 등록
		
		ImageIcon icon = new ImageIcon("example_icon.png");
		menuItem2 = new JMenuItem("menu item 2", icon); //이미지 등록
		menuItem2.addActionListener(this);
		menu.add(menuItem2);
		
		//라디오 버튼 메뉴 항목 생성
		firstMenu.addSeparator(); // 구분자 생성
		
		rbMenuItem1 = new JRadioButtonMenuItem("radio button item 1");
		rbMenuItem1.setSelected(true); //선택 되어있도록 설정
		group.add(rbMenuItem1); //버튼 그룹에 추가
		firstMenu.add(rbMenuItem1); //그룹에 추가하는 것과 메뉴에 추가하는 것은 별도이다.
		
		rbMenuItem2 = new JRadioButtonMenuItem("radio button item 2");
		group.add(rbMenuItem2);
		firstMenu.add(rbMenuItem2);
		
		//체크 박스 메뉴 항목 생성
		firstMenu.addSeparator();
		cbMenuItem1 = new JCheckBoxMenuItem("check box item 1");
		cbMenuItem1.addItemListener(this); //체크박스는 아이템 이벤트가 발생함 (액션 이벤트와는 별도 처리)
		firstMenu.add(cbMenuItem1);
		
		cbMenuItem2 = new JCheckBoxMenuItem("check box item 2");
		cbMenuItem2.addItemListener(this);
		firstMenu.add(cbMenuItem2);
		
		//서브 메뉴 생성
		submenu.addSeparator();
		submenu = new JMenu("sub menu");
		submenu.setMnemonic(KeyEvent.VK_S); //단축키 설정
		
		subMenuItem1 = new JMenuItem("sub menu item 1");
		subMenuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
		submenu.add(subMenuItem1);
		
		subMenuItem2 = new JMenuItem("sub menu item 2");
		subMenuItem2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
		submenu.add(subMenuItem2);
		
		menu.add(submenu);
		
		//두번째 메뉴 초기화
		secondMenu = new JMenu("second menu");
		secondMenu.addActionListener(this);
		menu.setMnemonic(KeyEvent.VK_S);
		menuBar.add(menu);
		
		//프레임에 메뉴바 추가하기
		setJMenuBar(menuBar);
		setVisible(true);
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == menuItem1) {
			System.out.println("This is the menu item 1.");
		}else if (e.getSource() == menuItem2) {
			System.out.println("This is the menu item 2.");
		}
	}
	
	@Override
	public void itemStatedChanged(ItemEvent e) {
		if (e.getSource() == cbMenuItem1) {
			System.out.println("check box item 1");
		else (e.getSource() == cbMenuItem2) {
			System.out.println("check box item 2");
		}
	}
	
	public static void main(String[] args) {
		MenuTest frame = new MenuTest();
		f.setSize(500, 500);
		f.setVisible(true);
	}
}

 

 
계속 고민하다 방법을 찾아 내었는데....
m1.setBorder(javax.swing.BorderFactory.createEmptyBorder(30, 30, 30, 30)); 를 사용하면 해결이 된다.
스택 오버 플로에서도 답을 찾기 힘들어서.... 어떻게 할까 고민하다가 넷빈즈의 gui 툴이라면 해결할 수 있지 않나? 했는데.... 넷빈즈의 gui 툴이 답안을 주었다.
와..... 이클립스는 git도 그렇고.... windowbuilder도 그렇고...... 이름은 그래도 멋있다...

 

여기서 팁을 또하나 주자면.... 배열을 사용하면 중복된 값을 엄청 줄일 수 있다. !!!

 

728x90