
화면에 보이는 요소(이미지, 오브젝트 등)에 대해
실제로 클릭되거나 충돌이 감지되는 논리적인 사각형 영역
➡️ 갤러리 예제에서의 적용
이미지를 패널에 직접 그리고, g.drawImage(...)
그 위치와 크기 정보를 Rectangle[]으로 저장해 new Rectangle(...)
클릭 이벤트 충돌 판정용으로 사용하는 구조 rect.contains(...)
보이는 건 이미지,
감지되는 건 히트박스(Rectangle)인 구조
| 구성 요소 | 역할 |
|---|---|
p_west (JPanel) | 썸네일 이미지들을 drawImage()로 직접 그리는 영역 |
rects[i] (Rectangle) | 눈에는 보이지 않지만, 해당 썸네일 영역의 위치와 크기를 기억하고 있음 |
MouseListener | 마우스 클릭 시 e.getPoint()가 rects[i] 중 어디에 속하는지 판단 (rect.contains(...)) |
public class Gallery extends JFrame {
JPanel p_west; // 좌측 썸네일들이 그려질 패널
JPanel container; // 북쪽, 중앙 패널들을 감쌀 컨테이너 (BorderLayout 사용)
JPanel p_north; // 북쪽 컨트롤러 영역 (현재 비어 있음)
JPanel p_center; // 선택한 큰 이미지가 표시될 패널
ImageUtil imageUtil = new ImageUtil(); // 이미지 로딩 유틸리티
Image[] images = new Image[9]; // 총 9장의 이미지 배열
// 썸네일 위치 정보를 담을 사각형 배열 (이벤트 판별용)
Rectangle[] rects = new Rectangle[images.length];
float y = 10f; // 현재 빨간 사각형 y 좌표
float a = 0.1f; // 감속도 비율 계수
int targetY; // 빨간 사각형이 도달해야 할 목표 y 좌표
int currentIndex; // 현재 선택된 이미지의 인덱스
Thread thread; // 애니메이션용 스레드 (게임루프 역할)
public Gallery() {
createImage(); // 이미지 및 rect 좌표 초기화
// 애니메이션용 스레드 (10ms 간격으로 repaint + 이동)
thread = new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(10); // 주기적 호출
move(); // y값 업데이트 (감속도 이동)
p_west.repaint(); // 썸네일 패널 다시 그리기
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
thread.start();
// 썸네일 패널 구현 (커스텀 paintComponent)
p_west = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 썸네일 9장 그리기
for (int i = 0; i < images.length; i++) {
g.drawImage(images[i], 5, 10 + (95 * i), 90, 90, this);
}
// 빨간 사각형 포인터 그리기
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(5));
g.setColor(Color.RED);
g.drawRect(5, (int) y, 90, 90);
}
};
container = new JPanel();
p_north = new JPanel();
// 큰 이미지 보여줄 중앙 패널 구현
p_center = new JPanel() {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(images[currentIndex], 0, 0, 800, 850, this);
}
};
// 스타일
p_west.setBorder(new LineBorder(Color.LIGHT_GRAY));
p_west.setPreferredSize(new Dimension(100, 800));
// 조립
add(p_west, BorderLayout.WEST);
container.setLayout(new BorderLayout());
container.add(p_north, BorderLayout.NORTH);
container.add(p_center);
add(container);
// 썸네일 클릭 시 이벤트 처리
p_west.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
for (int i = 0; i < rects.length; i++) {
//✅rect.contains(click)
if (rects[i].contains(e.getPoint())) {
currentIndex = i; // 현재 선택 이미지 설정
p_center.repaint(); // 큰 이미지 갱신
targetY = rects[i].y; // 이동할 목표 y좌표 설정
}
}
}
});
targetY = 10; // 초기 포인터 위치
setSize(900, 900);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
// 이미지 객체 생성 및 썸네일 좌표 rect 배열 초기화
public void createImage() {
for (int i = 0; i < images.length; i++) {
images[i] = imageUtil.getImage("geographic/animal" + (i + 1) + ".jpg", 90, 90);
rects[i] = new Rectangle(5, 10 + (95 * i), 90, 90);
}
}
// 감속도 공식 적용
public void move() {
y = y + a * (targetY - y);
}
public static void main(String[] args) {
new Gallery();
}
}
사용자가 클릭한 좌표가 이 사각형 안에 들어 있나요?
if (rects[i].contains(e.getPoint())) {
currentIndex = i; // 선택한 이미지 인덱스 저장
targetY = rects[i].y; // 빨간 사각형의 목표 y좌표 설정
p_center.repaint(); // 오른쪽 큰 이미지 갱신
}
rects[i]는 썸네일 하나의 위치 사각형e.getPoint()는 사용자가 클릭한 위치 (마우스 좌표)사용자가 클릭한 위치가 해당 썸네일 사각형 안에 있으면 → 클릭 처리