I am not sure why the mouse events set by my mouse listener are not affecting whether or not the hat is drawn. The variable "mouseInside" seems not to be affected by the mouse events. How do I change the variable to false with the mouse events?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
public class EyesOpen extends JPanel{
private Ellipse2D.Double head;
private Ellipse2D.Double eyeOne;
private Ellipse2D.Double eyeTwo;
private Rectangle2D.Double hatBody;
boolean mouseInside;
public EyesOpen(){
this.setFocusable(true);
this.requestFocus();
this.setPreferredSize(new Dimension(500,500));
head = new Ellipse2D.Double(180,180,140,140);
eyeOne = new Ellipse2D.Double(220,220,20,20);
eyeTwo = new Ellipse2D.Double(260,220,20,20);
hatBody = new Rectangle2D.Double(170,180,160,20);
class MyMouseListener implements MouseListener{
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e){
mouseInside=true;
}
public void mouseExited(MouseEvent e){
mouseInside=false;
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
}
this.addMouseListener(new MyMouseListener());
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.BLUE);
g2.fill(head);
g2.setPaint(Color.BLACK);
g2.fill(eyeOne);
g2.setPaint(Color.BLACK);
g2.fill(eyeTwo);
if(mouseInside=true){
g2.setPaint(Color.BLACK);
g2.fill(hatBody);}
}
public static void main(String[] args){
JFrame f = new JFrame("Head");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLayout(new FlowLayout());
f.add(new EyesOpen());
f.pack();
f.setVisible(true);
}
}
Don't forget to call repaint() after changing the boolean.
To be precise, you could specify that it is the drawing component's method that gets called via EyesOpen.this.repaint();, but this isn't absolutely necessary in this current program (I don't think).
Other nitpicks:
The paintComponent(...) method should be specified as protected not public. No sense in exposing it any more than it needs to be exposed.
Don't forget to use the #Override annotation any time that you think that you're overriding a method. While it may not matter with this program, it will save your behind in the future.
You will want to start your GUI on the Swing thread in your main method by placing your JFrame creation code inside of a Runnable and then queuing that Runnable onto the event queue by placing it into a SwingUtilities.invokeLater(/** Your Runnable Goes Here **/);
Related
I am trying to animate a circle in Java. I want it to move every time I press a key, but it is not working. Is there a problem with the way I am drawing the circle? Am I forgetting a repaint() somewhere.
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel implements KeyListener {
int x = 300, y = 300;
public Main() {
super();
}
public void paintComponent(Graphics g) {
g.drawOval(x, y, 300, 300);
}
#Override
public void keyPressed(KeyEvent e) {
x++;
y++;
repaint();
}
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void keyReleased(KeyEvent e) {}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(1200, 800);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
f.add(new Main());
f.setVisible(true);
}
}
Don't use KeyListener, honestly, make use of the Key Bindings API instead, which has been designed to resolve the issues which KeyListener creates.
paintComponent in JPanel does an important job, you are expected to call it's super method before doing any custom painting.
See Painting in AWT and Swing and Performing Custom Painting for more details
You should also make an effort to initialise you UI from within the context of the Event Dispatching Thread, this solves a number of known issues on some platforms, see Initial Threads for more details
You are not very far off. First, you need to actually add a listener for your key events.
f.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
m.keyPressed(e);
}
});
Second, you'll notice this uses 'm'. That is a reference to your Main object.
Change:
f.add(new Main());
to:
Main m = new Main();
f.add(m);
Now it should work!
I searched all over the Internet but could not find out why the circle is appears to be distorted beyond the middle of the JFrame(sorry,no image because i needed 10 reputation to post images).
I checked my code but found no errors.I'm a newbie to java GUI programming .
This is my code so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class test1 extends JPanel implements MouseMotionListener
{
private static final long serialVersionUID = -2068330714634802982L;
public int Mousex,Mousey;
public void init()
{
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e)
{
Mousex=e.getX();
Mousey=e.getY();
repaint();
}
public void mouseDragged(MouseEvent e){}
public void paintComponent(Graphics g)
{
Graphics2D g2=(Graphics2D)g;
g2.setColor(Color.GREEN);
g2.fillOval(Mousex,Mousey,50,50);
}
public static void main(String[] args)
{
test1 t=new test1();
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1305,650);
frame.setLocationRelativeTo(null);
frame.getContentPane().add(t);
frame.setResizable(true);
frame.setVisible(true);
}
}
You need to call
t.init();
to register the MouseMotionListener. Also super.paintComponent(g); in the needs to be invoked in the paintComponent method to repaint the parent container otherwise the last rectangle wont be clearly visible.
You are never calling init() on your panel so you don't add the MouseMotionListener to the panel. Try adding
t.init();
after creating your panel object. Alternatively, add a constructor to your class that adds the MouseMotionListener instead, so it's adden right when you create an object of the class:
public test1 () {
addMouseMotionListener(this);
}
So I am trying to implement a mouse listener into my program, I got the mouseListener to work but not the graphics. I am trying to find a way to draw a blue circle every time the mouse is clicked on the JPANEL, the only problem is I can not seem to get a good call for the Graphics (that I have tried to name g).
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
class moveItMon extends JPanel implements MouseListener{
public moveItMon() {
this.setPreferredSize(new Dimension(500, 500));
addMouseListener(this);
}
public void addNotify() {
super.addNotify();
requestFocus();
}
public void mouseClicked(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e) {
movetehMon(e);
}
public void movetehMon(MouseEvent e){
int x = e.getX();
int y = e.getY();
System.out.println("(" + x + "," + y + ")");
paintMon(x,y);
}
public void paintMon( int x, int y){
Graphics g = new Graphics();
g.setColor(Color.WHITE);
g.clearRect(0,0,500,500);
g.setColor(Color.BLUE);
g.fillOval(x,y,20,20);
}
public static void main(String[] s) {
JFrame f = new JFrame("moveItMon");
f.getContentPane().add(new moveItMon());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
Graphics g = new Graphics(); isn't going to work (as I'm sure you're aware) as the class is abstract.
Custom painting in Swing is done by overriding the paintComponent of a component that extends from JComponent (like JPanel) and using the supplied Graphics context to paint to.
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
You should also beware that painting is a destructive process, meaning that each time paintComponent is called, you are expected to update everything that you need painted.
I have just started working with Swing and am trying to draw a button with a custom shape, a triangle in this example. I called the JButton subclass 'ShiftingButton' in the following code because of its unusual behavior. When the mouse enters its region, it is repainted with an offset from its original position. Furthermore the shifted, offset version is drawn in addition to the original position so that both the original and shifted versions appear together. That is, when I run this code, the button is shown as a triangle along the left edge of the window. Then when I run the mouse over the button, a new triangle is drawn (in addition to the old one), shifted down and to the right by about 10 pixels. Resizing the window changes the offset of the phantom button from the original.
Experimenting with mouse clicks shows that only the original, correctly-positioned button is active. The region of the offset phantom button is not active.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.awt.Polygon;
public class ShiftingButton extends JButton implements ActionListener {
private Polygon shape;
public ShiftingButton () {
initialize();
addActionListener(this);
}
protected void initialize() {
shape = new Polygon();
setSize(120, 120);
shape.addPoint(0, 0);
shape.addPoint(0, 60);
shape.addPoint(90, 0);
setMinimumSize(getSize());
setMaximumSize(getSize());
setPreferredSize(getSize());
}
// Hit detection
public boolean contains(int x, int y) {
return shape.contains(x, y);
}
#Override
public void paintComponent (Graphics g) {
System.err.println("paintComponent()");
g.fillPolygon(shape);
}
protected void paintBorder(Graphics g) {
}
#Override
public void actionPerformed (ActionEvent ev) {
System.out.println("ShiftingButton ActionEvent!");
}
public static void main (String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
ShiftingButton button = new ShiftingButton();
panel.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
You failed to call super.paintComponent(g) inside the overridden paintComponent(...) method. Moreover, while overriding a method of the Base class, always try to keep the access specifier of the methods, the same, as much as possible. In this case it's protected and not public :-) Now function should be like this :
#Override
protected void paintComponent (Graphics g) {
System.err.println("paintComponent()");
super.paintComponent(g);
g.fillPolygon(shape);
}
EDIT 1 :
Moreover, since you are using a custom shape to be drawn, hence you again failed to specify the ContentAreaFilled property for this JButton in question, hence inside your constructor, you should write setContentAreaFilled(false), for it to work nicely. Though if this doesn't works (for reasons specified in the Docs), then you have to use the plain old Opaque property and set it to false for this JButton using setOpaque(false) :-)
Here is your code with modified changes :
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.awt.Polygon;
public class ShiftingButton extends JButton implements ActionListener {
private Polygon shape;
public ShiftingButton () {
setContentAreaFilled(false);
initialize();
addActionListener(this);
}
protected void initialize() {
shape = new Polygon();
setSize(120, 120);
shape.addPoint(0, 0);
shape.addPoint(0, 60);
shape.addPoint(90, 0);
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(120, 120));
}
// Hit detection
public boolean contains(int x, int y) {
return shape.contains(x, y);
}
#Override
protected void paintComponent(Graphics g) {
System.err.println("paintComponent()");
super.paintComponent(g);
g.fillPolygon(shape);
}
protected void paintBorder(Graphics g) {
}
#Override
public void actionPerformed (ActionEvent ev) {
System.out.println("ShiftingButton ActionEvent!");
}
public static void main (String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
ShiftingButton button = new ShiftingButton();
panel.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
am doing that program to paint the mouse location in a panel , the program works fine but after like 10 seconds it stops painting the points... any help?
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class Draw extends JPanel {
public static int newx;
public static int newy;
public void paint(Graphics g) {
Mouse mouse = new Mouse();
mouse.start();
int newx = mouse.x;
int newy = mouse.y;
g.setColor(Color.blue);
g.drawLine(newx, newy, newx, newy);
repaint();
}
public static void main(String[] args) {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.white);
frame.setSize(2000,2000 );
frame.setVisible(true);
frame.getContentPane().add(new Draw());
frame.revalidate();
frame.getContentPane().repaint();
}
}
public void paint(Graphics g) should be public void paintComponent(Graphics g).
And you isn't supposed to call repaint() inside this method.
You should add an mouse listener outside this method, too.
An adapted example from Java Tutorials
public class MouseMotionEventDemo extends JPanel
implements MouseMotionListener {
//...in initialization code:
//Register for mouse events on blankArea and panel.
blankArea.addMouseMotionListener(this);
addMouseMotionListener(this);
...
}
public void mouseMoved(MouseEvent e) {
Point point = e.getPoint();
updatePanel(point); //create this method to call repaint() on JPanel.
}
public void mouseDragged(MouseEvent e) {
}
}
}
You call repaint within the paint method, causing an infinite loop. Swing Timers are preferred for running periodic updates on components.
For custom painting in Swing the method paintComponent rather than paint should be overridden not forgetting to call super.paintComponent.