2012-11-28 4 views
3

다음 코드가 있습니다. 기본적으로 배경 이미지가있는 프레임이 있습니다. 또한 프레임 내에 3 개의 패널이 있습니다. 1, 2, 3 패널. 2 & 3 서브 클래스로 서브를하지 않아도됩니다. 하지만 패널 1은 서브 클래스를 만들 자마자 즉, JPanel의 paintComponent 메소드 안에 로직을 넣으면 해당 메소드가 호출되지 않고 foo가 결코 인쇄되지 않기 때문에 작동을 멈 춥니 다. 나는 이유를 알 수 없다. 도와 주셔서 감사합니다. 다른 비슷한 스레드에서 몇 가지 제안을 시도했지만 도움이되지 않았습니다.paintComponent가 호출되지 않는 이유는 무엇입니까?

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Toolkit; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.BorderFactory; 
import javax.swing.ImageIcon; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class Test { 

    public static void main(String[] args) throws IOException { 

     JFrame.setDefaultLookAndFeelDecorated(true); 
     Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

     int fooPanelX = 5; 
     int fooPanelY = 160; 
     int fooPanelWidth = 470; 
     int fooPanelHeight = 305; 

     int bar0PanelX = 5; 
     int bar0PanelY = 550; 
     int bar0PanelWidth = 230; 
     int bar0PanelHeight = 210; 

     int bar1PanelX = bar0PanelX * 2 + bar0PanelWidth + bar0PanelX; 
     int bar1PanelY = bar0PanelY; 
     int bar1PanelWidth = bar0PanelWidth; 
     int bar1PanelHeight = bar0PanelHeight; 

     JPanel panel1 = new Panel1(fooPanelX, fooPanelY, fooPanelWidth, fooPanelHeight); 

     JPanel panel2 = new JPanel(); 
     panel2.setBackground(Color.WHITE); 
     panel2.setLocation(bar0PanelX, bar0PanelY); 
     panel2.setSize(bar0PanelWidth, bar0PanelHeight); 
     panel2.setOpaque(false); 
     panel2.setBorder(BorderFactory.createLineBorder(Color.WHITE)); 
     panel2.setBounds(bar0PanelX, bar0PanelY, bar0PanelWidth, bar0PanelHeight); 

     JPanel panel3 = new JPanel(); 
     panel3.setBackground(Color.WHITE); 
     panel3.setLocation(bar1PanelX, bar1PanelX); 
     panel3.setSize(bar1PanelWidth, bar1PanelHeight); 
     panel3.setOpaque(false); 
     panel3.setBorder(BorderFactory.createLineBorder(Color.WHITE)); 
     panel3.setBounds(bar1PanelX, bar1PanelY, bar1PanelWidth, bar1PanelHeight); 

     JLabel imagePanel = new JLabel(new ImageIcon(ImageIO.read(new File("image.png")))); 

     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.addKeyListener(new KeyAdapter() { 

      @Override 
      public void keyPressed(KeyEvent e) { 
       if (e.getKeyCode() == 27) { 
        System.exit(0); 
       } 
      } 

     }); 

     frame.setContentPane(imagePanel); 
     frame.getContentPane().add(panel1); 
     frame.getContentPane().add(panel2); 
     frame.getContentPane().add(panel3); 
     frame.setLocation((int) (screenSize.getWidth() * 0.75), 
       (int) (screenSize.getHeight() * 0.25)); 
     frame.pack(); 
     frame.setVisible(true); 

    } 

    @SuppressWarnings("serial") 
    static class Panel1 extends JPanel { 

     int x, y, w, h; 

     public Panel1(int x, int y, int w, int h) { 
      this.x = x; 
      this.y = y; 
      this.w = w; 
      this.h = h; 
     } 

     @Override 
     public void paintComponent(Graphics graphics) { 

      System.out.println("foo"); 
      super.paintComponents(graphics); 

      setBackground(Color.WHITE); 
      setLocation(x, y); 
      setSize(w, h); 
      setOpaque(true); 
      setBorder(BorderFactory.createLineBorder(Color.WHITE)); 

     } 

    } 

} 

는 업데이트 : 당신이 문제를 찾을 수없는 경우 당신은 다음과 같은 일을 다른 방법으로 날을 제공 할 수 바랍니다. 배경 이미지가있는 프레임과 배경 이미지 위에 세 개의 패널이 필요합니다. 세 개의 패널은 배경 이미지에서 픽셀이 완벽한 위치와 크기를 가져야합니다. 그게 전부예요. 세 패널을 다시 칠할 것이지만 배경 이미지는 그대로 유지됩니다.

+0

Panel1의 정의에서 정적을 제거하면 어떻게됩니까? – 11684

+2

(** 실제로는 ** 절대) 페인팅 프로세스에서 구성 요소의 상태를 변경하지 마십시오! 그리고 컴포넌트의 수동 크기 조정/위치 지정을하지 마십시오. 적절한 LayoutManager의 독점적 인 작업입니다. – kleopatra

+0

@kleopatra - 감사합니다. 나는 스윙이 처음이다.크기와 위치를 설정하지 않으면 배경 이미지의 특정 지점에 물건을 정확하게 배치해야하는 이유는 무엇입니까? – junkie

답변

2

저는이 문제를 매우 다른 방식으로 해결하기로 결정했습니다. 이게 내가 한 일이야. 나는 코드를 처음부터 완전히 시작했다. JFrame 인스턴스와 Canvas 인스턴스를 만들었습니다 (캔버스는 서브 클래 싱되었습니다). 캔버스에서 drawImage()를 사용하여 배경 이미지를 적용했습니다. 그런 다음 세 개의 영역 각각에 대해 배경 이미지에 애니메이션을 적용하려는 대신 세 개의 JPanel을 만드는 대신 캔버스 내에 fillRect()를 사용하여 이미지의 오른쪽 영역을 채 웁니다. 그게 전부 야. 좋고 간단합니다. 매초 repaint()가 세 영역에서 플리커를 치며 다음 과제입니다. 이중 버퍼링을 사용해야한다고 생각하지만 이전에 사용한 적이 없으므로 다음에 살펴볼 것입니다. 어쨌든, 3 개의 JPanels 대신 하나의 캔버스를 사용하면 훨씬 간단 해졌고 배경 이미지가 모든 것을 시각적으로 제공했기 때문에 내가 할 수 있었던 이유가 입증되었습니다. 내가해야만하는 것은 drawImage()와 fillRect()뿐입니다. 모든 기여에 감사드립니다.

업데이트 : 이제이 작업을 완료했습니다. 위의 내용을 바꿨습니다. Canvas를 사용하여 버퍼를 두 번 시도하는 동안 몇 가지 문제가있었습니다. 일반적으로 "구성 요소에는 유효한 피어 (peer)가 있어야합니다"예외가 있습니다. 그 동안 Swing에서 Canvas를 사용해서는 안되며 AWT와 Swing을 섞어 사용하는 관행이라는 것을 알게되었습니다. 그래서 JComponent (JPanel에서 제공 할 필요는 없었으므로)를 대신 사용했습니다. Swing은 기본적으로 이중 버퍼링되어 있으므로 작업이 완료되었습니다. 깜박 거림 및 단순화 된 코드가 없습니다.

+0

위에서 언급 한 문제는 JPanel/JComponent를 하위 클래스로 분류하지 않았지만 부적절한 LayoutManager를 사용하여 발생합니다 (이 경우에는 없음). 어쨌든 모든 것을 이해할 수는 없지만 문제를 해결해 주어서 기쁩니다. –

2

글쎄, 문제는 적절한 LayoutManager을 사용하지 않는 것입니다.

JLabel은 기본적으로 LayoutManager과 함께 제공되지 않습니다. 따라서 Panel1을 추가하면 크기가 0x0이고 위치가 (0,0)이고 LayoutManager가 변경되지 않으므로 크기와 위치가 유지됩니다. 빈 경계를 사용하면 구성 요소가 페인트되지 않으므로 paintComponent 메서드는 호출되지 않습니다.

지금, 당신은 paintComponent에서이 작업을 수행해서는 안 :

 setBackground(Color.WHITE); 
     setLocation(x, y); 
     setSize(w, h); 
     setOpaque(true); 
     setBorder(BorderFactory.createLineBorder(Color.WHITE)); 

생성자 또는 다른 방법으로이 작업을 수행합니다. paintComponent은 속성을 변경하지 않고 "구성 요소 페인팅"을위한 것입니다.

+0

감사합니다. 그 코드를 생성자 나 그 클래스 외부로 옮기는 것은 부분적으로 작동하지만 불투명하지 않습니다. true 대신 opacity false로 표시됩니다. 그러나 jpanel 하위 클래스를 사용하지 않고 jpanel을 만든 다음 불투명도가 적용된 후에 해당 항목을 설정하면 서브 클래 싱과 관련된 것이됩니다. – junkie

+0

또한 이제 빈 paintComponent 메서드를 삭제하고 Panel1 클래스를 인스턴스화하고 불투명도가 작동하는 것처럼 보입니다. 어떻게 든 그 방법을 사용하는 것은 그것을 깨뜨리는 것입니다. – junkie

+0

이제이 작업을 마쳤습니다. 결국이 질문에 대한 내 대답을 읽어보십시오. 감사. – junkie

관련 문제