JPanel에 이미지를 추가하는 방법
JPEG와 PNG 이미지를 추가하고 싶은 JPanel이 있습니다.
지금까지 Swing Tutorials, 특히 Swing 예제에서 본 모든 예제는ImageIcon
s.
이러한 이미지는 바이트 배열로 생성되며, 보통 예시에서 사용되는 일반적인 아이콘보다 640x480 더 큽니다.
- 이미지 사용 시 (퍼포먼스 또는 기타) 문제가 있습니까?JPanel에 해당 크기의 이미지를 표시하는 아이콘 클래스?
- 보통 어떻게 해요?
- 이미지를 사용하지 않고 JPanel에 이미지를 추가하는 방법아이콘 클래스?
편집: 튜토리얼과 API를 자세히 살펴보면 이미지를 추가할 수 없습니다.JPanel에 직접 연결되는 아이콘입니다.대신 이미지를 JLabel 아이콘으로 설정함으로써 동일한 효과를 얻을 수 있습니다.이건 좀 아닌 것 같은데...
JPanels를 사용하고 있다면 Swing을 사용하고 있을 것입니다.이것을 시험해 보세요.
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);
이미지가 스윙 컴포넌트가 되었습니다.다른 컴포넌트와 마찬가지로 레이아웃 조건의 대상이 됩니다.
이 방법은 다음과 같습니다(이미지 로드 방법에 대한 자세한 정보 포함).
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters
}
}
Fred Haslam의 방식은 잘 작동한다.다만, 항아리내의 이미지를 참조하고 싶어서, 파일 패스에 문제가 있었습니다.이를 위해 저는 다음과 같이 했습니다.
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));
이 방법으로 로드해야 하는 이미지는 한정되어 있기 때문에 매우 잘 동작합니다.올바른 상대 파일 경로 없이 파일을 가져옵니다.
나는 어떤 것도 하위 분류할 필요가 없다고 생각한다.그냥 Jlabel을 사용하세요.이미지를 Jlabel로 설정할 수 있습니다.Jlabel의 크기를 조정하고 이미지를 채웁니다.괜찮아.이게 제 방식입니다.
무료 SwingX 라이브러리에서 JXImagePanel 클래스를 사용하면 자신의 Component 하위 클래스를 완전히 롤링하지 않아도 됩니다.
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
JPanel을 서브클래스로 분류할 수 있습니다.다음은 ImagePanel에서 발췌한 것입니다.상단/좌측, 상단/우측, 중간/중간, 하단/좌측/우측 중 하나의 위치에 이미지를 배치합니다.
protected void paintComponent(Graphics gc) {
super.paintComponent(gc);
Dimension cs=getSize(); // component size
gc=gc.create();
gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2) +mmHrzShift),(((cs.height-mmSize.height)/2) +mmVrtShift),null); }
if(tlImage!=null) { gc.drawImage(tlImage,(insets.left +tlHrzShift),(insets.top +tlVrtShift),null); }
if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top +trVrtShift),null); }
if(blImage!=null) { gc.drawImage(blImage,(insets.left +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
}
- 매우 큰 이미지에서 발생할 수 있는 일반적인 문제 외에는 문제가 없습니다.
- 는 '여러 이미지'를 합니다.
ImageIcon
s.의 커스텀 해 보겠습니다.JPanel
「」를 .paintComponent
이치노 - (2 참조)
JPanel
거의 항상 서브클래스에 맞지 않는 클래스입니다. 분류를 하지 거죠?JComponent
요.ImageIcon
컨스트럭터가 이미지 읽기를 차단합니다.응용 프로그램 jar에서 로드할 때는 문제가 없지만 네트워크 연결을 통해 읽을 수도 있습니다.AWT 에는 AWT를 MediaTracker
,ImageObserver
JDK 데모에서도 친구분들과 함께하고 있습니다.
지금 하고 있는 개인 프로젝트에서도 비슷한 일을 하고 있어요.지금까지 1024x1024까지 문제없이 이미지 생성(메모리 제외)하여 매우 빠르고 성능 문제 없이 표시할 수 있습니다.
JPanel 서브클래스의 도장 방법을 덮어쓰는 것은 오버킬이며 필요한 것보다 더 많은 작업이 필요합니다.
내가 하는 방법은:
Class MapIcon implements Icon {...}
또는
Class MapIcon extends ImageIcon {...}
이미지 생성에 사용하는 코드는 이 클래스에 포함됩니다.BufferedImage를 사용하여 paintIcon()이 호출되면 g.drawImvge(bufferedImage)를 사용합니다.이것에 의해, 이미지를 생성하는 동안 발생하는 플래시의 양이 감소해, 스레드 할 수 있습니다.
다음으로 JLabel을 확장합니다.
Class MapLabel extends Scrollable, MouseMotionListener {...}
그 이유는 이미지를 스크롤 페인에 표시하기 때문입니다.즉, 이미지의 일부를 표시해, 유저가 필요에 따라서 스크롤 할 수 있도록 합니다.
JScrollPane을 사용하여 MapLabel을 잡습니다.MapLabel에는 MapIcon만 포함되어 있습니다.
MapIcon map = new MapIcon ();
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);
다만, 시나리오의 경우(매회 전체 이미지를 표시해 주세요).맨 위의 JPanel에 MapLabel을 추가하고 모두 이미지의 풀사이즈로 사이징해야 합니다(GetPreferredSize()를 덮어쓰기).
이 대답은 @shawalli의 대답에 대한 보충입니다...
항아리 내의 이미지를 참조하고 싶었지만 Buffered Image가 아닌 다음과 같이 했습니다.
JPanel jPanel = new JPanel();
jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));
프로젝트 디렉토리에 소스 폴더를 만듭니다.이 경우는 Images라고 부릅니다.
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();
의 것을 할 수 있습니다.Component
SwingX 및 "SwingX"ImageIO
"반드시":
File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));
OP의 세 가지 질문에 대한 답변은 많지 않습니다.
1) 퍼포먼스: 바이트 배열은 디스플레이 어댑터의 현재 해상도 및 색심도와 일치하는 정확한 픽셀 바이트 순서를 사용할 수 없는 한 비효율적일 수 있습니다.
최상의 그리기 성능을 얻으려면 이미지를 현재 그래픽 구성에 해당하는 유형으로 생성된 Buffered Image로 변환하기만 하면 됩니다.https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html 에서 create Compatible Image 를 참조해 주세요.
이러한 이미지는 프로그래밍 작업 없이 여러 번 그린 후 디스플레이 카드 메모리에 자동으로 캐시되므로(Java 6 이후 Swing에서는 표준입니다), 이미지를 변경하지 않은 경우 실제 도면에는 거의 시간이 걸리지 않습니다.
이미지를 변경하면 메인 메모리와 GPU 메모리 간에 메모리 전송이 느립니다.따라서 이미지를 Buffered Image로 "다시 그리기"하지 마십시오. 따라서 getPixel 및 setPixel을 수행하지 마십시오.
예를 들어 게임을 개발하고 있다면 모든 게임 액터를 Buffered Image로 그리고 다음으로 JPanel로 그리는 것이 아니라 모든 액터를 작은 Buffered Images로 로드하여 JPanel 코드로 적절한 위치에 하나씩 그리는 것이 훨씬 빠릅니다.이렇게 하면 메인 메모리와 GPU 메모리 간에 추가 데이터 전송이 없습니다.캐시하기 위한 이미지의 초기 전송의 t.
ImageIcon은 후드 아래에 BufferedImage를 사용합니다.단, 기본적으로 적절한 그래픽 모드를 사용하여 BufferedImage를 할당하는 것이 중요합니다.이를 올바르게 하기 위한 노력은 없습니다.
2) 일반적인 방법은 JPanel의 오버라이드된 paint Component 메서드로 Buffered Image를 그리는 것입니다.Java는 GPU 메모리에 캐시된 VolatileImages를 제어하는 버퍼 체인 등의 많은 추가 기능을 지원하지만 Java 6은 GPU 가속의 세부 사항을 모두 노출하지 않고 상당히 잘 작동하므로 이러한 기능을 사용할 필요가 없습니다.
GPU 가속은 반투명 이미지 스트레칭과 같은 특정 작업에서는 작동하지 않을 수 있습니다.
3) 추가하지 마십시오.위에 언급한 대로 도장하면 됩니다.
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
이미지가 레이아웃의 일부인 경우 "추가"는 의미가 있습니다.JPanel을 채우는 배경 이미지 또는 전경 이미지로 필요한 경우 paint Component를 그리기만 하면 됩니다.이미지를 표시할 수 있는 일반적인 Swing 컴포넌트를 양조하고 싶은 경우는 같은 스토리입니다(JComponent를 사용하여 paint Component 메서드를 덮어쓸 수 있습니다).이것을 GUI 컴포넌트의 레이아웃에 추가합니다.
4) 어레이를 버퍼 이미지로 변환하는 방법
바이트 어레이를 PNG로 변환한 후 로드하는 작업은 상당히 많은 리소스를 필요로 하는 작업입니다.더 좋은 방법은 기존 바이트 배열을 Buffered Image로 변환하는 것입니다.
그 경우: 루프 및 복사 픽셀에는 사용하지 마십시오.그것은 매우 느리다.대신:
- Buffered Image의 우선 바이트 구조를 학습합니다(요즘은 픽셀당 4바이트인 RGB 또는 RGBA를 가정하는 것이 안전합니다).
- 스캔 라인을 학습하여 사용 중인 스캔 사이즈를 확인합니다(예를 들어 142픽셀의 와이드 이미지가 있는 경우가 있습니다.그러나 실제 환경에서는 256픽셀의 와이드 바이트 어레이로 저장됩니다.이는 GPU 하드웨어에 의해 처리되어 사용되지 않는 픽스를 마스킹하는 것이 빠르기 때문입니다).
- 이러한 원칙에 따라 어레이를 구축하면 BufferedImage의 setRGB 어레이 메서드로 어레이를 BufferedImage에 복사할 수 있습니다.
언급URL : https://stackoverflow.com/questions/299495/how-to-add-an-image-to-a-jpanel
'programing' 카테고리의 다른 글
구문 오류:Browserify에서 예기치 않은 토큰... (82:8) (0) | 2022.08.12 |
---|---|
등록된 모듈의 vuex 알 수 없는 변환 유형 (0) | 2022.08.12 |
Vuex getter가 null을 반환함 (0) | 2022.08.12 |
라이브러리가 -g로 컴파일되었는지 어떻게 알 수 있습니까? (0) | 2022.08.12 |
Java에서 두 정수를 올바르게 비교하려면 어떻게 해야 합니까? (0) | 2022.08.12 |