2014-10-07 68 views
0

因此,我有一個JTextPane對象需要在運行時將其背景更改爲特定圖像的背景。我似乎有相當多的錯誤(JComboBox用於更改背景,並呼籲repaintBackground()似乎沒有autoclose選擇等),它也拋出一個空指針,我不知道爲什麼隨着背景的變化。嘗試在運行時更改JTextPane的背景,但成功但出錯

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.... 

這是我的目標:

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()); 

    } 

} 

任何幫助,將不勝感激。

+0

'保護無效paintComponent(圖形G)拋出的RuntimeException { .. IMG = ImageIO.read('哇一種油漆方法:1)不應該拋出運行時異常。 2)應立即調用超級方法。 3)不應該嘗試像加載圖像一樣可能長時間運行的任務! – 2014-10-07 12:08:31

+0

你會如何推薦避免這種情況? – Ofek 2014-10-07 12:09:37

+0

哪'這'?請明確點。 – 2014-10-07 12:10:24

回答

4
  1. paintComponent(this.getGraphics()); - NO。你不應該明確地打電話給paintComponent。請撥打repaint()

  2. super.paintComponent(g);應在堪稱開始paintComponent方法,或您與Graphics方面做任何噴漆至少前。

  3. 請勿將圖片加載到paintComponent方法中。一種選擇是將緩存保存在Map<String, Image>中。這樣,您可以輕鬆地引用它們,而無需在每次要更改時加載它們。總的來說,它不是巨大的問題,無論您是否決定緩存它們。您可以將其加載到repaintBackground方法中。保持班級成員Image image;。這將是您用於繪製的Image。你的repaintBackground,我會接受一個Image而不是一個字符串。您通過的Image將用於繪畫的班級成員Image image。如果您決定從該方法加載圖像,您仍然可以讓該方法接受字符串。

    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); 
        } 
    } 
    
  4. paintComponent不應該拋出一個RuntimeException

這裏有一個完整的例子。我決定使用Map緩存。它取決於你如何做到這一點。有很多方法可以處理這個問題。

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 2014-10-07 23:30:57

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 2014-10-07 12:34:54

+0

這也似乎給我例外:) – Ofek 2014-10-07 12:39:29

+0

@斯特凡只是第一次,當然它可以被移出去,例如,構造函數 – StanislavL 2014-10-07 13:44:12

相關問題