Incremento exponencial en lugar de lineal
Buenas, amigos de Java; mi duda es la que sigue:
Escribí un programa que dibuja un globito (un círculo sencillo en un panel con Graphics) y le coloqué un temporizador para que subiera diez pixeles cada segundo.
El problema es que, el primer segundo sube como debe, 10 px, el segundo sube 20px, esto lo pude comprobar colocando un JTextField que muestra el valor de Y cada vez que se vuelve a dibujar el globo y va incrementando el valor que resta a la posición Y de mi dibujo, lo correcto para este programa es que el primer dibujo se realizara en 235, el segundo en 225, el tercero en 215 y así, anexo el código para que lo examinen y me puedan decir porqué está funcionando de esa manera incorrecta, gracias de antemano a todos.
import java.awt.event.*;
import javax.swing.*;
public class GlobitoVolador extends JFrame implements ActionListener{
private int posicionY = 245;
private JPanel panel;
private JButton boton;
private Timer temporizador;
private JTextField valorY;
public static void main (String args[]){
GlobitoVolador demo = new GlobitoVolador();
demo.setTitle("Globito que vuela");
demo.setSize(400, 400);
demo.creaGUI();
demo.setVisible(true);
}//Fin de main
private void creaGUI(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container ventana = getContentPane();
ventana.setLayout(new FlowLayout());
panel = new JPanel();
panel.setBackground(Color.white);
panel.setPreferredSize(new Dimension(300, 300));
ventana.add(panel);
boton = new JButton("Despegue");
boton.addActionListener(this);
ventana.add(boton);
valorY = new JTextField(5);
ventana.add(valorY);
}//Fin de creaGUI
public void actionPerformed(ActionEvent event){
Graphics papel = panel.getGraphics();
papel.setColor(Color.white);
papel.fillRect(0, 0, 300, 300);
temporizador = new Timer(1000, this);
temporizador.start();
papel.setColor(Color.BLACK);
papel.drawOval(120, posicionY, 50, 50);
posicionY = posicionY - 10;
valorY.setText(Integer.toString(posicionY));
}//Fin de aP
}//Fin de la clase GlobitoVolador
- Inicie sesión o regístrese para enviar comentarios
Podrías usar un wait
Hola, viendo tu programa creo que podrías hacer uso de un wait dentro del método actionPerformed, sería como temporizador.wait(1000); (encerrándolo en un bloque try-catch junto con todo lo demás para que se pinte el globo, abarcando desde Graphics papel...). Eso haría yo.
Lo intentaré
Ah, muchas gracias, voy a intentarlo y avisaré del resultado :D
Tal vez pudieras resolverlo de otra forma
Mira te dejo este código, aunque no se si te sirva, lo que hago es tener una clase que herede java.util.Observable y ahí realizo todo el trabajo.
Lo que logré es tener la vista en una clase, después al botón le implemente un actionlistener para que escuche el evento al ser pulsado y, cuando esto sucede, se ejecuta el timer y se pone en marcha todo lo demás.
Main
public static void main(String[] args) {
VistaGlobo vista = new VistaGlobo();
vista.arrancarVista();
}
}
Vista
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class VistaGlobo {
private JFrame framePrincipal;
private JPanel pnlGlobo;
private JButton btnDespegue;
private JTextField txtValorY;
public VistaGlobo() {
framePrincipal = new JFrame();
pnlGlobo = new JPanel();
btnDespegue = new JButton();
txtValorY = new JTextField();
framePrincipal.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
framePrincipal.setLayout(new FlowLayout());
pnlGlobo.setBackground(Color.WHITE);
pnlGlobo.setPreferredSize(new Dimension(300, 300));
btnDespegue.setText("Despegar");
btnDespegue.setActionCommand("DESPEGAR");
btnDespegue.addActionListener(new Controlador(this));
txtValorY.setPreferredSize(new Dimension(100, 25));
framePrincipal.add(pnlGlobo);
framePrincipal.add(btnDespegue);
framePrincipal.add(txtValorY);
}
public void arrancarVista() {
getFramePrincipal().setTitle("Globo que vuela");
getFramePrincipal().setSize(400, 400);
getFramePrincipal().setLocationRelativeTo(null);
getFramePrincipal().setResizable(false);
getFramePrincipal().setVisible(true);
}
public JButton getBtnDespegue() {
return btnDespegue;
}
public JFrame getFramePrincipal() {
return framePrincipal;
}
public JPanel getPnlGlobo() {
return pnlGlobo;
}
public JTextField getTxtValorY() {
return txtValorY;
}
public void setTxtValorPosicion(int valorPosicionGlobo) {
getTxtValorY().setText(String.valueOf(valorPosicionGlobo));
}
}
Controlador
import java.awt.event.ActionListener;
public class Controlador implements ActionListener {
private VistaGlobo vistaGlobo;
public Controlador(VistaGlobo vistaGlobo) {
this.vistaGlobo = vistaGlobo;
}
@Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand().equals("DESPEGAR")) {
getVistaGlobo().getBtnDespegue().setEnabled(false);
new TimerGlobo(getVistaGlobo());
}
}
public VistaGlobo getVistaGlobo() {
return vistaGlobo;
}
}
Timer
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import javax.swing.Timer;
public class TimerGlobo extends Observable {
private VistaGlobo vistaGlobo;
private Graphics graficoPanel;
private Timer timer;
private int posicionGlobo = 245;
public TimerGlobo(VistaGlobo vistaGlobo) {
this.vistaGlobo = vistaGlobo;
timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
getVistaGlobo().setTxtValorPosicion(getPosicionGlobo());
graficoPanel = getVistaGlobo().getPnlGlobo().getGraphics();
graficoPanel.setColor(Color.WHITE);
graficoPanel.fillRect(0, 0, 300, 300);
graficoPanel.setColor(Color.BLACK);
graficoPanel.drawOval(120, getPosicionGlobo(), 50, 50);
setPosicionGlobo(getPosicionGlobo() - 10);
if (getPosicionGlobo() < 0) {
getVistaGlobo().getBtnDespegue().setEnabled(true);
getVistaGlobo().getTxtValorY().setText("");
timer.stop();
}
}
});
timer.start();
}
public int getPosicionGlobo() {
return posicionGlobo;
}
public VistaGlobo getVistaGlobo() {
return vistaGlobo;
}
public void setPosicionGlobo(int posicionGlobo) {
this.posicionGlobo = posicionGlobo;
}
}
Saludos
Inicialízalo en la declaración...
Oye si todavía es oportuno, solo tienes que inicializarlo en la declaracion, en ves de hacerlo en el actionPerformed, de esta manera realiza el incremento lineal como lo quieres...
lo demás lo dejas igual...
Ya te respondió Arturo. Pero
Ya te respondió Arturo.
Pero ahí va otra explicación, si comentas la línea donde limpias el dibujo:
Te darás cuenta de que sí está haciendo el dibujo cada vez con y - 10, lo que pasa es que cada vez que lo haces, llamas al método
actionPerformed(ActionEvent)
que a su vez crea otro timer the hace lo mismo, el resultado es que cada vez es más rápido y solo puedes ver como se decrementa exponencialmente.