Estoy tratando de hacer una sencilla aplicación java que cuenta a tiempo, con la capacidad para iniciar y detener el temporizador. Sin embargo, la etiqueta de no actualizar, y cuando yo pulse inicio, se congela.

Podría usted ayudarme a averiguar cuál es el problema?

package random;

import javax.swing.JFrame;

public class Timer {
boolean shouldCount=false;
int int_sec=0;
int int_min=0;
int int_mil=0;
public static void main(String[] args) {
    TimeFrame t = new TimeFrame();
    JFrame f = new JFrame("Timer");
    f.setSize(300,200);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    f.getContentPane().add(t);
    f.setVisible(true);
}

public void count(){
    TimeFrame t = new TimeFrame();
    if(shouldCount){
        long now = System.currentTimeMillis();
        while(true){
            if(System.currentTimeMillis()-now>=100){
                now=System.currentTimeMillis();
                String sec = Integer.toString(int_sec);
                String min = Integer.toString(int_min);
                String mil = Integer.toString(int_mil);
                t.update(sec,int_sec,min,mil,int_mil);
                int_mil++;
                if(int_mil>9){
                    int_mil=0;
                    int_sec++;
                    if(int_sec>=60){
                        int_sec=1;
                        int_min++;
                    }
                }
            }
        }
    }
}
}

Y aquí es TimeFrame.java

    package random;

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    public class TimeFrame extends JPanel{
    JLabel time = new JLabel("Time goes here", JLabel.CENTER);
    Timer t = new Timer();
    JButton pause = new JButton ("Pause");
     JButton start = new JButton ("Start");
    public TimeFrame(){

         start.addActionListener(new starts());
         pause.addActionListener(new starts());
         add(time);
         add(start);
         add(pause);
    }
    public void update(String sec,int s, String min,String mil,int m){
        if (s<=10){
            sec="0"+sec;
        }
        System.out.println(min+":"+sec+","+mil);
        time.setText(min+":"+sec+","+mil);

    }
    public class starts implements ActionListener{
        public void actionPerformed(ActionEvent event){
            if(event.getSource() == start){
                t.shouldCount=true;
            }else{
                t.shouldCount=false;
            }
            t.count();
        }
    }
}
  • Por qué no utilizar un javax.swing.Timer en lugar de un while bucle?
  • también, podría ser posible que usted está intentando actualizar la interfaz gráfica de usuario hilo de otro hilo, lo que causará problemas. Creo que hay un runLater() thread cosa que puede permitir que usted para actualizar la interfaz gráfica de usuario hilo de otros subprocesos de forma segura.
InformationsquelleAutor Quar | 2013-09-20

2 Comentarios

  1. 3

    El problema es que usted tiene sólo un hilo en su aplicación. Usted debe tener al menos dos : uno para la interfaz de usuario que va a actualizar el texto y otro para el cómputo del tiempo.

    Si usted tiene sólo un hilo que cuelga en el while(true) bucle y el Swing llegar nunca a actualizar la vista.

    Me refactorizado el código con dos subprocesos :

    1. Uno contando hasta el final de los tiempos y la actualización de los campos a la hora de mantener en la memoria

    2. Otro que usa java.util.Temporizador#scheduleAtFixedRate() método que es invocada cada 100 millisec para actualizar la vista.

    Timer.java (evitar nombrar a las clases como en la API de Java)

        public class Timer {
    
            boolean shouldCount=false;
            int int_sec=0;
            int int_min=0;
            int int_mil=0;
    
            public Timer() {
            }
    
            public static void main(String[] args) {
                TimeFrame t = new TimeFrame();
                JFrame f = new JFrame("Timer");
                f.setSize(300,200);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setLocationRelativeTo(null);
                f.getContentPane().add(new TimeFrame());
                f.setVisible(true);
            }
    
            public void count(){
                    Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            long now = System.currentTimeMillis();
                            while(true){
                            if(shouldCount){
                                if(System.currentTimeMillis()-now>=100){
                                    now=System.currentTimeMillis();
                                    int_mil++;
                                    if(int_mil>9){
                                         int_mil=0;
                                         int_sec++;
                                         if(int_sec>=60){
                                              int_sec=1;
                                              int_min++;
                                         }
                                    }
                                }       
                            }
                        }               
                    }
                });
                thread.start();
            }
        }
    }

    TimeFrame (Yo diría que es TimePanel ya que se extiende JPanel)

    public class TimeFrame extends JPanel{
    JLabel time;
    Timer t ;
    JButton pause ;
    JButton start ;
    public TimeFrame(){
    t= new Timer(this);
    time = new JLabel("Time goes here", JLabel.CENTER);
    pause = new JButton ("Pause");
    start = new JButton ("Start");
    start.addActionListener(new starts());
    pause.addActionListener(new starts());
    add(time);
    add(start);
    add(pause);
    java.util.Timer updateTimer= new java.util.Timer();
    updateTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
    t.update(int_sec,int_min,int_mil);
    }
    }, 0, 100);
    }    
    public void update(int s, int minute,int m){
    String sec = Integer.toString(s);
    String min = Integer.toString(minute);
    String mil = Integer.toString(m);
    if (s<=10){
    sec="0"+sec;
    }
    System.out.println(min+":"+sec+","+mil);
    time.setText(min+":"+sec+","+mil);
    }
    public class starts implements ActionListener{
    boolean firstTime=true;
    public void actionPerformed(ActionEvent event){
    if (firstTime){
    t.count();
    firstTime = false;
    }
    if(event.getSource() == start){
    t.shouldCount=true;
    }else{
    t.shouldCount=false;
    }
    }
    }
    }
    • Gracias funciona bien excepto por el botón de pausa. He leído el código y yo pensaba que iba a funcionar pero no es así, ¿sabes por qué?
    • bueno, sí hay algunas cosas a cambio para hacer este trabajo. Voy a mirar en él, pero también puede probar por ti mismo
    • Cuando se establece que debe contar para verdadero o falso, esto no afectará a su mientras que el verdadero bucle, ya que la condición nunca se evalúa. Poner la enfermedad en el interior del bucle while y quitar la t.count() de la ActionListener, porque iba a crear un nuevo Hilo.
    • Ahora debería funcionar…
    • He intentado lo que sugiere y funcionó gracias!
  2. 1

    El problema es el bucle while se vincula a su subproceso de la interfaz. Cuando usted haga clic en el botón de arranque Temporizador de llamadas.count() y, a continuación, entra en un bucle infinito causando la interfaz de estar atascado y no actualizar.

    La hipótesis de que el uso de java.util.Clase Timer es mejor puede estar por encima de la estimación de que la funcionalidad de las clases para este problema específico. No contiene un método pause y tiene que volver a crear el temporizador cuando se desea hacer una pausa, causando algunos de los posibles retos difíciles para la adición de tiempo.

    Lo que yo haría es hacer que su temporizador de implementar la interfaz runnable y el uso de un hilo para mantener las pestañas en el momento actual. Heres los cambios que yo haría

    Aviso yo hice a los campos privados. Es la práctica adecuada para hacer sus campos privado (si es que debe ser) y el uso de getters y setters para conceder acceso a ellos. por ejemplo: getCurrentTime()

    Timer.java:

    package random;
    import javax.swing.JFrame;
    public class Timer implements Runnable {
    private Thread runThread;
    private boolean running = false;
    private boolean paused = false;
    private TimeFrame timeFrame;
    private long summedTime = 0;
    public Timer(TimeFrame timeFrame) {
    this.timeFrame = timeFrame;
    }
    public static void main(String[] args) {
    TimeFrame t = new TimeFrame();
    JFrame f = new JFrame("Timer");
    f.setSize(300,200);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLocationRelativeTo(null);
    f.getContentPane().add(t);
    f.setVisible(true);
    }
    public void startTimer() {
    running = true;
    paused = false;
    //start the thread up
    runThread = new Thread(this);
    runThread.start();
    }
    public void pauseTimer() {
    //just pause it
    paused = true;
    }
    public void stopTimer() {
    //completely stop the timer
    running = false;
    paused = false;
    }
    @Override
    public void run() {
    long startTime = System.currentTimeMillis();
    //keep showing the difference in time until we are either paused or not running anymore
    while(running && !paused) {
    timeFrame.update(summedTime + (System.currentTimeMillis() - startTime));
    }
    //if we just want to pause the timer dont throw away the change in time, instead store it
    if(paused)
    summedTime += System.currentTimeMillis() - startTime;
    else 
    summedTime = 0;
    }
    }

    TimeFrame.java:

    package random;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    public class TimeFrame extends JPanel{
    private JLabel time = new JLabel("Time goes here", JLabel.CENTER);
    private Timer timer;
    private JButton pause = new JButton ("Pause");
    private JButton start = new JButton ("Start");
    public TimeFrame(){
    timer = new Timer(this);
    start.addActionListener(new starts());
    pause.addActionListener(new starts());
    add(time);
    add(start);
    add(pause);
    }
    public void update(long dT){
    //convert milliseconds into other forms
    time.setText(String.valueOf((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000));
    }
    public class starts implements ActionListener{
    public void actionPerformed(ActionEvent event){
    if(event.getSource() == start){
    timer.startTimer();
    }else{
    timer.pauseTimer();
    }
    }
    }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here