尝试在运行时更改JTextPane的背景,但是成功但有错误

时间:2014-10-07 11:55:42

标签: java swing nullpointerexception jtextpane

所以我有一个JTextPane对象需要在运行时将其背景更改为特定图像的背景。我所拥有的似乎非常多(JComboBox用于更改背景并调用repaintBackground()似乎不会在选择时自动关闭等),它也会抛出一个nullpointer而我不知道为什么背景变化。

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

    }

}

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:4)

  1. paintComponent(this.getGraphics()); - 。您永远不必明确调用paintComponent。而是致电repaint()

  2. 应该在super.paintComponent(g);方法的开头调用
  3. paintComponent,或者至少在使用Graphics上下文进行任何绘制之前调用。

  4. 请勿使用paintComponent方法加载图片。一种选择是将缓存保留在Map<String, Image>中。这样您就可以轻松地引用它们,而无需在每次想要更改时加载它们。总的来说,无论你是否决定缓存它们,它都不是 的大问题。您只需在repaintBackground方法中加载它。

  5. 保留班级成员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);
        }
    }
    
  6. paintComponent不应抛出RuntimeException

  7. 这是一个完整的例子。我决定使用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 :(得分: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);
}