Domanda

I want to know when I am writing and when I am deleting, but, after a 0.5 second delay, it will tell me "You stopped writing/deleting" However, it only shows that message and it delete or write after a half second delay.

How could I use Thread.sleep(500); correctly?

My current source code:

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;


public class TextChangedFrame extends JFrame {

    JTextField textField = new JTextField("Put your text here");
    JLabel label = new JLabel("You have written: ");

    public TextChangedFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(300, 100);
        setLayout(new BorderLayout());
        getContentPane().add(textField, BorderLayout.CENTER);
        getContentPane().add(label, BorderLayout.SOUTH);
        textField.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                label.setText("I'm writting: " + textField.getText());
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ex) {

                }
                label.setText("I stopped writing");
            }

            public void removeUpdate(DocumentEvent e) {
                label.setText("I'm deleting");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ex) {

                }
                label.setText("I stopped deleting");
            }

            public void changedUpdate(DocumentEvent e) {
            }
        });
    }

    public static void main(String[] args) {
        TextChangedFrame frame = new TextChangedFrame();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
È stato utile?

Soluzione

Again, use a Swing Timer to do the dirty work. What you do is whenever you edit or delete, call re-start on the Timer to re-set the timer and start it. The restart() method will stop the Timer if it is running.

     public void insertUpdate(DocumentEvent e) {
        label.setText(EDITING);
        writeDeleteTimer.restart();
     }

For example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

@SuppressWarnings("serial")
public class TextChangedFrame extends JPanel {

   public static final String STOPPED_EDITING = "No Longer Editing or Deleting";
   private static final String EDITING = "Editing";
   private static final String DELETING = "Deleting";
   private static final int TIMER_DELAY = 500;
   private static final int PREF_W = 400;
   private static final int PREF_H = 100;
   private JTextField textField = new JTextField("Put your text here");
   private JLabel label = new JLabel("You have written: ");
   private ActionListener timerListener = new TimerListener();
   private Timer writeDeleteTimer = new Timer(TIMER_DELAY, timerListener);

   public TextChangedFrame() {
      setLayout(new BorderLayout());
      add(textField, BorderLayout.CENTER);
      add(label, BorderLayout.SOUTH);
      textField.getDocument().addDocumentListener(new DocumentListener() {

         public void insertUpdate(DocumentEvent e) {
            label.setText(EDITING);
            writeDeleteTimer.restart();
         }

         public void removeUpdate(DocumentEvent e) {
            label.setText(DELETING);
            writeDeleteTimer.restart();
         }

         public void changedUpdate(DocumentEvent e) {
         }
      });
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent evt) {
         label.setText(STOPPED_EDITING);
         Timer timer = (Timer) evt.getSource();
         timer.stop();
      }
   }

   private static void createAndShowGui() {
      TextChangedFrame mainPanel = new TextChangedFrame();

      JFrame frame = new JFrame("TextChangedFrame");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Answer edited: no need to recreate the Timer object. Simply call restart() on it as it will stop the current Timer if it's running.

Altri suggerimenti

This question is fairly poor, and is not very clear, so I cannot give an exact answer until the question is cleared up.

It seems currently that you are using Thread.sleep(500) to cause a delay for 500 milliseconds. In most programs, this will work.

Thread.sleep(int x) suspends (or freezes, depending on who you ask) the current operation for x milliseconds (in your case, 500 milliseconds).

In the application you are using, you are using it to suspend a change in text. Due to it's location, it currently freezes the entire swing box, and it is not recovering.

If you HAVE to use Thread.sleep(int x), then I would recommend that you save the text you are using as a String, then update the TextChangedFrame after you update the String. This allows you to suspend operations, without suspending the TextChangedFrame.

PsuedoCode:

String oldString = "old string";
String newString = "new string";

// setup your dialog/popup here, with oldString

Thread.sleep(500);

// modify the dialog/popup here, changing oldString to newString

and that should avoid any freezing issues. (which I think, with the question and comments, your problem is).

A better solution would be to use Swing Timers, as mentioned by Hovercraft Full Of Eels in his comment

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top