enoy enoy - 3 years ago 177
Java Question

Move an oval to follow the cursor java

I would like some advice:

I am learning how to use swing and I have an assigment which proposes to make an application where user can choose from one combo box the JPanel's background's color (implemented as a custom Beam). Also we have other combo box to choose a shape's color.
The user needs to move the cursor and watch five ovals following it. So then I have done all the interface and I learnt how to use the timer to repaint the canvas every 100 ms.

INTERFACE:

White and blue interface

So how can I be able to store oval's lasts five positions? My code:

Base FRAME:

import java.awt.Color;
import java.awt.geom.Point2D;
import java.lang.reflect.Field;


public class Frame extends javax.swing.JFrame {



public Frame() {
initComponents();
}


@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

chooseBackground = new javax.swing.JComboBox<>();
chooseShape = new javax.swing.JComboBox<>();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
canvas1 = new lienzo();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

chooseBackground.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "WHITE", "BLACK", "PINK" }));
chooseBackground.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chooseBackgroundActionPerformed(evt);
}
});

chooseShape.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "BLUE", "YELLOW", "ORANGE" }));
chooseShape.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chooseShapeActionPerformed(evt);
}
});

jLabel1.setText("Seleccione el color:");

jLabel2.setText("Fondo:");

jLabel3.setText("Figura:");

canvas1.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseMoved(java.awt.event.MouseEvent evt) {
canvas1MouseMoved(evt);
}
});
canvas1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
canvas1MouseEntered(evt);
}
public void mouseExited(java.awt.event.MouseEvent evt) {
canvas1MouseExited(evt);
}
});

javax.swing.GroupLayout canvas1Layout = new javax.swing.GroupLayout(canvas1);
canvas1.setLayout(canvas1Layout);
canvas1Layout.setHorizontalGroup(
canvas1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
canvas1Layout.setVerticalGroup(
canvas1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 184, Short.MAX_VALUE)
);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(31, 31, 31)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(canvas1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chooseBackground, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 59, Short.MAX_VALUE)
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chooseShape, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(97, 97, 97))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(13, 13, 13)
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chooseBackground, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(chooseShape, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(jLabel3))
.addGap(18, 18, 18)
.addComponent(canvas1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(33, Short.MAX_VALUE))
);

pack();
}// </editor-fold>

private void chooseBackgroundActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String selection = chooseBackground.getSelectedItem().toString();

Color color;
try{
Field field = Class.forName("java.awt.Color").getField(selection);
color = (Color)field.get(null);
}catch(Exception e){
color = null;
}

canvas1.setBackground(color);

}

private void chooseShapeActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:

String selection = chooseShape.getSelectedItem().toString();

Color color;
try{
Field field = Class.forName("java.awt.Color").getField(selection);
color = (Color)field.get(null);

}catch(Exception e){
color = null;
}

canvas1.setForeground(color);




}

private void canvas1MouseMoved(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:

canvas1.setX(evt.getX());
canvas1.setY(evt.getY());
}

private void canvas1MouseEntered(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
canvas1.userHasMouseEntered=true;
}

private void canvas1MouseExited(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
canvas1.userHasMouseEntered=false;
}



/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Frame().setVisible(true);
}
});
}







// Variables declaration - do not modify
private lienzo canvas1;
private javax.swing.JComboBox<String> chooseBackground;
private javax.swing.JComboBox<String> chooseShape;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
// End of variables declaration


}


CANVAS:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/

/**
*
* @author YonePC
*/
public class lienzo extends JPanel {
public boolean userHasMouseEntered;

private int countSavedPos = 0;

private int[] posX = new int[5];
private int[] posY = new int[5];

private int x;
private int y;

public void setX(int x) {
this.x = x;
}

public void setY(int y) {
this.y = y;
}

public lienzo() {
Timer timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.start();

this.setBackground(Color.white);
this.setForeground(Color.blue);

}


@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
if(userHasMouseEntered)
g.fillOval(x, y, 30, 30);



posX[countSavedPos] = x;
posY[countSavedPos] = y;
countSavedPos++;
if(countSavedPos>4) countSavedPos=0;

for (int i = 0; i < countSavedPos; i++) {
g.fillOval(posX[countSavedPos], posY[countSavedPos], 30, 30);


}

//repaint();
}


}


In addition, I do not understand why the current oval which draws correctly under the cursor, is painted well but the second one which follows it blinks. Plus why do I have two ovals, am I not keeping the 5 last positions and repainting them?

Thank you for your time sincerely.

I have also seen:
How to use a swing Timer with JPanel
Converting a String to Color in Java
Move an Oval in java

Answer Source

Hello I have had help from classmates and I want to reply my own question:

To store mouse's last 5 positions we used into the canvas:

    private final ArrayList<Position> trail = new ArrayList<>();




public void addNewPosition(Position position){
       trail.add(0, position);       
}

public void removeLastPosition(){
    if (trail.size()> 5) trail.remove(5);
}    

To update last 5 positions we put into the JFrame:

    private void canvas1MouseMoved(java.awt.event.MouseEvent evt) {                                   
    // TODO add your handling code here:
    canvas1.addNewPosition(new Position(evt.getX(),evt.getY()));
    canvas1.removeLastPosition();
    repaint();

    /*
    canvas1.setX(evt.getX());
    canvas1.setY(evt.getY());*/        
}  

To paint ovals and make them look separated, into the canvas:

   @Override
public  void paintComponent(Graphics g){
    super.paintComponent(g);

    if(userHasMouseEntered){

            for (int i = 0; i < trail.size(); i++) {
                g.fillOval(trail.get(i).getX(), trail.get(i).getY(), 30, 30);
                try {
                    Thread.sleep(25);
                } catch (InterruptedException ex) {
                    Logger.getLogger(lienzo.class.getName()).log(Level.SEVERE, null, ex);
                }
            }


    }   
    repaint();
}

Thank you.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download