2014-10-07 7 views
0

따라서 JTextPane 객체는 런타임 중에 특정 이미지의 배경으로 변경해야합니다. 내가 무엇을 가지고 꽤 버그 (JComboBox 배경을 변경하는 데 사용하고 repaintBackground() 호출은 선택에 autoclose 보이지 않습니다), 그것도 nullpointer을 throw하고 아무 이유도 배경 변경으로 가지고 있습니다. 어떤 도움을 주시면 감사하겠습니다런타임 중에 JTextPane의 백그라운드를 변경하려고 시도했지만 성공했지만 오류가 발생했습니다.

public class PreviewPane extends JTextPane { 
    private String _name = "bg3"; 

    public PreviewPane() { 
     super(); 
     setOpaque(false); 
     StyledDocument document = this.getStyledDocument(); 
     SimpleAttributeSet center = new SimpleAttributeSet(); 
     StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); 
     document.setParagraphAttributes(0, document.getLength(), center, false); 
    } 

    @Override 
    protected void paintComponent(Graphics g) throws RuntimeException{ 
     g.setColor(Color.WHITE); 
     g.fillRect(0, 0, getWidth(), getHeight()); 

     BufferedImage img = null; 

      try { 
       img = ImageIO.read(new File(getClass().getResource("/icons/"+_name+".png").toURI())); 
      } catch (IOException | URISyntaxException e) { 
       // TODO Auto-generated catch block 
       //e.printStackTrace(); 
      } 

     g.drawImage(img, 0, 0, this); 


     super.paintComponent(g); 
    } 

    public void repaintBackground(String bgName){ 

     _name = bgName; 

     paintComponent(this.getGraphics()); 

    } 

} 

:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at javax.swing.text.BoxView.paint(Unknown Source) 
at javax.swing.plaf.basic.BasicTextUI$RootView.paint(Unknown Source) 
at javax.swing.plaf.basic.BasicTextUI.paintSafely(Unknown Source) 
at javax.swing.plaf.basic.BasicTextUI.paint(Unknown Source) 
at javax.swing.plaf.synth.SynthEditorPaneUI.paint(Unknown Source) 
at javax.swing.plaf.synth.SynthEditorPaneUI.update(Unknown Source) 
at javax.swing.JComponent.paintComponent(Unknown Source) 
etc etc etc.... 

내 개체입니다.

+0

이 RuntimeException을 던졌습니다 { .. IMG = ImageIO.read ('워 페인트 방법! 1) 런타임 예외를 throw하지 않아야합니다. 2) 즉시 슈퍼 메서드를 호출해야합니다. 3) 이미지를로드하는 것과 같이 잠재적으로 장기간 실행되는 작업을 시도해서는 안됩니다! –

+0

이 문제를 피하는 방법을 권하고 싶습니다. – Ofek

+0

어느 'this'? 구체적으로 말하십시오. –

답변

4
  1. paintComponent(this.getGraphics()); - NO. 절대 paintComponent을 명시 적으로 호출해서는 안됩니다. 대신 repaint()으로 전화하십시오.

  2. super.paintComponent(g);paintComponent 방법의을 시작하는 에서 호출, 또는 당신이 Graphics 컨텍스트에 어떤 그림을 최소하기 전에해야합니다.

  3. paintComponent 방법으로 이미지를로드하지 마십시오. 하나의 옵션은 캐시를 Map<String, Image>에 보관하는 것입니다. 그렇게하면 변경할 때마다로드 할 필요없이 쉽게 참조 할 수 있습니다. 전체적으로 그것은 이 아니며, 캐시 여부에 상관없이 거대한 문제입니다. repaintBackground 방법으로로드하면됩니다.

  4. 클래스 회원 유지 Image image;. 이것은 페인트 할 때 사용하는 Image입니다. repaintBackground을 입력하면 문자열 대신 Image을 사용할 수 있습니다. Image은 회화에 사용되는 반원 Image image을 전달합니다. 해당 메서드에서 이미지를로드하기로 결정한 경우에도 메서드에서 String을 허용 할 수 있습니다.

    classs MyPanel extends JPanel { 
        Image image; 
    
        public void repaintBackground(Image image) { 
         this.image = image; 
         repaint(); 
        } 
    
        protected void paintComponent(Graphics g) { 
         super.paintComponent(g); 
         g.drawImage(image); 
        } 
    } 
    
  5. paintComponentRuntimeException

이 여기에 완벽한 예입니다 버리지한다. 나는 Map 캐시와 함께 가기로 결정했습니다. 어떻게 할 지 당신에게 달려 있습니다. 당신이 이것을 처리 할 수있는 많은 방법이 있습니다. `보호 무효의 paintComponent (그래픽 g)

import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
import javax.swing.*; 

public class ImageChangeDemo { 

    private ImagePanel imagePanel = new ImagePanel(); 

    public ImageChangeDemo() { 
     JFrame frame = new JFrame(); 
     frame.add(imagePanel); 
     frame.add(createCombo(), BorderLayout.PAGE_START); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private JComboBox createCombo() { 
     String[] items = { 
      ImagePanel.DIRECTORY, 
      ImagePanel.COMPUTER, 
      ImagePanel.FILE, 
      ImagePanel.FLOPPY, 
      ImagePanel.HARD_DRIVE 
     }; 
     JComboBox comboBox = new JComboBox(items); 
     comboBox.addActionListener(new ActionListener(){ 
      public void actionPerformed(ActionEvent e) { 
       imagePanel.repaintBackground(comboBox.getSelectedItem().toString()); 
      } 
     }); 
     return comboBox; 
    } 

    private class ImagePanel extends JPanel { 
     public static final String DIRECTORY = "directory"; 
     public static final String FILE = "file"; 
     public static final String COMPUTER = "computer"; 
     public static final String HARD_DRIVE = "harddrive"; 
     public static final String FLOPPY = "floppy"; 

     Map<String, Image> images = new HashMap<>(); 

     private Image currentImage; 

     public ImagePanel() { 
      initImageMap(); 
      repaintBackground(DIRECTORY); 
     } 

     private void initImageMap() { 
      ImageIcon dirIcon = (ImageIcon)UIManager.getIcon("FileView.directoryIcon"); 
      ImageIcon fileIcon =(ImageIcon)UIManager.getIcon("FileView.fileIcon"); 
      ImageIcon compIcon = (ImageIcon)UIManager.getIcon("FileView.computerIcon"); 
      ImageIcon hdIcon = (ImageIcon)UIManager.getIcon("FileView.hardDriveIcon"); 
      ImageIcon flopIcon = (ImageIcon)UIManager.getIcon("FileView.floppyDriveIcon"); 
      images.put(DIRECTORY, dirIcon.getImage()); 
      images.put(FILE, fileIcon.getImage()); 
      images.put(COMPUTER, compIcon.getImage()); 
      images.put(HARD_DRIVE, hdIcon.getImage()); 
      images.put(FLOPPY, flopIcon.getImage()); 
     } 

     protected void repaintBackground(String key) { 
      currentImage = images.get(key); 
      repaint(); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.drawImage(currentImage, 0, 0, getWidth(), getHeight(), this); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(150, 150); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable(){ 
      public void run() { 
       new ImageChangeDemo(); 
      } 
     }); 
    } 
} 
+1

이것은 훌륭했습니다! 고맙습니다! – Ofek

2

먼저 이미지 초기화 및 그리기. 페인트에서 img로드를 이동하십시오. 또한 파일을 만들지 마십시오. JAR 파일 내의 이미지를 생성 할 수 없었던 경우.

public PreviewPane() { 
    super(); 
    setOpaque(false); 
    StyledDocument document = this.getStyledDocument(); 
    SimpleAttributeSet center = new SimpleAttributeSet(); 
    StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER); 
    document.setParagraphAttributes(0, document.getLength(), center, false); 
} 

BufferedImage img = null; 

private void initImg() { 
    if(img==null) { 
     img = ImageIO.read(getClass().getResourceAsStream("/icons/"+_name+".png"))); 
//process missing img here 
    } 
} 

@Override 
protected void paintComponent(Graphics g) throws RuntimeException{ 
    g.setColor(Color.WHITE); 
    g.fillRect(0, 0, getWidth(), getHeight()); 
    initImg(); 

    BufferedImage img = null; 

    g.drawImage(img, 0, 0, this); 


    super.paintComponent(g); 
} 
+1

이것 역시 paintComponent 안에 이미지를로드하고 있습니다;) – Stefan

+0

이것은 또한 나에게 예외를주는 것처럼 보입니다 :) – Ofek

+0

@Stefan은 처음으로 그리고 물론 그것은 예를 들어. 생성자 – StanislavL