강좌 & 팁
안녕하세요.
유형석입니다.
이번에는 자바 프로그래밍 팁하나 알려 드리도록 하겠습니다.
1. 상황
간단한 자바 SWT라이브러리를 이용한 GUI 프로그램을 만들려고 합니다.
기본적인 바탕을 만들고 Label 2개와 Button 2개가 있습니다.
처음에는 Lable 1개와 Button 1개 밖에 없습니다.
여기서 Button 을 클릭하면 지금 있는 Lable과 Button이 없어지고,
설정한 새로운 Lable과 Button이 생성 되게 만들고 싶습니다.
2. 실험
그래서 만들어 보았습니다. 아래처럼...
import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class test { private static Display display; private static Shell shell; private static Label labPast; private static Button btnPast; private static Label labNew; private static Button btnNew; public static void main(String[] args) { display = new Display(); shell = new Shell(); shell.setBounds(200, 200, 270, 250); labPast = new Label(shell, SWT.NONE); btnPast = new Button(shell, SWT.PUSH); labNew = new Label(shell, SWT.NONE); btnNew = new Button(shell, SWT.PUSH); // Create a label labPast.setBounds(20, 20, 100, 30); labPast.setText("Past Label"); // Create a Button btnPast.setBounds(20, 50, 200, 30); btnPast.setText("Past Button"); btnPast.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub // Create a label labNew.setBounds(20, 150, 100, 30); labNew.setText("new Lable"); // Create a Button btnNew.setBounds(20, 100, 200, 30); btnNew.setText("New Button"); } }); btnNew.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub // Create a label labPast.setBounds(20, 20, 100, 30); labPast.setText("Past Label"); // Create a Button btnPast.setBounds(20, 50, 200, 30); btnPast.setText("Past Button"); } }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
그래서 실행을 해보니 아래와 같이 되었습니다.
Label과 Button이 정상적으로 하나씩 나왔습니다.
이제 Past Button 을 클릭해서 기존 Label과 Button을 없애고 위치가 다른 새로운 Lable과 Button을 생성 하겠습니다.
으아니! 기존 Label과 Button이 없어지지 않고 그대로 남아 있네요.
뭐 소스 보시면 아시겠지만 이미 소스에 없애는 부분이 없죠?-_-;
추가해 보았습니다.
btnPast.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub labPast.dispose(); btnPast.dispose(); // Create a label labNew.setBounds(20, 150, 100, 30); labNew.setText("new Lable"); // Create a Button btnNew.setBounds(20, 100, 200, 30); btnNew.setText("New Button"); } }); btnNew.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub labNew.dispose(); btnNew.dispose(); // Create a label labPast.setBounds(20, 20, 100, 30); labPast.setText("Past Label"); // Create a Button btnPast.setBounds(20, 50, 200, 30); btnPast.setText("Past Button"); } });
기존의 Lable과 Button을 없애도록 각 위젯에 dispose 를 사용해서 없애도록 하였습니다.
자 결과를 볼까요?
여기 까진 똑같네요.
자 Past Button 을 클릭하면??
야! 신난다 성공입니다!
이제 다시 New 씨리즈를 없애고 Past 들을 활성화 시키기 위해서 New Button을 클릭합니다.
???!?? 갑자기 프로그램이 죽어 버리고 이클립스에 콘솔메시지에서 에러를 쏟아 내고 있습니다.
이유는 바로...
.
.
.
.
dispose를 사용 하기때문에 생성된 Label과 Button 설정이 아얘 사라져 버리기 때문입니다.
때문에 다시 살리기 위해서는 new Label, new Button을 이용해서 다시 만들어 줘야 합니다.
예... 다시 만들면 되긴 하겠죠?
하지만 예로 들은 것처럼 위젯들이 적으면 차~암 편하고 간단합니다.
만약 라벨이 한 10개정도 되고 버튼도 한 10개 기타 등등 해서 위젯이 한 50개정도 있다고 치면
그때그때 dispose를 한다음에 다음 이벤트에서 다시 new하고..
그것도 위의 상황 말고 Past 버튼 누르면 New로 가고 New 버튼 누르면 New2로 갈수도 있고 Past로 갈수도 있고...
이렇게 몇개나 존재 한다면?
클래스를 3개로 나눈다 쳐도 각 클래스에 전부다~~~~ 그때그때 상황에 맞춰서 위젯 하나하나 마다 다 해줘야 합니다.
아오.... 50개씩 만들어 줘야 합니다. 아니..그 이상 만들어야 할지도 모릅니다.
정말 귀찮아요.
그래서 저는 아래와 같은 방법을 이용했습니다.
3. 방법
그리하여 나온 방법이 현재 클래스가 가진 위젯 다~~~ 지우기 입니다.
import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; public class test { private static Display display; private static Shell shell; private static Label labPast; private static Button btnPast; private static Label labNew; private static Button btnNew; private static void delWidget() { // TODO Auto-generated method stub for (Control kid : shell.getChildren()) { kid.dispose(); } } private static void pastDisplay() { // TODO Auto-generated method stub labPast = new Label(shell, SWT.NONE); btnPast = new Button(shell, SWT.PUSH); // Create a label labPast.setBounds(20, 20, 100, 30); labPast.setText("Past Label"); // Create a Button btnPast.setBounds(20, 50, 200, 30); btnPast.setText("Past Button"); btnPast.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub delWidget(); newDisplay(); } }); } private static void newDisplay() { // TODO Auto-generated method stub labNew = new Label(shell, SWT.NONE); btnNew = new Button(shell, SWT.PUSH); // Create a label labNew.setBounds(20, 150, 100, 30); labNew.setText("new Lable"); // Create a Button btnNew.setBounds(20, 100, 200, 30); btnNew.setText("New Button"); btnNew.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event arg0) { // TODO Auto-generated method stub delWidget(); pastDisplay(); } }); } public static void main(String[] args) { display = new Display(); shell = new Shell(); shell.setBounds(200, 200, 270, 250); pastDisplay(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } display.dispose(); } }
소스가 달라져서 당황하지 마세요!
설명하자면
pastDisplay()는 labPast와 btnPast를 만들고 btn에 이벤트를 추가한것을 다른 함수에 넣어 둔것 뿐입니다.
newDisplay()는 그 반대의 경우 겠죠?
여기서 봐야 할 것은
private static void delWidget() {
// TODO Auto-generated method stub
for (Control kid : shell.getChildren()) {
kid.dispose();
}
}
이겁니다.
for문을 돌면서 현재 shell이 가지고 있는 위젯들을 가져 옵니다.
근데 가져온 shell 자식이 Control 이면 그 위젯을 가져와 Control kid에 대입하고 dispose 시킵니다.
이런 식으로 하면 100개든 200개든 한꺼번에 죄다 싹 없애 줄 수 있습니다.
처음에 했던 각각의 위젯 이름을 써서 dispose 하는것보다 훨씬 편한 방법이죠?
그래서 그냥 new Label, new Button 으로 위젯에 값을 다시 넣어주는 함수를 서로 불러 오면 끗~~~!
자 결과를 봅시다.
3. 결과
자..벌써 세번째 보는 화면입니다. 이제 슬슬 지겨워 지네요.
올~ 여기까진 똑같습니다. 이제 이클립스에서 에러를 뱉느냐 마느냐의 기로!!
오늘은 여기 까지!
짧은 글 읽어 주셔서 감사합니다!
는 농담이구요-_-; 정상으로 작동 합니다. 이야 해냈습니다 여러분!
위의 예시는 약간 부적절 할 수도 있겠지만 본문의 내용처럼
위젯이 아~ 이건 너무 많다 할때 사용 하시면 될것 같습니다.
여기서 잠깐!!
제가 왜 위젯하나하나 마다 dispose를 넣어 줬을까요?
혹시나 Display나 Shell API 중에 한꺼번에 삭제 하는것이 있을까 해서 찾아 보았지만
발견하지 못해서 부득이 하게 사용 했습니다.... 그리하야 나온 팁이라고 보시면 됩니다.
혹시 아시는분은 댓글로 제보좀 부탁 드리겠습니다.. 그런 방법이 있으면 이 팁은 그냥 저의.....삽..질.... orz
오늘은 정말 여기 까지!
- java_logo.png (3.1KB)(105)
- no_del_defalut_01.png (21.1KB)(103)
- no_del_defalut_02.png (14.4KB)(105)
- added_dispose_01.png (14.1KB)(113)
- added_dispose_02.png (12.2KB)(189)
- added_dispose_03.png (27.6KB)(97)
- added_del_widget_01.png (14.9KB)(119)
- added_del_widget_03.png (14.9KB)(93)
- added_del_widget_02.png (15.0KB)(98)