Figure drawn without function call? - java

I am getting a problem in java program for moving a circle. The program has 2 basic buttons:
START: used for moving the circle
STOP: used for exiting the program
My problem is that the circle appears before I press the start button. However I make the call to move only when START Button is pressed which makes the call to repaint and then the circle should appear. But it appears by default. I have no problem in moving the circle. Here is my source code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Moving extends JFrame implements ActionListener
{
JButton start,stop;Move mypanel;
Moving()
{
setTitle("Moving circle");
setLayout(new BorderLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800,600);
start=new JButton("START");
stop=new JButton("STOP");
start.addActionListener(this);stop.addActionListener(this);
JPanel p=new JPanel();
p.setLayout(new FlowLayout());
p.add(start);p.add(stop);
getContentPane().add(p,BorderLayout.SOUTH);
mypanel=new Move();
getContentPane().add(mypanel,BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e)
{
String s=e.getActionCommand();
if(s.equals("STOP"))
System.exit(0);
else if(s.equals("START"))
mypanel.move();
}
public static void main(String []args)
{
Moving obj=new Moving();
obj.setVisible(true);
}
}
class Move extends JPanel
{ static int x=80, cv=0;
public void move()
{
repaint();
}
public void paintComponent(Graphics g)
{
setBackground(Color.green);
super.paintComponent(g);
g.setColor(Color.red);
if(x<500&&cv==0)
{g.fillOval(x, 80, 100, 100);this.inc();}
else if((x>=500||cv==1)&&x>=80)
{
cv=1;g.fillOval(x, 80, 100, 100);this.dec();
}
else cv=0;
}
public void inc()
{
x+=10;
}
public void dec()
{
x-=10;
}
}

By default setVisible would be true. So, if you don't won't to show panel on load then make it false on constructor.
And then make it visible when you hit Start.
See below:
class Move extends JPanel {
static int x = 80, cv = 0;
Move(){
setVisible(false); <-- Make it false here
}
public void move() {
this.setVisible(true); <----- make it visible here when you click start
repaint();
}
public void paintComponent(Graphics g) {
setBackground(Color.green);
..... REMAINING CODE
}
}

My suggestion is that if you do not want to show your circle before the pressing of the start button you have to remove drawing of the circle from the paintComponent method.
You can achieve the above by declaring a new method in your Move class say drawCircle like this:
public void drawCircle(Graphics g){
g.setColor(Color.red);
if(x<500&&cv==0)
{g.fillOval(x, 80, 100, 100);this.inc();}
else if((x>=500||cv==1)&&x>=80)
{
cv=1;g.fillOval(x, 80, 100, 100);this.dec();
}
else cv=0;
}
now in your Move class introduce a new boolean variable say circleShowing and intialise to false. This is declared so that the paintComponent method of the Move class can decide whether the circle should be drawn or not. You can do it like this:
public void paintComponent(Graphics g){
setBackground(Color.green);
super.paintComponent(g);
if(circleShowing){
drawCircle(g);
}
}
Now finally in the actionPerformed method of your Moving class you in the else if block you could write the following:
mypanel.circleShowing = true;
mypanel.move();
I hope if you make these changes this will work as you wish.

Related

Buttons not visible until mouseover

I created a frame and panel (for Graphics) and add buttons to the panel. However, when I run my program buttons are not visible until I hover over them. Maybe it is something wrong with graphics methods.
How the problem can be solved?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main{
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(600,500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setResizable(false);
Panel panel = new Panel();
f.add(panel);
f.setVisible(true);
}
}
class Panel extends JPanel implements ActionListener{
int[] x = {200,400,300,200};
int[] y = {100,100,200,100};
JButton fillRed;
JButton fillBlack;
JButton cancel;
Panel(){
this.setLayout(null);
fillRed = new JButton("Red");
fillRed.setBounds(50, 400, 100, 50);
fillRed.addActionListener(this);
this.add(fillRed);
fillBlack = new JButton("Black");
fillBlack.setBounds(250, 400, 100, 50);
fillBlack.addActionListener(this);
this.add(fillBlack);
cancel = new JButton("Cancel");
cancel.setBounds(450,400,100,50);
cancel.addActionListener(this);
this.add(cancel);
}
public void paint(Graphics g) {
super.paintComponent(g);
g.drawPolygon(x,y,4);
}
public void fillRed(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillPolygon(x,y,4);
}
public void fillBlack(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillPolygon(x,y,4);
}
public void cancel(Graphics g) {
super.paintComponent(g);
g.drawPolygon(x,y,4);
repaint();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==fillRed) {
fillRed(getGraphics());
}
if(e.getSource()==fillBlack) {
fillBlack(getGraphics());
}
if(e.getSource()==cancel) {
cancel(getGraphics());
}
}
}
Your painting code is mostly wrong. For example:
public void paint(Graphics g) {
super.paintComponent(g);
g.drawPolygon(x,y,4);
}
If you need to override paint() then the first statement should be super.paint(g).
However, you should NOT override paint. For custom painting you override paintComponent(...) and then invoke super.paintComponent(g). Read the Swing tutorial on Custom Painting for more information and working examples.
public void fillBlack(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillPolygon(x,y,4);
}
Never invoke paintComponent(...) directly. If you need to change a property of a component then you invoke repaint() and Swing will invoke the painting methods.
if(e.getSource()==fillRed) {
fillRed(getGraphics());
}
Don't invoke getGraphics() on a Swing component. Painting is done by setting properties of your class and then you invoke repaint(). If you need to paint multiple objects then you need to keep track of each object you want to paint and then in the painting method you paint every object. Check out Custom Painting Approaches for example of how this can be done.

MouseListener not giving accurate mouse location

I am attempting to have a circle appear on the screen and follow the mouse around. (Eventually I'm going to turn it into a game with ray casting) I am using a MouseMotionListener and am trying to use the mouseMoved method to get accurate mouse location within my JPanel. The problem is though that the farther I move my mouse down the screen, the less accurate it becomes. By the time my mouse gets to the bottom, it is drawing circles about 20 pixels above. It is not a lagging thing because it never catches up, it is always a few pixels above where it should be.
I've tried using different methods that call from MouseEvents and have tried using MousePointerInfo but none work correctly. It does seem to work when I have the JFrame set to undecorated, but obviously that does not look good for a program and thus I want to avoid that.
public class Driver {
public static void main(String[] args) {
JFrame frame = new JFrame("Moonlight");
frame.setSize(700, 700);
frame.setLocation(350, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new MoonlightPanel());
frame.setVisible(true);
}
}
public class Panel extends JPanel {
private BufferedImage myImage;
private Graphics myBuffer;
private Timer t;
public Panel () {
myImage = new BufferedImage(700, 700, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
t = new Timer(0, new Listener());
t.start();
addMouseMotionListener(new Mouse());
}
private class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
drawBackground();
/*try {
Point pos = getMousePosition();
myBuffer.setColor(Color.WHITE);
myBuffer.fillOval(pos.x - 10, pos.y - 10, 20, 20);
}
catch(NullPointerException en) {}*/
repaint();
}
}
private class Mouse implements MouseMotionListener {
public void mouseMoved(MouseEvent e) {
Point pos = new Point(e.getX(), e.getY());
System.out.println(pos);
myBuffer.setColor(Color.BLUE);
myBuffer.fillOval(pos.x - 10, pos.y - 10, 20, 20);
}
public void mouseDragged(MouseEvent e) {}
}
public void drawBackground() {
setBackground(Color.BLACK);
}
public void paintComponent(Graphics g) {
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
}
Your code is much more complex than it needs to be. The Panel class members are unnecessary. All you need to do is save the mouse location in the mouseMoved() method - in a class member variable - and reference it in the paintComponent() method to draw your blue circle. The below code is a stripped-down version which displays a blue circle that follows the mouse pointer around on the screen.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MoonLite extends JPanel implements MouseMotionListener {
private Point pt;
public MoonLite() {
setBackground(Color.BLACK);
setForeground(Color.BLUE);
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent e) {
pt = e.getPoint();
repaint();
}
public void mouseDragged(MouseEvent e) {
// Do nothing.
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (pt != null) {
g.fillOval(pt.x - 10, pt.y - 10, 20, 20);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Moonlight");
frame.setSize(700, 700);
frame.setLocation(350, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new MoonLite());
frame.setVisible(true);
}
});
}
}

How to handle two different objects in the same JPanel at the same time?

I am trying to make a simple JAVA game where an object is coming toward another static object or character and if I press "space" button the static object will jump and avoid the collision. I was successful to make the first object moving but I couldn't make the static object jump or move. I tried using keyevent but it didn't work. So how can I make it work? Or can you point out what am I doing wrong in my code?
package jpanel;
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
public class jp extends JPanel implements ActionListener{
Timer t;
int x,y,k;
jp(){
x=650;
k=0;
t=new Timer(5,this);
t.start();
}
public void actionPerformed(ActionEvent e){
x--;
//k++;
if(x==76){
x=650;
}
repaint();
}
public void keyPressed(KeyEvent e){
int key=e.getKeyCode();
if(key == KeyEvent.VK_SPACE){
k++;
/* if(k>300){
k=0;
}*/
repaint();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.black);
g.setColor(Color.blue);
g.fillRect(x,400,50,50);//moving object
g.setColor(Color.red);
//Static Object
g.fillRect(30, 350-k, 45, 70);//static_body
g.setColor(Color.yellow);
g.fillOval(28, 310-k, 40, 40);//static_head
g.setColor(Color.green);
g.fillRect(30, 420-k, 10, 35);//static_leg1
g.fillRect(65, 420-k, 10, 35);//static_leg2
g.setColor(Color.blue);
g.fillRect(35, 350-k, 10, 45);//static_hand
g.setColor(Color.black);
g.fillOval(55, 320-k, 7, 7);//static_eye
}
}
public class Jpanel extends JFrame {
public static void main(String[] args) {
jp p=new jp();
JFrame j=new JFrame("TEST_CASE-1");
j.add(p);
j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
j.setSize(700,500);
j.setVisible(true);
}
}
Not sure what you're trying to do, but if you want to listen to key events, you must register a listener (in the constructor, for instance):
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
...
}
);

Trying to draw lines in java over an image i already drew but i can't get it on top of the image?

I have to draw an archery target with two black lines in the innermost circle that forms a cross, but every time i adjust the lines so that the lines are closer to the centre it goes behind the image instead of appearing on top. How can I stop this? Does it need to have a separate set of instructions entirely?
This is my code:
package sumshapes;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;
public class SumShapes extends JFrame
implements ActionListener {
private JPanel panel;
public void paint(Graphics g)
{
g.setColor(Color.BLACK);
g.drawLine(250, 200, 250, 200);
g.drawOval(140,90,200,200);
g.setColor(Color.BLACK);
g.fillOval(140,90,200,200);
g.drawOval(162,109,155,155);
g.setColor(Color.BLUE);
g.fillOval(162,109,155,155);
g.drawOval(183,129,112,112);
g.setColor(Color.RED);
g.fillOval(183, 129, 112, 112);
g.drawOval(210,153,60,60);
g.setColor(Color.YELLOW);
g.fillOval(210, 153, 60, 60);
g.setColor(Color.BLACK);
}
public static void main(String[] args) {
SumShapes frame = new SumShapes();
frame.setSize(500,400);
frame.setBackground(Color.yellow);
frame.createGUI();
frame.setVisible(true);
}
private void createGUI(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout (new FlowLayout());
}
public void actionPerformed(ActionEvent event) {
Graphics paper = panel.getGraphics();
paper.drawLine(20,80,120,80);
}
}
All your drawing should go into the paintComponent method of a lightweight component, such as a JPanel.
There should never be a need to call getGraphics. If you wish to change the drawing upon a particular action you should a) program the logic into paintComponent b) alter the logic in the Action c) call repaint on the Component
For example:
private JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);//call parent method first thing
//paint here
}
#Override
public Dimension getPreferredSize(){//provided so you can size this component as necessary
return new Dimension(500,400);
}
};
....
frame.add(panel);
frame.pack();
As an aside, I'd recommend placing all calls to to Swing components on the EDT - this means wrapping your Swing calls in the main method with SwingUtilities. eg
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable(){
#Override
public void run() {
SumShapes frame = new SumShapes();
....
}
});
}

Drawing an oval on JButton when clicked

I've started working on a project for my Java class - LAN gomoku/five in a row. The game board is represented by a 2-dimensional array filled with buttons (JButton). With the event handler (class clickHandler) I want to draw an oval on the button that I click (the parameter of a clickHandler object). My following code hasn't worked though (I don't know how to get rid of the null-value of variable g)... I'd appreciate any piece of advice. Thank You a lot.
class clickHandler implements ActionListener {
JButton button;
Dimension size;
Graphics g;
public clickHandler(JButton button) {
this.button = button;
this.size = this.button.getPreferredSize();
}
#Override
public void actionPerformed(ActionEvent ae) {
this.g.setColor(Color.BLUE);
this.g.fillOval(this.button.getHorizontalAlignment(), this.button.getVerticalAlignment(), this.size.width, this.size.height);
this.button.paint(this.g);
this.button.setEnabled(false);
}
}
(In a class that creates the GUI - the game board full of buttons - I assign each button a new Action Listener - an instance of clickHandler) this way:
gButton.addActionListener(new clickHandler(gButton));
You have to:
Extends the JButton class, and override the paintComponent(Graphics g) method.
Do override getPreferredSize() method, which will return on Dimension object and will help the Layout Manager in placing your JButton on the Container/Component, by providing it one appropriate size.
Make your circle code there.
add an onClickListener, and set a flag on the clicked button if it is clicked, and call it to repaint.
About the Graphics object: it's best to keep it in it's paintComponent method, and to use it only there. It will always get passed in on a repaint, and if you save it for other moments, strange things can happen (happy experimenting :) ).
A small Example :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonExample
{
private MyButton customButton;
private void displayGUI()
{
JFrame frame = new JFrame("Custom Button Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
customButton = new MyButton();
customButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
MyButton.isClicked = true;
customButton.repaint();
}
});
frame.getContentPane().add(customButton, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ButtonExample().displayGUI();
}
});
}
}
class MyButton extends JButton
{
public static boolean isClicked = false;
public Dimension getPreferredSize()
{
return (new Dimension(100, 40));
}
public void paintComponent(Graphics g)
{
if (!isClicked)
super.paintComponent(g);
else
{
g.setColor(Color.BLUE);
g.fillOval(getHorizontalAlignment(), getVerticalAlignment(), getWidth(), getHeight());
}
}
}

Categories

Resources