why does the int not change? java - java

Can someone please tell me how i can get the value of int x in my following code:
when i move the square left and right, the output from Test stays as 500.
I am wanting the Thread in Test to get the value of x every time it loops, but x is always 500 (from the thread) even though the value of x is changing in Drawing.java. please help me with this.
package block;
public class Test extends Drawing implements Runnable{
Thread collision = new Thread(this);
public Test() {
collision.start();
}
#Override
public void run() {
while(true) {
System.out.println(x);
}
}
}
package block;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Drawing extends Canvas implements Runnable, KeyListener{
Thread thread = new Thread(this);
int x = 500;
int y = 540;
public Drawing() {
setSize(1000, 800);
addKeyListener(this);
thread.start();
}
public void update(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, 1000, 700);
paint(g);
}
public void paint(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(x, y, 50, 50);
}
#Override
public void run() {
while(true) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Drawing.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public void keyTyped(KeyEvent ke) {
}
#Override
public void keyPressed(KeyEvent ke) {
if(ke.getKeyCode() == KeyEvent.VK_LEFT) {
x -= 5;
}
if(ke.getKeyCode() == KeyEvent.VK_RIGHT) {
x += 5;
}
}
#Override
public void keyReleased(KeyEvent ke) {
}
}
EDIT: --------------------
package block;
import javax.swing.JFrame;
public class Block extends JFrame{
Test test = new Test();
public Block() {
setSize(1000, 700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(new Drawing());
setVisible(true);
createBufferStrategy(2);
}
public static void main(String[] args) {
new Block();
}
}

You are creating multiple instances of x because you are not using inheritance correctly. When you call new Test(), that creates one instance of a Test (which contains a Drawing, which contains a member x), and then the call to new Drawing() creates another instance of a Drawing (which contains a different member x).
To fix this, you could pass a reference to a Drawing object to your Test constructor, and access the x member through the reference.

Related

Problems with repaint()

Im having some trouble using repaint.The code is supposed to draw a line behind your cursor.
package javaapplication6;
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.*;
class Test extends Canvas implements MouseListener, MouseMotionListener {
int x[]=new int[1024];
int y[]=new int[1024];
int size=0;
public void MouseDemo(){
addMouseListener(this);
addMouseMotionListener(this);
}
public void paint (Graphics g){
g.setColor(Color.red);
for (int i=1;i<size;i++) g.drawLine(x[i],y[i],x[i-1],y[i-1]);
}
public void mousePressed(MouseEvent e){
x[size]=e.getX();
y[size]=e.getY();
size++;
}
public void mouseDragged(MouseEvent e){
y[size]=e.getY();
x[size]=e.getX();
size++;
repaint();
}
public void mouseEntered(MouseEvent e){
size=0;
y[size]=e.getY();
x[size]=e.getX();
repaint();
}
public void mouseExited (MouseEvent e){
size=0;
repaint();
}
public void mouseReleased (MouseEvent e){}
public void mouseClicked (MouseEvent e){
}
public void mouseMoved (MouseEvent e){}
}
public class JavaApplication6 {
public static void main(String[] args) {
JFrame win= new JFrame ("Target");
win.setSize(600,500);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.add(new Test());
win.setVisible(true);
}}
This same code worked at the school computer but when I got home and tried to do another example and it didn't really work so I decided to test this one and it doesn't work either.I would really appreciate some help and an explanation as to why repaint doesn't trigger.
Your primary problem is here...
public void MouseDemo() {
addMouseListener(this);
addMouseMotionListener(this);
}
This is a method, not a constructor, so it will never register your listeners. Instead, change it to...
public MouseDemo() {
addMouseListener(this);
addMouseMotionListener(this);
}
Or, based on you actually example code...
public Test() {
addMouseListener(this);
addMouseMotionListener(this);
}
java.awt.Canvas is a heavy weight component, AWT components don't always play nice with Swing, as they have no concept of z-ordering in the way that Swing implements it.
You'd be better off starting with a JPanel.
By convention, you should then override the paintComponent method and perform your custom painting within it, remembering to call super.paintComponent first
Because frame borders are inserted into the visible area of the frame, you "useable" area will be less then that specified by setSize, instead, you should override the getPreferredSize method of the JPanel and specify the "usable" area you prefer. From there, you can pack the frame around it.
To avoid any possible issues with threads, you should use EventQueue.invokeLater to start you UI in
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test extends JPanel implements MouseListener, MouseMotionListener {
int x[] = new int[1024];
int y[] = new int[1024];
int size = 0;
public Test() {
addMouseListener(this);
addMouseMotionListener(this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 500);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
for (int i = 1; i < size; i++) {
g.drawLine(x[i], y[i], x[i - 1], y[i - 1]);
}
}
#Override
public void mousePressed(MouseEvent e) {
x[size] = e.getX();
y[size] = e.getY();
size++;
}
public void mouseDragged(MouseEvent e) {
y[size] = e.getY();
x[size] = e.getX();
size++;
repaint();
}
public void mouseEntered(MouseEvent e) {
System.out.println("Entered");
size = 0;
y[size] = e.getY();
x[size] = e.getX();
repaint();
}
public void mouseExited(MouseEvent e) {
size = 0;
repaint();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Test());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

i can't see circle moving

While using Swing in java, I am trying to move a circle slowly from a starting position to an end position when clicking a button. However, I can't see the circle moving. It just moves from start to end in an instant.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyApp {
private int x = 10;
private int y = 10;
private JFrame f;
private MyDraw m;
private JButton b;
public void go() {
f = new JFrame("Moving circle");
b = new JButton("click me to move circle");
m = new MyDraw();
f.add(BorderLayout.SOUTH, b);
f.add(BorderLayout.CENTER, m);
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
b.addActionListener(new Bute());
}
public static void main(String[] args) {
MyApp m = new MyApp();
m.go();
}
private class Bute implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 150; i++) {
++x;
++y;
m.repaint();
Thread.sleep(50);
}
}
}
private class MyDraw extends JPanel {
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 500, 500);
g.setColor(Color.red);
g.fillOval(x, y, 40, 40);
}
}
}
I think the problem is with the action listener because when I'm doing it without using button it is working. Any suggestions?
As Andrew Thompson said, calling Thread.sleep() without defining a second thread freezes everything, so the solution is to define and run another thread like so:
class Bute implements ActionListener, Runnable {
//let class implement Runnable interface
Thread t; // define 2nd thread
public void actionPerformed(ActionEvent e) {
t = new Thread(this); //start a new thread
t.start();
}
#Override //override our thread's run() method to do what we want
public void run() { //this is after some java-internal init stuff called by start()
//b.setEnabled(false);
for (int i = 0; i < 150; i++) {
x++;
y++;
m.repaint();
try {
Thread.sleep(50); //let the 2nd thread sleep
} catch (InterruptedException iEx) {
iEx.printStackTrace();
}
}
//b.setEnabled(true);
}
}
The only problem with this solution is that pressing the button multiple times will speed up the circle, but this can be fixed by making the button unclickable during the animation via b.setEnabled(true/false). Not the best solution but it works.
As said in the comments and another answer, don't block the EDT. Thead.sleep(...) will block it, so you have two options:
Create and manage your own (new) thread.
Use a Swing Timer
In this answer I'll be using a Swing Timer, since it's easier to use. I also changed the paintComponent method to use the Shape API and change the button text to start and stop accordingly as well as reusing the same ActionListener for the button and the timer:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MovingCircle {
private JFrame frame;
private CustomCircle circle;
private Timer timer;
private JButton button;
public static void main(String[] args) {
SwingUtilities.invokeLater(new MovingCircle()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(this.getClass().getSimpleName());
circle = new CustomCircle(Color.RED);
timer = new Timer(100, listener);
button = new JButton("Start");
button.addActionListener(listener);
circle.setBackground(Color.WHITE);
frame.add(circle);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private ActionListener listener = (e -> {
if (!timer.isRunning()) {
timer.start();
button.setText("Stop");
} else {
if (e.getSource().equals(button)) {
timer.stop();
button.setText("Start");
}
}
circle.move(1, 1);
});
#SuppressWarnings("serial")
class CustomCircle extends JPanel {
private Color color;
private int circleX;
private int circleY;
public CustomCircle(Color color) {
this.color = color;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(color);
g2d.fill(new Ellipse2D.Double(circleX, circleY, 50, 50));
}
#Override
public Dimension preferredSize() {
return new Dimension(100, 100);
}
public void move(int xGap, int yGap) {
circleX += xGap;
circleY += yGap;
revalidate();
repaint();
}
public int getCircleX() {
return circleX;
}
public void setCircleX(int circleX) {
this.circleX = circleX;
}
public int getCircleY() {
return circleY;
}
public void setCircleY(int circleY) {
this.circleY = circleY;
}
}
}
I'm sorry, I can't post a GIF as I wanted but this example runs as expected.

I cannot draw objects and have them move on the screen

I can draw static things to the screen, but I want to make them move with user key input. I don't know what to do, I've been searching and searching and haven't come up with an answer yet. Please help!
package com.Game.game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JFrame
{
final static int width = 500;
final static int height = 500;
public int x = 250;
public int y = 250;
public int changeX = 10;
public int changeY = 10;
public static void main(String[] args)
{
new Game();
}
public Game()
{
KeyListener listener = new KeyListening();
addKeyListener(listener);
setFocusable(true);
DrawingStuff drawingstuff = new DrawingStuff();
add(drawingstuff);
setSize(width, height);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public class DrawingStuff extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawString("Hey there!", 300, 300);
g.setColor(Color.RED);
g.fillRect(x, y, 50, 50);
}
}
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
#Override
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
y = y + changeY;
System.out.println("Hey");
drawingstuff.repaint();
}
}
#Override
public void keyReleased(KeyEvent e)
{
}
#Override
public void keyTyped(KeyEvent e)
{
}
}
public void update()
{
}
}
EDIT: Fixed it. I took away the key listener stuff in the constructor method, added a command to focus on "drawingstuff" in the constructor method, and, most importantly, added this bit of code to the end of the constructor method:
while(true)
{
drawingstuff.repaint();
}
The problem is that your KeyListening object has a reference to a different DrawingStuff object than the one you added to your UI inside the Game constructor.
public class KeyListening implements KeyListener
{
DrawingStuff drawingstuff = new DrawingStuff();
...
You should pass a DrawingStuff reference to the KeyListening instance so that it can tell the right object to repaint itself.

draw a circle when certain condition is met

My program is to convert the letters to some signals.My main method generates some random letters. The letter is passed to another method which calls repaint() method based on the Letter generated.The PaintComponent() method is used to drew a circle filled with white color.When i execute the program i get only a Jframe. I don't see the circle.Please help.
package morsecode;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
import java.awt.*;
public class MorseCode extends Frame {
public static void main(String[] args) {
MorseCode mc = new MorseCode();
MorseCode frame = new MorseCode();
final String chars = "abcdefghijklmnopqrstuvwxyz1234567890";
char word;
for(int i=1;i<=1;i++)
{
Random rand = new Random();
int x = rand.nextInt(36);
word = chars.charAt(x);
System.out.print(word);
frame.setBackground(Color.BLACK);
frame.addWindowListener(
new WindowAdapter()
{
#Override
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
}
);
frame.setSize(400, 400);
frame.setVisible(true);
mc.toMorseCode(word);
}
}
void toMorseCode(char letter)
{
switch(letter)
{
case 'A' | 'a':
repaint();
Thread.sleep(1000);
repaint();
Thread.sleep(2000);
break;
case 'B' | 'b':
repaint();
Thread.sleep(1000);
repaint();
Thread.sleep(1000);
repaint();
Thread.sleep(1000);
repaint();
Thread.sleep(2000);
break; ..............
}
}
public void paintComponent(Graphics g) {
Graphics2D ga = (Graphics2D)g;
ga.setColor(Color.white);
ga.fillOval(125,125,150,150);
}
}
Two things...
First, calling Thread.sleep(2000); within the Event Dispatching Thread will prevent the EDT from processing events on the event queue, including paint events.
Second, Frame doesn't have a paintComponent.
Adding the #Override annotation and trying to call super.paintComponent would have highlighted this issue as the code wouldn't have compiled.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
First of all, start by using a JPanel to hold your core logic and perform your custom painting.
Second, use a javax.swing.Timer to perform animation. See How to use Swing Timers for more details
Updated
The basic concept is relatively simple. You need some kind of second/background thread which can generate the delays between the changes in the output. You then need to update the UI before each delay based on what type of information you are trying to display.
The implementation becomes tricky because Swing, like most GUI frameworks, is single threaded and not thread safe.
This means, you can not block the GUI thread, doing so will prevent the UI from been repainted, amongst other things and you must update the state of any UI component from within the context of the GUI thread.
This means that while you can use a Thread to run in the background, you must ensure that all changes/modifications to the UI are carried out only from within the EDT.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MorseCodeTest {
public static void main(String[] args) {
new MorseCodeTest();
}
public MorseCodeTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static final int GAP = 500;
public static final int DOT = 1000;
public static final int DASH = 4000;
public interface Transmitter {
public void setTap(boolean tap);
}
public class TestPane extends JPanel implements Transmitter {
private MorseCode code;
private boolean tapped;
public TestPane() {
code = MorseCode.create('A').addDot().addDash();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
Signalar signalar = new Signalar(TestPane.this, code);
signalar.execute();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (tapped) {
Graphics2D g2d = (Graphics2D) g.create();
int diameter = Math.min(getWidth(), getHeight()) / 2;
int x = (getWidth() - diameter) / 2;
int y = (getHeight() - diameter) / 2;
g2d.fillOval(x, y, diameter, diameter);
g2d.dispose();
}
}
#Override
public void setTap(boolean tap) {
tapped = tap;
repaint();
}
}
public class Signalar extends SwingWorker<Void, Boolean> {
private final MorseCode code;
private final Transmitter transmitter;
public Signalar(Transmitter transmitter, MorseCode code) {
this.code = code;
this.transmitter = transmitter;
}
#Override
protected void process(List<Boolean> chunks) {
transmitter.setTap(chunks.get(chunks.size() - 1));
}
#Override
protected Void doInBackground() throws Exception {
for (Tone tone : code.getTones()) {
publish(true);
Thread.sleep(tone.getDelay());
publish(false);
Thread.sleep(GAP);
}
return null;
}
}
public static class Tone {
private final int delay;
public Tone(int delay) {
this.delay = delay;
}
public int getDelay() {
return delay;
}
}
public static class DashTone extends Tone {
public DashTone() {
super(DASH);
}
}
public static class DotTone extends Tone {
public DotTone() {
super(DOT);
}
}
public static class MorseCode {
private final char value;
private final List<Tone> tones;
public static MorseCode create(char value) {
MorseCode code = new MorseCode(value);
return code;
}
public MorseCode(char value) {
this.value = value;
this.tones = new ArrayList<>(25);
}
public char getValue() {
return value;
}
public MorseCode addDash() {
return addTone(new DashTone());
}
public MorseCode addDot() {
return addTone(new DotTone());
}
public MorseCode addTone(Tone tone) {
tones.add(tone);
return this;
}
public Iterable<Tone> getTones() {
return tones;
}
}
}

How do I fix the KeyListener

why isnt this working
the JFrame is made and the paint is working but I can't get the keylistener to work. Ive tried to print something inside the keylistener but it did not show when left arrow was pressed.
import java.awt.event.KeyEvent;
public class movingsquare extends runpaintgui{
public void key(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT){
x = x - 5;
repaint();
System.out.println( x);
}
}
}
other class
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class runpaintgui extends JFrame{
int x = 30;
public static void main(String[] args){
runpaintgui frame = new runpaintgui();
frame.setSize(1275, 775);
frame.setResizable(false);
frame.setTitle("game");
frame.setVisible(true);
}
public void paint(Graphics g){
super.paint(g);
g.fill3DRect(x, 30, 60, 60, true);
}
}
Change your code this way:
package de.swisslife.muellerj.test;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
public class runpaintgui extends JFrame implements KeyListener{
public runpaintgui(){
this.setSize(1275, 775);
this.setResizable(false);
this.setTitle("game");
this.setVisible(true);
this.addKeyListener(this);
this.setVisible(true);;
}
int x = 30;
public static void main(String[] args){
runpaintgui runpaintgui = new runpaintgui();
}
public void paint(Graphics g){
super.paint(g);
g.fill3DRect(x, 30, 60, 60, true);
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT){
x = x - 5;
repaint();
System.out.println( x);
}
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Firstly I would not have a subclass implement from you main program.
I am not exactly sure what you want to do in your program, but you probably just need to implement a key listener like this :
public class Test extends JFrame {
static int x = 30;
public static void main(String[] args) {
final Test frame = new Test();
frame.setSize(1275, 775);
frame.setResizable(false);
frame.setTitle("game");
frame.setVisible(true);
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent arg0) {
if (arg0.getKeyCode() == KeyEvent.VK_LEFT){
x = x - 5;
frame.repaint();
System.out.println( x);
}
}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyPressed(KeyEvent arg0) {}
});
}
public void paint(Graphics g) {
super.paint(g);
g.fill3DRect(x, 30, 60, 60, true);
}
}

Categories