edi233
edi233

Reputation: 3031

Java Swing and drawing problem

I have a problem with drawing. I have a frame with one button. Using the mouse, I draw a transculent rectangle. But I have a small problem, because when drawing this rectangle, it is drawing behind the button and I want this rectangle to be over the button.

This is a screenshot:

And this is the code:

package draw;

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


public class Selection extends JPanel
    implements  ChangeListener {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private static final int WIDE = 640;
    private static final int HIGH = 640;  
    private List<Node> nodes = new ArrayList<Node>();
    private Point mousePt = new Point(WIDE / 2, HIGH / 2);
    private Rectangle mouseRect = new Rectangle();
    private boolean selecting = false;

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

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

    Selection() {
        JButton but=new JButton("Button");
        add(but);

        this.setPreferredSize(new Dimension(WIDE, HIGH));      
        this.addMouseListener(new MouseHandler());
        this.addMouseMotionListener(new MouseMotionHandler());
    }

    @Override
    public void paintComponent(Graphics g) {
        g.setColor(new Color(0x00f0f0f0));
        g.fillRect(0, 0, getWidth(), getHeight());


            g.setColor(Color.BLACK);
            ((Graphics2D) g).setComposite(AlphaComposite.getInstance(rule, alpha));
            g.fillRect(mouseRect.x, mouseRect.y,
                    mouseRect.width, mouseRect.height);

            g.drawRect(mouseRect.x, mouseRect.y,
                mouseRect.width, mouseRect.height);

    }
    int rule = AlphaComposite.SRC_OVER;
    float alpha = 0.85F;


    private class MouseHandler extends MouseAdapter {

        @Override
        public void mouseReleased(MouseEvent e) {
            selecting = false;
            mouseRect.setBounds(0, 0, 0, 0);
            if (e.isPopupTrigger()) {

            }
            e.getComponent().repaint();
        }

        @Override
        public void mousePressed(MouseEvent e) {
            mousePt = e.getPoint();

                Node.selectNone(nodes);
                selecting = true;          
            e.getComponent().repaint();
        }      
    }

    private class MouseMotionHandler extends MouseMotionAdapter {


        @Override
        public void mouseDragged(MouseEvent e) {
            if (selecting) {
                mouseRect.setBounds(
                    Math.min(mousePt.x, e.getX()),
                    Math.min(mousePt.y, e.getY()),
                    Math.abs(mousePt.x - e.getX()),
                    Math.abs(mousePt.y - e.getY()));

            } 
            e.getComponent().repaint();
        }
    }



    /** A Node represents a node in a graph. */
    private static class Node {

        private Color color;

        private boolean selected = false;
        private Rectangle b = new Rectangle();

        /** Draw this node. */
        public void draw(Graphics g) {
            g.setColor(this.color);

            if (selected) {
                g.setColor(Color.darkGray);
                g.drawRect(b.x, b.y, b.width, b.height);
            }
        }




       /** Mark this node as slected. */
         public void setSelected(boolean selected) {
            this.selected = selected;
        }

        /** Select no nodes. */
        public static void selectNone(List<Node> list) {
            for (Node n : list) {
                n.setSelected(false);
            }
        }
  }



    @Override
    public void stateChanged(ChangeEvent arg0) {
        // TODO Auto-generated method stub

    }

}

How can I solve this problem?

Upvotes: 1

Views: 1212

Answers (3)

camickr
camickr

Reputation: 324088

Normally custom painting is done by overriding the paintComponent() method. So the painting order is to paint the component and then the children are painted. So the button is painted on top of the rectangle.

In this case you want the rectangle to be painted after the children so you can do this by overriding the paint() method. Now the panel and its children will be painted. Then your rectangle will be painted so it gets painted on top of the button.

So your basic code should be:

    @Override
    public void paint(Graphics g)
    {
        super.paint(g); // added this

        g.setColor(new Color(0x00f0f0f0));
//      g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.BLACK);
        ((Graphics2D) g).setComposite(AlphaComposite.getInstance(rule, alpha));
        g.fillRect(mouseRect.x, mouseRect.y, mouseRect.width, mouseRect.height);
        g.drawRect(mouseRect.x, mouseRect.y, mouseRect.width, mouseRect.height);
    }

Upvotes: 1

Boro
Boro

Reputation: 7943

Why don't you do the drawing on the glass pane which you can get from a frame. For how to do it check out the tutorial.

You should have all your painting code in a class that extends JPanel. Then create an object and set it as the glasspane of your frame. Plus you must remember to set it to visible as it is hidden by default.

Upvotes: 2

aioobe
aioobe

Reputation: 420921

You draw the rectangle on the panel that is behind the button. (There's no way to let an underlying component draw on top of a child component.) If the rectangle should be on top of the button, the component you're drawing on must be on top of the button. (Such component has to be non-opaque though, since if it was opaque, it would always cover the button and the button wouldn't be visible.

I'd suggest you draw the rectangle on some glass-pane or something, which lies on top of the whole frame.

Upvotes: 4

Related Questions