简体   繁体   中英

Why does the paint clear on my JPanel whenever the JFrame is resized?

Go ahead, test the code. When the program is running, you can draw on the panel, but whenever it resized, the paint disappears. Any idea why or how to solve this? I would love the help!

Window.java --The GUI class

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.JToolBar;

public class Window extends JFrame implements ComponentListener {

    public Window(){

        this.setSize(700, 700);
        this.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        this.setJMenuBar(menubar);
        this.add(new PaintPanel());
        this.setTitle("JPaint");
        this.setBackground(Color.WHITE);
        this.add(TOOL_BAR, BorderLayout.NORTH);
        TOOL_BAR.add(BUTTON);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        this.add(PAINT_PANEL);
        menubar.add(FILE);
        FILE.setMnemonic(KeyEvent.VK_F);
        FILE.add(NEW);
        FILE.add(NEW_OPEN_SEPARATOR);
        FILE.add(OPEN);
        FILE.add(SAVE);
        FILE.add(SAVE_AS);
        FILE.add(SEPARATOR);
        FILE.add(EXIT);
        menubar.add(Box.createHorizontalGlue());
        menubar.add(HELP);
        HELP.add(ABOUT);
        HELP.add(GNU_PUBLIC_LICENSE);

        this.setVisible(true);

        NEW.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                PAINT_PANEL.repaint();

            }

        });

        OPEN.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                final JFileChooser FILE_CHOOSER = new JFileChooser();
                int CHOSEN_FILE = FILE_CHOOSER.showOpenDialog(FILE_CHOOSER);

            }

        });

        SAVE.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                final JFileChooser SAVE_FILE_CHOOSER = new JFileChooser();
                SAVE_FILE_CHOOSER.showSaveDialog(null);
                Container c = frame.getContentPane();
                BufferedImage SAVED_IMAGE = new BufferedImage(c.getWidth(), c
                        .getHeight(), BufferedImage.TYPE_INT_ARGB);
                c.paint(SAVED_IMAGE.getGraphics());
                try {
                    ImageIO.write(SAVED_IMAGE, "PNG", new File("test.png"));
                } catch (IOException e1) {
                    // If unable to save image for 'Exception' reason.
                    e1.printStackTrace();
                }

            }

        });

        EXIT.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);

            }

        });

        ABOUT.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                JOptionPane
                        .showMessageDialog(frame,
                                "Created by Matthew Hanzelik for "
                                        + "open source use!");

            }

        });
        GNU_PUBLIC_LICENSE.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(frame, "gpl.txt");

            }

        });

    }

    /**
     * Serial Version
     */
    private static final JFrame frame = new JFrame();

    private static final long serialVersionUID = 5259700796854880162L;

    private static final JMenuBar menubar = new JMenuBar();
    private static final JMenu FILE = new JMenu("File");
    private static final JMenu HELP = new JMenu("Help");
    private static final JMenuItem SAVE = new JMenuItem("Save");
    private static final JMenuItem EXIT = new JMenuItem("Exit");
    private static final JSeparator SEPARATOR = new JSeparator();
    private static final JSeparator NEW_OPEN_SEPARATOR = new JSeparator();
    private static final JMenuItem NEW = new JMenuItem("New");
    private static final JMenuItem OPEN = new JMenuItem("Open");
    private static final JMenuItem SAVE_AS = new JMenuItem("Save as...");
    private static final JMenuItem ABOUT = new JMenuItem("About");
    private static final JMenuItem GNU_PUBLIC_LICENSE = new JMenuItem(
            "GNU Public License");
    private static final JToolBar TOOL_BAR = new JToolBar();
    private static final JButton BUTTON = new JButton("Test");
    private static final PaintPanel PAINT_PANEL = new PaintPanel();

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Window GUI = new Window();
            }

        });

    }

    @Override
    public void componentHidden(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentMoved(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentResized(ComponentEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("resized");
    }

    @Override
    public void componentShown(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }

}

PaintPanel --The class that contains the panel on which to paint on

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PaintPanel extends JPanel {
    MouseMotionListener theListener;
    Graphics g;
    MouseListener theListening;
    int x, y, x1, y1;
    boolean inside;

    public PaintPanel() {
        x = 0;
        y = 0;
        x1 = -99;
        y1 = -99;
        inside = false;
        theListener = new MouseMotionListener() {
            public void mouseDragged(MouseEvent arg0) {
                if (inside) {
                    repaint();
                }
            }

            public void mouseMoved(MouseEvent arg0) {
            }
        };
        theListening = new MouseListener() {

            public void mouseClicked(MouseEvent arg0) {

            }

            public void mousePressed(MouseEvent arg0) {

            }

            public void mouseReleased(MouseEvent arg0) {
                x1 = -99;
                y1 = -99;
            }

            public void mouseEntered(MouseEvent arg0) {
                inside = true; 
                x1 = -99;
                y1 = -99; 
            }

            public void mouseExited(MouseEvent arg0) {
                inside = false; 
                x1 = -99;
                y1 = -99;
            }
        };
        this.setBackground(Color.WHITE);
        this.setVisible(true);
        this.addMouseMotionListener(theListener);
        this.addMouseListener(theListening);
    }

    @Override
    public void paint(Graphics g) {

        try {
            if (x1 == -99) { 


                x = getMousePosition().x;
                x1 = x; 
                y = getMousePosition().y;
                y1 = y; 
            } else
            {
                x = getMousePosition().x;
                y = getMousePosition().y;
                g.drawLine(x, y, x1, y1);
                x1 = x;
                y1 = y;
            }
        } catch (Exception ex) {
        }
    }
}

Two things: first, when extending a JComponent , you should really override paintCompontent , not paint .

Secondly, inside of your paintComponent , you need to render all of the lines that the user has drawn. This means that you need to store them as they are drawn, and then render them all inside of paintComponent every time. This is because paintComponent gets called any time the window needs to be re-rendered (for example, when the window has been minimized and then restored). Swing does not "remember" which pixels you've set to which colors in this case. Instead, it calls paintComponent and expects you to re-create them.

Also, when you override paintComponent , you will most likely want to call super.paintComponent before doing any of your rendering work.

, but whenever it resized, the paint disappears. Any idea why or how to solve this?

If you want to do incremental painting then there are two common approaches:

  1. Keep an ArrayList of the Objects you want to paint and then repaint all the Object every time the component is repainted.
  2. Paint your objects directly to a BufferedImage. Then the BufferedImage will be repainted automatically every time.

See Custom Painting Approaches for more information and working examples of each approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM