[질문] Swing에서 이벤트를 만들어 내려면 어떻게 해야 하나요??

tyolee83의 이미지
1347
points
0
points

질문의 뜻이 제대로 전달되도록 최선을 다해 보겠습니다.

마우스를 클릭하거나 버튼을 클릭하면 이벤트가 발생하게 되잖아요...

이벤트 리스너가 그 이벤트를 받아서 처리하고...

그런데 이벤트 멀티캐스트를 위해 중간에 개념적인 Event Multicaster를 두려고 하거든요...

버튼이나 마우스에서 일어난 이벤트를 이 멀티캐스터가 보고

각각의 상황에서 이제 다른 컴포넌트들에게

정보를 가진 새로운 이벤트를 multicast 해야되는데(제가 직접 정의하는 이벤트이죠)

이 이벤트를 어떻게 만들어 내야 할지 모르겠습니다....

좀 더 구체적으로 말씀드리자면

캔버스에다가 원을 여러개 그리고

한 원을 선택할때, 마우스 이벤트가 멀티캐스터에게 전달되고

이 멀티캐스터가 각각의 원들에게 이벤트를 Multicast 하여

해당되는 원이 어떤것인지 파악하려는 것입니다.

while을 돌면서 하나하나 찾는게 아니라 multicast의 개념을 적용하려 하는 것입니다.

어떤 방법이 있는지 도움좀 부탁드립니다.

열심히 찾아봤는데 잘 모르겠어서 이렇게 질문 올립니다.

미리 감사드립니다.

mykldp의 이미지
1314
points

음 바라시는 바를

0
points

음 바라시는 바를 정확히 짐작하기 힘들지만... 다음 같은 것을 말씀하시는 것인지. 코드는 정확치 않습니다만 내용은 전달되리라고 생각합니다 ^^;

interface CustomListener {
	public void execute(CustomEvent e);
}

class Multicaster {
	public Multicaster(Canvas c) {
		c.addMouseListener(new MouseListener() {
			public void ~~~(MouseEvent e) {
				for(CustomListener l : listeners) {
					CustomEvent e = new CustomEvent();
					l.execute(e);
				}
			}
		});
	}

	public void addListner(CustomListener l) {
		listeners.add(l);
	}

	private List listeners = new ArrayList();
}

그리고 각 원이 Multicaster 에 CustomListener 를 등록합니다.
class Circle  {
	public Circle(Multicaster m) {
		m.addListener(new CustomListener() {
			public void execute(CustomEvent e) {
				~~
			}
		});
	}
}

익명 사용자의 이미지

Robot을 원하시는건지?

0
points

자동으로 마우스 클릭하고 키보드 입력하는것을 원하시는 거라면 스윙의 Robot 이라는 클래스를 확인해 보세요.

익명 사용자의 이미지

Robot...

0
points

자동으로 마우스 클릭하고 키보드 입력하는것을 원하시는 거라면 스윙의 Robot 이라는 클래스를 확인해 보세요.

tyolee83의 이미지
1347
points

잘 이해가 안되네요....

0
points

일단 robot을 써보라고 하신 분께는, 질문이 그 의도가 아니라고 말씀드려야 할것 같구요~ ^^;

하지만, bot이라는 놈이 있다는 것을 알려주셔서 감사드립니다 :)

그리고 처음에 답해주신 분의 코드가 잘 이해가 안되서요....

제가 해놓은 소스 보여드리고, UI 그려놓은것만 올려볼게요....

위에 코드를 적용시켜 보려 하는데... 이해가 안되네요...

캔버스에 리스너를 다는것 까지는 알겠는데

위에 코드에서 이해가 안되는 부분을 몇가지 말씀드려보면

1. CustomEvent e

CustomEvent라는건 찾아봐도 없는것 같구요...

2.
for(CustomListener l : listeners) {
CustomEvent e = new CustomEvent();
l.execute(e);
}

for 안에 있는게 어떤 의미인지를 모르겠습니다... 처음보는 문법인데요 ㅠ
그리고 l.execute(e)를 하는데, l이 구현되어 있지 않은 인터페이스인데
어떤 동작을 하는지 잘 이해가 안되구요...

3. 각 원이 Multicast에 등록한다고 했는데...
멀티캐스트가 유지하고 있는 리스트에 추가하는것 같은데...
왜 여기서 execute를 구현하는지 잘 이해가 안됩니다.

질문을 써놓고 보니 자바에 대한 이해가 부족하다는 느낌이 많이 드네요... ㅠㅠ

그래도 자바는 약간이나마 안다고 생각했는데 갑갑합니다.... ㅠㅠ

제 소스 붙여 볼테니 도움좀 부탁드립니다.

감사합니다.

import javax.swing.*;

import sun.org.mozilla.javascript.internal.ContextFactory.Listener;

import java.awt.*;
import java.awt.event.*;

public class GraphEditor {
	public static void main(String[] args) {
		_GraphEditor ge = new _GraphEditor();
		ge.canvasPanel.addMouseListener(new MyListener(ge));
		ge.canvasPanel.addMouseMotionListener(new MyListener(ge));
		ge.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		ge.setVisible(true);		
	}
}

class MyListener implements MouseListener, MouseMotionListener{
	private static final long serialVersionUID = 1L;
	private _GraphEditor ge;
	public MyListener(_GraphEditor ge){
		this.ge=ge;
	}

	public void mouseClicked(java.awt.event.MouseEvent e) {
		if(this.ge.createButton.isSelected()){
			System.out.println("Create Vertex");
			//TODO drawOval and add to List
		}else if(this.ge.connectButton.isSelected()){
			System.out.println("Connect Vertices");
			//TODO drawEdge and add to List
		}else if(this.ge.mergeButton.isSelected()){
			System.out.println("Merge Vertices");
			//TODO select two vertices and merge them into a vertex. maybe redraw
			
		}else{
			System.out.println("Split Vertex");
			//TODO split merged vertex into two vertices. maybe redraw
		}		
	}
	public void mousePressed(java.awt.event.MouseEvent e) {
		
	}
	public void mouseReleased(java.awt.event.MouseEvent e) {
		
	}
	public void mouseEntered(java.awt.event.MouseEvent e) {
		
	}
	public void mouseExited(java.awt.event.MouseEvent e) {
		
	}
	public void mouseDragged(java.awt.event.MouseEvent e) {
		//TODO when selecte mode, move vertex or edge. maybe redraw
		//TODO when merge mode, draw focusbox to choose two vertices. maybe XOR brush
	}
	public void mouseMoved(java.awt.event.MouseEvent e) {
		
	}	
}

==========================
Toward Fully Understanding

첨부 파일파일 크기
graph.PNG10.08 KB
mykldp의 이미지
1314
points

1. CustomEvent 는 표준

0
points

1. CustomEvent 는 표준 API에 있는게 아니구요. tyolee83 님께서 직접 정의하신다고 한 이벤트를 그냥 그렇게 쓴겁니다. 의도에 맞게 아무렇게나 만드셔도 관계 없습니다.^^

2. for(Type var : container) 는 자바 5.0 에서 추가된 문법입니다. container 에는 배열 또는 java.util.Iterable 인터페이스를 구현한 객체가 올 수 있습니다. 그러면 그 녀석의 모든 원소들을 차례로 돌면서 for 블럭이 실행됩니다. 예를 들어 String 을 담고 있는 ArrayList list 에 대해서 적용한다치면

for(String s : list) {
	System.out.println(s);
}

는 아래와 동일합니다.
Iterator itr = list.iterator();
while(itr.hasNext()) {
	String s = itr.next();
	System.out.println(s);
}

3. 제가 tyolee83 님께서 하고자하는 바를 제대로 이해했는지 잘 모르겠지만 ^^; 말하자면 이런식입니다.

Canvas 에서 발생한 MouseEvent 를 받아서 처리하기 위해서 canvas 에 MouseListener 를 등록하듯이, 각 원도 Multicaster 가 발생시키는 이벤트를 받기 위해서 Multicaster에 CustomEvent에 대한 리스너를 등록하는겁니다. 보통 Listener pattern 이라고 부르는 패턴이구요. 구현 방식은 Swing 과 조금 다르지만 기본적인 아이디어는 같습니다. 실행 순서를 따지자면 아래와 같지요.

1. 각 원은 Multicaster 에 CustomEvent 에 대한 리스너를 등록한다. 즉, "난 Multicaster 가 발생시키는 이벤트에 관심있다"고 알려주는 겁니다.
2. Canvas 에서 마우스 이벤트가 발생하면 Multicaster가 이벤트를 받는다.
3. Multicaster 는 필요한 정보를 담아서 CustomEvent 객체를 만든다.
4. Multicaster 는 등록된 CustomListener 에게 이벤트를 알린다.(즉, 등록된 각 CustomListener 의 execute 메소드를 실행시킨다.)

"왜 여기서 execute를 구현하는지 잘 이해가 안됩니다." 라고 물으셨는데 execute 구현은 각 CustomListener 가 하는거지 Multicaster 가 하는 것이 아닙니다. CustomListener 의 execute 를 "호출하는" 부분이 Multicaster 에 있을 뿐입니다.

tyolee83의 이미지
1347
points

자세한 설명

0
points

자세한 설명 감사드립니다.

설명해 주신 내용이 완벽하게 제가 구현하고자 하는 내용입니다.

그런데 아직 객체지향의 개념이 완벽하지 않아서 확 와닿지가 않네요...

CustomEvent를 어떻게 구현해야 할지 모르겠네요....

이것도 제가 궁금했던 것중에 하나인데,

멀티캐스터가 원들에게 이벤트를 "어떻게" 보내는지가

정말 큰 의문이었습니다.

sendEvent() 이런 API가 있을줄 알고 뒤져봤는데 암만해도 없더군요 ㅠㅠ

그리고 원을 캔버스에 그리는 부분도 넣어야 하는데

이걸 MyListener에 extends JPanel 한 후에 paint() 메소드를 오버라이딩 시켜서 해야 하는지

아니면 vertex 라는 클래스를 별도로 만들어서

거기에 extends JPanel 한 후에 paint() 해야 할지...

(흠 사실 둘다 해봤는데 원이 안나옵니다. 미치겠네요 ㅠㅠ)

상황에 따라서 원들이 캔버스 내에서 움직이는 경우도 있는데...

이런 경우 캔버스로 가능할런지....

답변 정말 감사드리고, 조금만 더 도움 부탁드립니다.
==========================
Toward Fully Understanding

mykldp의 이미지
1314
points

음... 저라면 대충

0
points

음... 저라면 대충 아래처럼 하겠습니다.^^; 컴파일 안해본 코드이고 기억나는대로 썼으니 정확하지 않습니다. 역시 내용은 전달되리라 믿으면서.. 다른 좋은 방법들도 있겠지만, 뭐 일단 적당히...^^

class Vertex {
	public Vertex() {
		m = new VertexModel();
		v = new VertexView();
	}

	getVertexModel()~~
	setVertexModel()~~
	getVertexView()~~
	setVertexView()~~

	private VertexModel m;
	private VertexView v;
}

class VertexModel {
	getName() ~~
	setName() ~~

	private String name;
	//기타 데이터들...
}

class VertexView {
	public VertexView(VertexModel v) {
		this.v = v;
	}

	public void draw(Graphics2D g) {
		g.drawCircle()
		g.drawText(v.getName());
	}

	private VertexModel v;
	//기타 위치나, 크기 등등 "그림"과 관련된 데이터들...
}

class GraphCanvas extends Canvas {
	public void paint() {
		for(VertexView v : vertexViewList) {
			v.draw(this.getGraphics());
		}
	}

	public void registerVertexView(VertexView v) {
		vertexViewList.add(v);
	}

	List vertexViewList = new ArrayList();
}

class GraphEditor {
	
	GraphEditor() {
		//일단 GUI 를  구성합니다. 각 요소들을 적절히 배치하고,
		//아래처럼 이벤트에 대한 행동들을 정해줍니다.

		canvas.addMouseListener(new MouseListener {
			public void mouseClicked(java.awt.event.MouseEvent e) {
				switch(command) {
					case Command.CREATE:
						Vertex v = new Vertex();
						v.getVertexModel().setName("new vertex");
						vertexList.add(v);
						canvas.registerVertexView(v.getVertexView());
						break;
					case Command.CONNECT:

						~~~

				}
			});
		}

		createButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				command = Command.CTEATE;
			}
		}

		connectButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				command = Command.CONNECT;
			}
		}
		
		~~~~
	}

	private int command;
	private List vertexList = new ArrayList();

	~~
}

class Command {
	public static int CREATE = 1;
	public static int CONNECT = 2;

	...
}

tyolee83의 이미지
1347
points

자세한 답변

0
points

자세한 답변 감사드립니다.

이걸 참고로 해서 한번 다시 달려들어봐야 겠네요.

정말 감사드립니다.

이제 문제없이 해결할 수 있었으면 ㅠㅠ
==========================
Toward Fully Understanding

댓글 보기 옵션

원하시는 댓글 전시 방법을 선택한 다음 "설정 저장"을 누르셔서 적용하십시오.