I'm a newbie here. I have a code here from which I would like to change the text of a JLabel to that of the position of a moving - mouse. Here is my code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
public class Draw extends JFrame{
int x;
int y;
String positions = "Positions: " + x + ", " + y;
JLabel positionsOnFrame = new JLabel(positions);
public class AL implements MouseMotionListener {
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseDragged(MouseEvent e) {
positions += " dragged.";
}
}
//Constructor
public Draw() {
setTitle("Title");
setBackground(Color.BLACK);
setSize(300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
addMouseMotionListener(new AL());
add(positionsOnFrame);
setVisible(true);
}
public static void main(String[] args) {
new Draw();
}
}
Side problem: The JFrame doesn't turn black as well even though I have set the color to be black from the constructor.
Any solution to the mouse problem? Nothing happens! The values are just set to 0! (I haven't initialized them, they're just automatically set to 0!).
Help would definitely be appreciated!
First, uninitialized integers (such as x and y) are given a default value of zero. But it's not good practice to rely on this; best to explicitly initialize their values even if still zero.
Next, your mouseMoved() callback is in-fact getting called. But it's not updating the text of your 'positionsOnFrame' label, it's only updating the x and y coordinates. Just because you created the label with a String (positions), doesn't mean the label's text will automatically change whenever that String is changed. You have to change the text of the label accordingly. So adding positionsOnFrame.setText("Positions: " + x + "," + y); inside your mouseMoved() callback will fix that part.
Finally, change the color of the frame's content pane instead of the frame directly: getContentPane().setBackground(Color.BLACK);
Hope that helps!
This should work
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
positionsOnFrame.setText("Positions: " + x +", " + y);
System.out.println(x);
}
and for the background color this should work.
getContentPane().setBackground(Color.BLACK);
The String positions will not change each time the x and y change. The value will stay with what x and y were when you assigned it originally.
For example
String s = "hello";
String t = s;
System.out.println(t);
s = "bye";
System.out.println(t);
will print hello both times
Related
I want to animate a rectangle in a specific pattern. I was told to use a SwingTimer for animation instead of a Thread.
My plan was to animate a rectangle moving forward until it hits the end of the frame. Then it moves down by one unit(The height of the rectangle, so in my case 30), and then moves backwards; and when it hits the end, there it moves down again and so on.
Now the problem with the SwingTimer is that the whole operation is a continuous loop so the rectangle doesn´t move the way I want it to. In order for this to work, I guess I´ve to start and stop the loop of some methods which is complicated and I don´t know how to do it properly .
So how can I animate the rectangle the way I want it to? Is SwingTimer really the proper way to do such things or are other methods better?
Here´s the code I´ve got so far. I´m aware that it´s not much and that ActionPerformed does a completely different animation.
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Test extends javax.swing.JPanel implements ActionListener{
private int x = 0;
private int y = 0;
Timer tm = new Timer(50, this);
public Test() {
initComponents();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new java.awt.Color(102, 102, 102));
g.fillRect(x, y, 30, 30);
tm.start();
}
public void moveForward() {
x = x + 30;
repaint();
System.out.println("(" + x + "|" + y + ")");
}
public void moveBackwards() {
x = x - 30;
repaint();
System.out.println("(" + x + "|" + y + ")");
}
public void moveDown() {
y = y + 30;
repaint();
System.out.println("(" + x + "|" + y + ")");
}
public void moveUp() {
y = y - 30;
repaint();
System.out.println("(" + x + "|" + y + ")");
}
public void actionPerformed(ActionEvent e) {
moveForward();
if (x >= 270){
moveDown();
}
}
public static void main(String[] args) {
Test t = new Test();
JFrame f = new JFrame();
f.setSize(300, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(t);
f.setVisible(true);
}
What you have done so far looks pretty good. You only need your action method to work properly. For that i would use a class variable called direction:
private boolean direction = true;
Now in your action method you move the rectangle either forward or backwards, depending on direction. And if it hits the end you move the rectangle down and invert direction:
public void actionPerformed(ActionEvent e) {
if (direction){
moveForward();
}
else {
moveBackwards();
}
//Check if it is at the end
if(((x >= 270) && (direction)) || ((x <= 30) && (!direction))) {
moveDown();
direction = !direction;
}
}
The if clause is a little bit complicated, but you can split it up, if you want it to be more readable.
This is code. I'm trying to create mini tennis, but right now I just want to learn how to move the bottom bar left and right.
panelObject Class
import javax.swing.*;
import java.awt.*;
class panelObject extends JPanel
{
int ballx = 50;
int bally = 50;
int barx = 405;
int bary = 405;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
this.setBackground(Color.WHITE);//creates the color of th background
g.setColor(Color.BLUE);// creates the color of the object
g.fillOval(ballx,bally,50,50); // creates the size and shape of the object
g.setColor(Color.RED);
g.fillRect(barx,bary, 50,50);
}
}
TennisGame class
public class TennisGame
{
public static void main (String[] args)
{
JFrame f = new JFrame("Tennis"); //Create a JFrame object, its basically the window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //This sets the default close operation, you don't really need to understand it, just make sure you have it
panelObject object = new panelObject(); // creates a panel object to draw on
f.add(object); // this adds the panel we created to the window
f.setSize(640,480); // this sets the size of the window
f.setVisible(true); // this shows the window
//this for loop just loops 540 times
//each time through the loop, we increase the x value of our rectangle
for (int i = 0; i < 540; i++)
{
//increase the x value of the rectangle; x was declared in the panelObeject class
object.ballx += 1;
//repaint will redraw the screen with the updated rectangle position
object.repaint();
//this whole try catch will pause the program for a while so it doesn't draw everything so fast
try
{
Thread.sleep(3); // time duration
}
catch(Exception e)
{
}
}
}
//update animation
public void update (long timePassed)
{
}
}
In order to have the Bar object move we must
Capture the Inputed key
Decide what that key is an update the bar's properties
redraw the bar
Note: This isn't the most efficient ways of creating such a program, and you might want to consider creating a tick and paint method that are called a designated number of times per second (Like 60, AKA 60 FPS/TPS).
tick being to update the Tennis games information and
paint to render that 'information' accordingly
here is all of your code, i edited some parts and created comments.
static panelObject object; //Declares the JPanel Object to draw on as a Global Variable
public static void main (String[] args)
{
JFrame f = new JFrame("Tennis"); //Create a JFrame object, its basically
the window
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //This sets the default close operation, you don't really need to understand it, just make sure you have it
object = new panelObject(); // initializing the global panel object to draw on
f.add(object); // this adds the panel we created to the window
f.setSize(640,480); // this sets the size of the window
f.setVisible(true); // this shows the window
f.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) { // This Method is called when any key is pressed on the keyboard and stores the key pressed as 'e'
if(e.getKeyCode() == KeyEvent.VK_A) //if the pressed key is 'a' then move left
{
System.out.println("left");
object.barx -= object.ballSpeed; //We know that the key is a so move the bar to the left
}
if(e.getKeyCode() == KeyEvent.VK_D) //if the pressed key is 'd' then move right
{
System.out.println("right");
object.barx += object.ballSpeed; //We know that the key is d so move the bar to the right
}
object.repaint();//Repaints to the screen(Not the Best place to do this,but will work)
}
});
//this for loop just loops 540 times
//each time through the loop, we increase the x value of our circle
for (int i = 0; i < 540; i++)
{
//increase the x value of the rectangle; x was declared in the panelObeject class
object.ballx += 1;
//repaint will redraw the screen with the updated rectangle position
object.repaint();
//this whole try catch will pause the program for a while so it doesn't draw everything so fast
try
{
Thread.sleep(3); // time duration
}
catch(Exception e)
{
}
}
}
//update animation
public static void update (long timePassed)
{
object.repaint();
}
Here is the panelObject class, i didnt change much
public class panelObject extends JPanel{
int ballSpeed = 3; // The ball has a speed property so when it moves you don't hard code the value in (Bad Practice especially in very large programs)
int ballx = 50;
int bally = 50;
int barx = 405;
int bary = 405;
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.WHITE);//creates the color of th background
g.setColor(Color.BLUE);// creates the color of the object
g.fillOval(ballx,bally,50,50); // creates the size and shape of the object
g.setColor(Color.RED);
g.fillRect(barx,bary, 50,50);
}
}
Exercise1609: Write a program that draws line segments using the arrow keys. The line starts from the center of the frame and draws towards east,north, west, or south when the right-arrow key, up-arrow key, left-arrow key, or down-arrow key is pressed. In short, draw a maze. See comments below for a description of my question.
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Exercise1609 extends JFrame {
private KeyboardPanel panel = new KeyboardPanel();
public Exercise1609() {
add(panel);
panel.setFocusable(true);
}
public static void main(String[] args) {
Exercise1609 frame = new Exercise1609();
frame.setTitle("Tegn med piltaster");
frame.setSize(600, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
//The panel that listens for key and responds by drawing
public static class KeyboardPanel extends JPanel {
private int x,y,previousX,previousY;
private boolean firstTime = true;
public KeyboardPanel() {
/**
* why must x and y be initialized inside paintComponent?
* if I want to start drawing from the middle of the panel?
* If I remove the if-block inside paintComponent and instead
* place the initialization here, as shown with the two lines below:
* x = previousX = getWidth() / 2;
* y = previousY = getHeight() / 2;
* ...then the program will not start to draw from the middle,
* but upper left corner of the screen
*/
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
previousY = y;
previousX = x;
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
y++;
break;
case KeyEvent.VK_UP:
y--;
break;
case KeyEvent.VK_RIGHT:
x++;
break;
case KeyEvent.VK_LEFT:
x--;
break;
}
repaint();
}
});
}//end constructor
#Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
if(firstTime) {
//Why can't x and y be initialized outiside paintComponent?
//Why can't they be initialized inside the constructor of this class?
x = previousX = getWidth() / 2;
y = previousY = getHeight() / 2;
firstTime = false;
}
g.drawLine(previousX, previousY, x, y);
System.out.println(x + " " + y);
}
}
}
The last line System.out.println(x + " " + y); outputs 0,0 if I try to initialize x and y anywhere else
but paintComponent(). When initialized inside paintcomponent() the output is 292,131...which is what I want.
getWidth() and getHeight() are not set correctly until the UI elements have gone through a layout pass. This is guaranteed to happen before paintComponent() is called but probably not at other points where you have tried to call them.
See: getWidth() and getHeight() are 0 after calling setPreferredSize()
If you need to be notified when the width and height of the component is set/changed, check out ComponentListener: http://docs.oracle.com/javase/7/docs/api/java/awt/event/ComponentListener.html
i'm trying to implement a function to calculate the area of the polygon. this code allows you yo draw a polygon but when it comes to display the area, i am not sure how to do that. i tried in a couple ways but i am still a beginner at programming, so i'd appreciate any help. here is the code:
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.Polygon;
public class DrawPolygons extends JApplet implements ActionListener, MouseListener
{
private static final int NUMPOINTS = 500; //Up to 500 points can be chosen
private JButton finish; //Button to indicate user is done entering points
private Polygon shape; //polygon object to be drawn
private boolean isDrawn; //boolean flag for when the user is finished drawing
private int count; //how many points the user has clicked
private Color color; //color of the polygon after user finalizes points
private int[] x; //x coordinates of each point user picks
private int[] y; //y coordinates of each point user picks
private float sum;
private double area;
public void init() //set up GUI
{
setLayout(new FlowLayout());
addMouseListener(this); //adds MouseListener for mouse clicks
isDrawn = false; //isDrawn is initially false
count = 0; //count starts as 0
x = new int[NUMPOINTS]; //allows for up to 500 points to be chosen
y = new int[NUMPOINTS]; //allows for up to 500 points to be chosen
finish = new JButton("Finalize points"); //creates finish button
finish.addActionListener(this); //adds finish button to ActionListener
add(finish); //adds finish button to GUI
color = Color.BLACK; //color is intially black, and will remain
// so if user cancels the color chooser
//JOptionPane.showMessageDialog(null, "Click points that will make up the polygon. After each" +
// "point is entered, press the Finalize Points button");
shape = new Polygon(); //creates the Polygon shape
}
public void paint(Graphics g) //draws the Polylines, Polygons, and sets the color
{
super.paint(g);
g.drawPolyline(x, y, count); //draws the polyline specified by user
// mouseclick
g.setColor(color); //sets the color to the user chosen color
if(isDrawn) //if finalize button is clicked
{
g.fillPolygon(x, y, count); //finalizes polylines into
} // polygon and fills shape
}
public void actionPerformed(ActionEvent a) //decides what to do when finalize button is pressed
{
if(a.getSource() == finish) //if the finalize button is pressed
{
isDrawn = true; //isDrawn is set to true, ending the users ability
// to add more points, and fills the polygon
color = Color.red;
//JColorChooser.showDialog(this, "Choose a color", color); //color is set to users choice
repaint();
JOptionPane.showMessageDialog(null, "The area is ");
}
}
public void mouseClicked(MouseEvent e) //save coordinates of clicks
{
if(isDrawn == false && count < NUMPOINTS) //if the finalize button is not pressed
{ // the user can add additional points
x[count] = e.getX(); //adds the x point at the current mouse x coordinate
y[count] = e.getY(); //adds the y point at the current mouse y coordinate
count++; //count increases with each mouse click
repaint();
}
else if (e.isShiftDown()) {
// Clear the applet. (This only requires a repaint.)
// Also, set count to zero to start a new polygon.
count = 0;
isDrawn = false;
repaint();
}
}
private float getPolygonArea(int[] x, int[] y, int count)
{
float sum_but_no_result=0;
for(int i=0;i<(count-1);i++) // count is point number of polygon
{
sum_but_no_result+=x[i]*y[i+1] + y[i]*x[i+1];
}
sum_but_no_result+=x[count-1]*y[0] + y[count-1]*x[0];
float sum = (float)Math.abs(sum_but_no_result) / 2.0f;
return sum;
}
//Empty Implementation provided here so we can implement MouseListener (needed because we must
// provide concrete forms of all methods of an interface to implement it
public void mousePressed(MouseEvent e){};
public void mouseReleased(MouseEvent e){};
public void mouseEntered(MouseEvent e){};
public void mouseExited(MouseEvent e){};
}
float x[N],y[N]; // point coordinates as x1,y1 x2,y2 ....
...
...
...
...
float sum_but_no_result=0;
for(int i=0;i<(N-1);i++) // N is point number of polygon
{
sum_but_no_result+=x[i]*y[i+1] + y[i]*x[i+1];
}
sum_but_no_result+=x[N-1]*y[0] + y[N-1]*x[0];
float sum= (float)Math.abs(sum_but_no_result) / 2.0f;
http://www.mathopenref.com/coordpolygonarea.html
For self-intersecting polygons, you may add an intersection-coord-finder and polygon-adder algorithm to find all sub-polygons produced by intersecting, recursively.
In Kotlin, using an extension on java.awt.Polygon :
import java.awt.Polygon
fun Polygon.area(): Float {
var sum = 0f
for (i in 0 until npoints - 1) {
sum += xpoints[i] * ypoints[i + 1] + ypoints[i] * xpoints[i + 1]
}
sum += xpoints[npoints - 1] * ypoints[0] + ypoints[npoints - 1] * xpoints[0]
return sum / 2.0f
}
I am creating a map editor, and where they click will be used to add a data point to the map.
public MapEditor() throws HeadlessException, FileNotFoundException, XMLStreamException {
super("MapEditor");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set JFrame properties.
this.setTitle("Map Editor");
this.setSize(PREFERRED_WIDTH, PREFERRED_HEIGHT);
this.setBackground(Color.gray);
this.setJMenuBar(makeMenuBar());
JPanel mainPanel = new JPanel( new BorderLayout());
Icon image = new ImageIcon("map.jpg");
JLabel label = new JLabel(image);
scrollPane = new JScrollPane();
scrollPane.getViewport().add(label);
scrollPane.addMouseListener(this);
mainPanel.add(scrollPane, BorderLayout.CENTER);
this.getContentPane().add(mainPanel);
this.getContentPane().add(makeStatusBar(), BorderLayout.SOUTH);
setVisible(true);
}
I also have the following event for when the mouse is clicked:
public void mouseClicked(MouseEvent e) {
int x = getX();
int y = getY();
System.out.println("clicked at (" + x + ", " + y + ")");
}
However, no matter where I click in the window, it returns the same value. I have noticed that if I move the entire window to somewhere else on my screen that it returns different values. They appear to correspond to the top left corner of the window. I've tried adding the MouseListener to different components, but I get the same result with each of them. Some help would be greatly appreciated.
Use MouseAdapter instead as it is an abstract adapter class for receiving mouse events.
See the accepted answer of Java MouseListener for code example.
EDIT: You are not using the MouseEvent variable reference so getX() and getY() will not return what you expect, unless getX() and getY() are your own methods?
Change your code to:
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("clicked at (" + x + ", " + y + ")");
}
figured it out. It needs to be:
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.println("clicked at (" + x + ", " + y + ")");
}
before I was just getting the X and Y of the pane, not where the Mouse Event occurred