How do I prevent the JPanel from updating?

I am creating a kind of drawing application. User can move the circle in JPanel by clicking / dragging the mouse.

I have JCheckBoxMenuItem

in one of my JMenu

s:

JCheckBoxMenuItem checkitem = new JCheckBoxMenuItem("Draw mode",false);

      

  • When not activated, the circle can only be moved (by dragging / clicking) and the previous circle will be deleted.
  • When activated, the circle can only be moved, but the previous circle will not be removed when dragging / clicking the mouse (this works the same as the paint program)

Shortened version of my code:

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

class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener, ItemListener
{
    JPanel mainPan, colorPan;
    Color color = Color.BLACK;
    JCheckBoxMenuItem checkitem;
    boolean clear = true;

    public GUI(String header)
    {
        maker();

        mainPan.addMouseListener(this);
        mainPan.addMouseMotionListener(this);

        add(mainPan , BorderLayout.CENTER);
        add(colorPan, BorderLayout.PAGE_END); 
    }

    public void maker()
    {
        colorPan = new JPanel();
        colorPan.setLayout(new GridLayout(1, 0));

        mainPan = new JPanel(){
            @Override
            public void paintComponent(Graphics g)
            {
                //g.setColor(Color.WHITE);
                //g.fillRect(0,0,getWidth(),getHeight());
                if(clear)
                    super.paintComponent(g); //Do the same thing as above(Clear JPanel)

                g.setColor(color);
                g.fillOval(x,y,50,50); //x and y are integer variables that I use in my full program
            }
        };

        checkitem = new JCheckBoxMenuItem("Draw mode",false);
        //After adding this to a JMenu,
        checkitem.addItemListener(this);
    }

    public void itemStateChanged(ItemEvent e)
    {
        if(e.getStateChange() == ItemEvent.SELECTED)
        {
            clear = false;
        }
        else
        {
            clear = true;
        }
    }
}

      

Below is a snapshot of my complete program:

SCREENSHOT

colorPan

- JPanel full of JButtons of different colors. Top of it mainPan

.

Right now, Draw mode is not working as expected. I always thought that super.paintComponent(g);

is the one that clears / resets the screen when called repaint()

. But I removed that and was very surprised to see that the program behaves the same.

Basically my problem is here:

if(clear)
    super.paintComponent(g);

      

I need to keep everything from being cleared when called repaint()

. How can I achieve what I want?

+3


source to share


2 answers


You cannot "prevent the update JPanel

"; paintComponent()

will be called asynchronously as required by the system. Instead, attribute the state of your view class so that your implementation paintComponent()

displays everything, whenever it is called.

In the example below, the foreground color changes with each mouse click and paintComponent()

uses the changed setting. The more complex example shown here ClearAction

clears List<Node>

and List<Edge>

, which define the graph model. In the absence of a call super.paintComponent(g)

, otherwise for an opaque component, calling fillRect()

in paintComponent()

clears any remaining selection artifacts.

public void actionPerformed(ActionEvent e) {
    nodes.clear();
    edges.clear();
    repaint();
}

      



image

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {

    private static final String TITLE = "Drag me!";
    private static final Random r = new Random();
    private static final int W = 640;
    private static final int H = 480;
    private Point textPt = new Point(W / 2, H / 2);
    private Point mousePt;
    private Color color = Color.black;

    public MouseDragTest() {
        this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                mousePt = e.getPoint();
                setColor(Color.getHSBColor(r.nextFloat(), 1, 1));
                repaint();
            }
        });
        this.addMouseMotionListener(new MouseMotionAdapter() {

            @Override
            public void mouseDragged(MouseEvent e) {
                int dx = e.getX() - mousePt.x;
                int dy = e.getY() - mousePt.y;
                textPt.setLocation(textPt.x + dx, textPt.y + dy);
                mousePt = e.getPoint();
                repaint();
            }
        });
    }

    public void setColor(Color color) {
        this.color = color;
    }

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

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(color);
        int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
        g.drawString(TITLE, textPt.x - w2, textPt.y);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame f = new JFrame(TITLE);
                f.add(new MouseDragTest());
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}

      

+1


source


It is not in this code where changes should be made. And this is not a paint method that should be changed. Paint paint whenever yours or over the system is required. When the window is resized or moved or partially covered, it uses paint again to paint the pattern. What you really have to do is stop updating the coordinates for your painted oval. This can be done in the mouse receiver, or in the coordinator, or better, in the control part that manages these coordinates. Your checkbox should control the ability to modify your model. He doesn't have to control painting. Typically the Model-View-Controller pattern is used- look at him. It might look like overkill for such a small application, but even Swing itself is built on this pattern, so you're already following it. Problems arise when you try to break it. So - don't.



+3


source







All Articles