Hello java programmers,
I want to draw some squares on layers using Graphics2D, course.
Here is my source code with problems:

import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

public class Draw extends JPanel {
	
	private static final long serialVersionUID = 1L;
	
	private List<Cube> cubes = new ArrayList<Cube>();

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

            public void run() {
                JFrame f = new JFrame("Draw");
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Draw gp = new Draw();
                f.add(gp, BorderLayout.CENTER);
                f.pack();
                f.setVisible(true);
            }
        });
    }

    Draw() {
        this.setPreferredSize(new Dimension(400, 300));
        
		Cube c1 = new Cube(new Point(10, 20), Color.red);
        cubes.add(c1);
        
		Cube c2 = new Cube(new Point(20, 30), Color.blue);
        cubes.add(c2);
        
		Cube c3 = new Cube(new Point(30, 40), Color.magenta);
        cubes.add(c3);
        
		Cube c4 = new Cube(new Point(40, 50), Color.green);
        cubes.add(c4);
        
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
    	   Graphics2D g2d = (Graphics2D)g;
    	   g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    	                        RenderingHints.VALUE_ANTIALIAS_ON);
    	   g2d.setColor(new Color(0x00f0f0f0));
    	   g2d.fillRect(0, 0, getWidth(), getHeight());
        for (Cube c : cubes) {
            c.draw(g2d);
        }
    }

    private static class Cube {

        private Point p;
        private Color color;
        
        public Cube(Point p, Color color) {
            this.p = p;
            this.color = color;
        }
        
        public void draw(Graphics g) {
            g.setColor(this.color);
            g.fillRoundRect(p.x, p.y, 64, 64, 6, 6);
        }
        
    }

}

After I added the four squares:

Cube c1 = new Cube(new Point(10, 20), Color.red);
        cubes.add(c1);
        
		Cube c2 = new Cube(new Point(20, 30), Color.blue);
        cubes.add(c2);
        
		Cube c3 = new Cube(new Point(30, 40), Color.magenta);
        cubes.add(c3);
        
		Cube c4 = new Cube(new Point(40, 50), Color.green);
        cubes.add(c4);

The four squares can be seen, depending on the order added.
But I want to move the blue cube above all clubs (on top) without changing the order of adding cubes.
Similar to:

Cube c1 = new Cube(new Point(10, 20), Color.red);
        cubes.add(c1);
        
		Cube c2 = new Cube(new Point(20, 30), Color.blue);
                [B][U]c2.setLayer(1);[/U][/B]
        cubes.add(c2);
        
		Cube c3 = new Cube(new Point(30, 40), Color.magenta);
        cubes.add(c3);
        
		Cube c4 = new Cube(new Point(40, 50), Color.green);
        cubes.add(c4);

How can I do this?
Can someone help me?
We thank you!

Dani AI

Generated

Simple rule: whatever you draw last is on top. That means “layers” are just a drawing order you control. was right to suggest giving each Cube a layer value and ordering shapes by that value before painting; is also correct to insist on doing custom painting in paintComponent and letting Swing clear the background first. ’s cubes.set(...) approach works for a quick hack, but it becomes fragile as the app grows.

Practical, robust options you can use immediately:

  • Give each Cube two fields: an int layer and a final int insertionSequence assigned when the Cube is created. Maintain your master list in insertion order. When you need to draw, build a small view list (copy the master), sort that view by (layer, insertionSequence) so ties preserve original order, then iterate the view and render. Only re-sort the view when a layer actually changes — avoid sorting on every repaint.
  • If you only need “bring-to-front / send-to-back” on user actions, simply remove the cube from the drawing list and re-add it in the desired position (end = top). That is simpler and faster than a full sort.
  • If each cube is a Swing component, prefer JLayeredPane or setComponentZOrder instead of custom drawing.

Practical tips: do list mutations on the EDT (Swing event handlers already run there), call repaint() after changes, and cache the sorted view when possible to avoid unnecessary work. This gives you reliable setLayer(...) semantics without relying on index gymnastics.

Recommended Answers

All 7 Replies

you could do something like this... its not much of a code change.

public void paint(Graphics g) 
        {
        // need to call the original paint method to paint the   	
        // panel itself.. 
            super.paint(g);
            g.setColor(color);
            //g.drawRect(5, 5, 200, 300);
            g.fillRect(draw_x, draw_y, width, height);
        }

please not

public void paint(Graphics g)

but

public void paintComponent(Graphics g)

it doesnt make a difference, the name of the class is irrelevant

You could add a layer instance variable to the cube class, then in the paintComponent (not paintComponents, not paint!) method sort the cubes on the layer variable before painting.
Or
Keep another list of cubes, this one in layer order. Shuffle the list when you want to change a cube's layer.
Or
Combine both for maximum efficiency

commented: You solved my problem with your great ideas. Rock. Thank you! +1

you are right not paintComponents but paintComponent for newbee

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class FullScreenFrame extends JFrame implements Runnable {

    private static final long serialVersionUID = 1L;
    public RenderablePanel redPanel, bluePanel;

    public static void main(String[] arg) {
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        d.setSize(d.width / 2, d.height);
        FullScreenFrame frame = new FullScreenFrame();
        frame.bluePanel = new RenderablePanel(Color.BLUE);
        frame.bluePanel.setPreferredSize(d);
        frame.redPanel = new RenderablePanel(Color.RED);
        frame.redPanel.setPreferredSize(d);
        frame.redPanel.add(new JButton("Click me"));
        frame.add(frame.bluePanel);
        frame.add(frame.redPanel);
        new Thread(frame).start();
    }

    public FullScreenFrame() {
        setUndecorated(true);
        setResizable(false);
        GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
        createBufferStrategy(2);
        setIgnoreRepaint(true);
        setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
        addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.exit(0);
            }
        });
        setVisible(true);
    }

    @Override
    public void run() {
        while (true) {
            BufferStrategy bStrategy = getBufferStrategy();
            Graphics g = null;
            try {
                g = bStrategy.getDrawGraphics();
                bluePanel.render(g);
                redPanel.render(g);
            } finally {
                if (g != null) {
                    g.dispose();
                }
            }
            if (!bStrategy.contentsLost()) {
                bStrategy.show();
            }
            Toolkit.getDefaultToolkit().sync();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class RenderablePanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private Color color;

    RenderablePanel(Color color) {
        this.color = color;
        setLayout(new FlowLayout());
    }

    public void render(Graphics g) {
        g.setColor(color);
        g.fillRect(getX(), getY(), getPreferredSize().width, getPreferredSize().height);
        paintComponents(g);
        revalidate();
    }
}

Our thanks go, first, to JamesCherrill. You saved the time to find a solution for solve this problem.
Then, thank those many gave a reply to this message.
I do not want to give you great detail how I solved the problem, but according to suggestions offered by JamesCherrill, I have done in the following way:
I set the index of cube blue from the list Cubes, from position 1, initial position to 3. Inside void MouseListener, I added this code:

cubes.set(3, c2);

Of course, followed by repaint();
And, Now, the blue cube is on top, above all cubes.
But it is much more complicated, not only that I did.
Thanks! If you have any idea about this problem, we expect answers.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.