I am struggling with a problem I have. I have this program which draws a face (w/ an optional hat). I am trying to get it so that if the mouse /cursor is inside the component, two extra little horizontal lines (c1,c2) are drawn to make it appear as if the eyes are closed. I am trying to use the mouse listener unsuccessfully and I was hoping someone may have some suggestions. Thanks
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.JCheckBox;
import java.awt.event.ItemListener;
import java.awt.event.*;
import javax.swing.event.ChangeListener;
public class Head extends JPanel implements MouseListener
{
private Ellipse2D.Double e1;
private Ellipse2D.Double e2;
private Ellipse2D.Double e3;
private Ellipse2D.Double e4;
private Ellipse2D.Double e5;
private Rectangle2D.Double r1;
private Ellipse2D.Double r2;
private Line2D.Double c1;
private Line2D.Double c2;
private JCheckBox check = new JCheckBox("Hat");
private int i;
public Head () {
this.setPreferredSize (new Dimension (600,600));
e1 = new Ellipse2D.Double(200,200, 200, 300);
e2 = new Ellipse2D.Double(255,285, 20, 10); //eyes
e3 = new Ellipse2D.Double(325,285, 20, 10); //eyes
e4 = new Ellipse2D.Double(285, 345, 30,30);
e5 = new Ellipse2D.Double(265,410, 75, 20);
r2 = new Ellipse2D.Double (90,175, 450,75);
r1 = new Rectangle2D.Double (200,110,200,115);
c1 = new Line2D.Double (255, 290, 275, 290 ); //horizontal lines across ayes
c2 = new Line2D.Double (325, 290, 345, 290 ); //horizontal lines across ayes
this.add(check);
//a separate itemlistener
class itemlistener implements ItemListener {
public void itemStateChanged(ItemEvent check){
repaint();
}
}
check.addItemListener(new itemlistener());
}
public void update(Graphics g) {
paint(g);
}
//All the mouselistening methods. Im only using exit and entered
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
i= 0;
}
public void mouseExited(MouseEvent e) {
i = 1;
}
public void mouseClicked(MouseEvent e) {
}
//this is a boolean method that is called is i==0 /mouse is inside to draw the lines
public boolean mouseInside(){
return (i==0);
}
public void paintComponent (Graphics g) {
// The first two lines are magic incantations to be explained in 209.
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g; // convert to better Graphics2D
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON); // looks nicer
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(e1); // draw the rectangle
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(e2); // draw the rectang
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(e3); //
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(e4); //
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(e5); //
if(check.isSelected()) {
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(r2); //
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(r1); //
}
//this is a method to draw the lines if the mouse is inside
if (mouseInside()){
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(c1); //
g2.setStroke(new BasicStroke(3.0f));
g2.setPaint(Color.BLACK);
g2.draw(c2);
}
}
public static void main(String[] args) {
JFrame f = new JFrame("ShapePanel demo");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new FlowLayout());
// Let's add two separate ShapePanel instances, just to see how it works.
f.add(new Head());
f.pack();
f.setVisible(true);
}
}
You haven't added any mouse listener to the panel. You need to add this line:
this.addMouseListener(this);
(it would be cleaner if the panel itself was not a mouse listener, and if you used a separate, inner class for the listener).
Moreover, the mouse listener changes the value of i
, but doesn't ask the panel to repaint itself. So you need this line in the mouseEntered()
and mouseExited()
methods:
repaint();
Also, note that the main method should use SwingUtilities.invokeLater()
to construct and display the frame in the event disptach thread, and that you shouldn't override update()
.