Home / Programmazione / Java / Disegnare su JPanel
Mattepuffo

Disegnare su JPanel

Disegnare su JPanel

Torniamo a parlare un pò di Java (che purtroppo ho dovuto un pò tralasciare per poco tempo).

Oggi vediamo come poter disegnare un rettangolo con il mouse su un JPanel.

Inoltre dovrà implementare MouseListener e MouseMotionListener e i metodi derivati:

  • mousePressed
  • mouseDragged
  • mouseReleased
  • mouseClicked
  • mouseEntered
  • mouseExited
  • mouseMoved

Gli ultimi 4 metodi però rimarrano vuoti perchè non ci serviranno.

Vediamo come strutturare il tutto:

public class FrameDraw extends JFrame {

    private JScrollPane scroll;
    private int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); // DIMENSIONE JPANEL
    private int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); // DIMENSIONE JPANEL

    public FrameDraw() {
        super("Draw panel");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout());
        ImagePanel panel = new ImagePanel();
        scroll = new JScrollPane(panel);
        add(scroll, BorderLayout.CENTER);
    }

// CLASSE PRIVATA JPANEL.

}

Questo è il JFrame principale; ImagePanel sarà il JPanel che andremo ad inserire come classe privata.

A questo punto vediamo il JPanel:

private class ImagePanel extends JPanel implements MouseListener, MouseMotionListener {

    private Rectangle currentRect;
    private int xx = 0;
    private int yy = 0;
    private int w = 0;
    private int h = 0;
    boolean done = false;

    public ImagePanel() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(width, height));
        try {
            addMouseListener(this);
            addMouseMotionListener(this);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage());
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        xx = e.getX();
        yy = e.getY();
        currentRect = new Rectangle(xx, yy, 0, 0);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        currentRect.setSize(e.getX() - currentRect.x, e.getY() - currentRect.y);
        repaint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        w = e.getX() - currentRect.x;
        h = e.getY() - currentRect.y;
        currentRect.setSize(w, h);
        done = true;
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(buff, 0, 0, this);
        if (done) {
            g.setColor(Color.RED);
            g.drawRect(xx, yy, w, h);
        }
    }

}

Questo è quello che ci serve nello specifico (alla fine metterò il codice completo).

Nel costruttore aggiungiamo due listener.

Sotto facciamo l'Override di alcuni metodi:

  • mousePressed serve per cominciare il tutto.
  • mouseDragged serve per calcolare le dimensione del rettangolo mentre il mouse viene trascinato.
  • mouseReleased invece calcola le coordinate finali.

Infine c'è paintComponent che si occupa di disegnare il rettangolo se tutto è andato a buon fine.

Il controllo viene fatto usando la variabile boolean done, che diventa true alla fine di mouseReleased.

In caso di esito positivo viene settato il colore sul rosso e poi disegnato il rettangolo.

Badate che prima deve essere richiamato setColor e poi drawRect; in caso contrario non verrà disegnato nulla.

Quindi in totale:

public class FrameDraw extends JFrame {

    private JScrollPane scroll;
    private int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); // DIMENSIONE JPANEL
    private int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); // DIMENSIONE JPANEL

    public FrameDraw() {
        super("Draw panel");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLayout(new BorderLayout());
        ImagePanel panel = new ImagePanel();
        scroll = new JScrollPane(panel);
        add(scroll, BorderLayout.CENTER);
    }

    private class ImagePanel extends JPanel implements MouseListener, MouseMotionListener {

        private Rectangle currentRect;
        private int xx = 0;
        private int yy = 0;
        private int w = 0;
        private int h = 0;
        boolean done = false;

        public ImagePanel() {
            setLayout(new BorderLayout());
            setPreferredSize(new Dimension(width, height));
            try {
                addMouseListener(this);
                addMouseMotionListener(this);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(null, ex.getMessage());
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
            xx = e.getX();
            yy = e.getY();
            currentRect = new Rectangle(xx, yy, 0, 0);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            currentRect.setSize(e.getX() - currentRect.x, e.getY() - currentRect.y);
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            w = e.getX() - currentRect.x;
            h = e.getY() - currentRect.y;
            currentRect.setSize(w, h);
            done = true;
            repaint();
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(buff, 0, 0, this);
            if (done) {
                g.setColor(Color.RED);
                g.drawRect(xx, yy, w, h);
            }
        }

        @Override
        public void mouseClicked(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }

        @Override
        public void mouseMoved(MouseEvent e) {
        }

    }

}

Enjoy!