0

Okay So I looked through multiple forums and Google and couldn't find an answer to my specific problem. So I have two panels stacked on top of each other and the one on top is a glassPane. When you drag your mouse around the glassPane it draws a vertical red line at the cursor,which works, but when I click on the glassPane I want it it draw a black line at the cursor position on the panel below the glassPane. I can get it to redirect the mouseClick to the bottom panel but it wont draw the line. It just makes the redline disappear until you move the mouse again. Also If I set the glassPane invisible and click on the bottom panel the line is drawn so the drawing code works just fine. Thanks in advance.

Main Class

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Robot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
public class LiveField extends JPanel {

/**
 * Create the panel.
 */
static JFrame frame;
static JPanel ContentPane;
private JPanel panel;
private MyGlassPane glassPane;
public static void main(String[] args) throws AWTException
{
    LiveField live = new LiveField();
    frame.setVisible(true);
}
public LiveField() throws AWTException {
    frame = new JFrame("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(1000, 433);
    setLayout(new BorderLayout(0, 0));

    ContentPane = new JPanel();
    frame.setContentPane(ContentPane);
    ContentPane.setLayout(new BorderLayout(0, 0));

    panel = new JPanel()
    {
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            panel.setBackground(new Color(50,160,55));
        }
    };
    glassPane = new MyGlassPane(panel);
    frame.setGlassPane(glassPane);
    glassPane.setVisible(true);
    panel.addMouseListener(new MouseAdapter() {
        int[] pos = new int[2];
        @Override
        public void mouseClicked(MouseEvent e) {
            System.out.println("Handles click event");
            Graphics g = panel.getGraphics();
            g.setColor(new Color(50,165,55));
            g.drawLine(pos[0], pos[1], 0+pos[0], 0);//to top
            g.drawLine(pos[0], pos[1], 0+pos[0], panel.getHeight());//to bottom
            int y = e.getYOnScreen();
            int x = e.getXOnScreen();
            pos[0]= x;
            pos[1] = y;
            g.setColor(new Color(0,0,0));
            g.drawLine(x, y, 0+x, 0);//to top
            g.drawLine(x, y, 0+x, panel.getHeight());//to bottom
            g.dispose();


        }
    });

    ContentPane.add(panel, BorderLayout.CENTER);
}

GlassPane Class

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JComponent;

class MyGlassPane extends JComponent implements ItemListener {
  Point point;



protected void paintComponent(Graphics g) {
}

public void setPoint(Point p) {
    point = p;
}

public MyGlassPane(final Container contentPane) throws AWTException {
    final Component glass = this;
    addMouseMotionListener(new MouseMotionListener()

    {
        ArrayList<Integer> line = new ArrayList<Integer>();
        Robot rb = new java.awt.Robot();
        @Override
        public void mouseMoved(MouseEvent e) {
            //System.out.println("Moving");
            Graphics g = glass.getGraphics();
            if(!line.isEmpty())
            {
                //System.out.println("line is not empty");
                g.setColor(new Color(50,160,55));
                g.drawLine(line.get(0), line.get(1), 0+line.get(0), 0);//to top
                g.drawLine(line.get(0), line.get(1), 0+line.get(0), contentPane.getHeight());//to bottom
            }

                //System.out.println("draw line");
                int x = e.getXOnScreen();
                int y = e.getYOnScreen();
                Color col = rb.getPixelColor(x, y);

                //System.out.println(col.toString() + " : " + Color.white.toString());
                //System.out.println(col.equals(new Color(255,255,255)));
                if(!col.equals(new Color(255,255,255)) && !inEndZone(x))
                {
                    g.setColor(new Color(255,0,0));
                    line = new ArrayList<Integer>();
                    line.add(x);line.add(y);
                    g.drawLine(x, y, 0+line.get(0), 0);//to top
                    g.drawLine(x, y, 0+line.get(0), contentPane.getHeight());//to bottom
                }

                g.dispose();
        }
        private boolean inEndZone(int x) {
            int ends = contentPane.getWidth()/10;
            //System.out.println(x + " : " + ends);
            if(x<ends)
            {
                //System.out.println("In endzone");
                return true;
            }
            else if(x>contentPane.getWidth()-ends)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        @Override
        public void mouseDragged(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    });
    addMouseListener(new CBListener(this,contentPane));
}

@Override
public void itemStateChanged(ItemEvent e) {
    // TODO Auto-generated method stub
    setVisible(e.getStateChange() == ItemEvent.SELECTED);
}

}

Listener Class ( for dispatching the mouse click)

import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;

class CBListener extends MouseInputAdapter {
Toolkit toolkit;
Robot rb;
MyGlassPane glassPane;
Container contentPane;

public CBListener(MyGlassPane glassPane, Container contentPane) {
    toolkit = Toolkit.getDefaultToolkit();
    this.glassPane = glassPane;
    this.contentPane = contentPane;
}


    @Override
public void mouseClicked(MouseEvent e) {
    redispatchMouseEvent(e, false);
}

// A basic implementation of redispatching events.
private void redispatchMouseEvent(MouseEvent e, boolean repaint) {
    Point glassPanePoint = e.getPoint();
    Container container = contentPane;
    Point containerPoint = SwingUtilities.convertPoint(glassPane,
            glassPanePoint, contentPane);
    if (containerPoint.y < 0) { // we're not in the content pane
    } else {
        // The mouse event is probably over the content pane.
        // Find out exactly which component it's over.
        Component component = SwingUtilities.getDeepestComponentAt(
                container, containerPoint.x, containerPoint.y);

        if ((component != null) && (component.equals(contentPane))) {
            System.out.println("contentPane");
            // Forward events over the check box.
            Point componentPoint = SwingUtilities.convertPoint(glassPane,
                    glassPanePoint, component);
            component.dispatchEvent(new MouseEvent(component, e.getID(), e
                            .getWhen(), e.getModifiers(), componentPoint.x,
                            componentPoint.y, e.getClickCount(), e
                                    .isPopupTrigger()));
        }
    }

    // Update the glass pane if requested.
    if (repaint) {
        glassPane.setPoint(glassPanePoint);
        glassPane.repaint();
    }
}

}

staticFlow
  • 141
  • 1
  • 2
  • 13

2 Answers2

1

I can get it to redirect the mouseClick to the bottom panel but it wont draw the line. It just makes the redline disappear until you move the mouse again

No, It is drawing black line indeed. But the line is drawn above the red line that makes the red line to vanish till the mouse is moved again . I Guess you are looking for something like this:

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

class  DoublePanel extends JFrame
{
    JPanel mainPanel;
    int x1;
    public void prepareAndShowGUI()
    {
        setTitle("DoublePanel");
        mainPanel = new JPanel()
        {
            @Override
            public void paintComponent(Graphics g)
            {
                super.paintComponent(g);
                g.setColor(Color.BLACK);
                g.drawLine(x1,0,x1,this.getHeight());
            }
        };
        mainPanel.setBackground(new Color(50,160,55));
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(new upperPanel(this));
        setContentPane(mainPanel);
        setSize(500,600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setVisible(true);
    }
    public void setXValue(int x)
    {
        this.x1 = x;
        mainPanel.repaint();
    }
    class upperPanel extends JPanel
    {
        int x; int y;
        DoublePanel dp;
        upperPanel(DoublePanel d)
        {
            this.dp = d;
            setOpaque(false);
            addMouseMotionListener(new MouseAdapter()
            {
                @Override
                public void mouseMoved(MouseEvent evt)
                {
                    x = evt.getX();
                    y = evt.getY();
                    repaint();
                }
            });
            addMouseListener(new MouseAdapter()
            {
                @Override
                public void mouseClicked(MouseEvent evt)
                {
                    dp.setXValue(evt.getX());
                }
            });
        }
        @Override
        public void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawLine(x,0,x,this.getHeight());
        }
    }
    public static void main(String st[])
    {
        SwingUtilities.invokeLater( new Runnable()
        {
            public void run()
            {
                DoublePanel dp = new DoublePanel();
                dp.prepareAndShowGUI();
            }
        });
    }
}
Vishal K
  • 12,976
  • 2
  • 27
  • 38
  • Thats a beautiful solution! Thank you so much! I never thought of just passing in a reference to the bottom panel, you live and learn! – staticFlow Mar 12 '13 at 20:36
0

You need to call the bottom panel's repaint().

Jean Waghetti
  • 4,711
  • 1
  • 18
  • 28
  • if I call panel.repaint() in the panels overridden paint method (see code above) it wont draw the lines at all. Even when not using the glass pane and doing it straight on the panel. – staticFlow Mar 12 '13 at 17:08
  • You are calling glass pane's repaint(), aren't you? You need to call the repaint() on the panel that is behind the glass pane. (Also, overriding glass pane's paintComponent() will clear it for you. But I didn't get if it is the expected behavior). – Jean Waghetti Mar 12 '13 at 17:40
  • if I put a repaint() method call anywhere in the mousClick method of the panel in MainClass it will not draw any lines at all. – staticFlow Mar 12 '13 at 18:51
  • From which object do you call repait()? You're only calling it on glassPane -> glassPane.repaint() in the end of the last class. Put contentPane.repaint() just before this. – Jean Waghetti Mar 12 '13 at 19:35
  • from the main class once it dispatches the mouseEvent it is suppost to draw the line on the panel, which I think I have it doing now but as soon as you move the mouse it deletes the black line. Also I tried that solution and it did not work. – staticFlow Mar 12 '13 at 20:23
  • But this action listener is in the contentPane, not in glassPane. You cannot click contentPane if glassPane is over it. – Jean Waghetti Mar 12 '13 at 21:01