0

I need a simple way to make Methods that can be used in a JLabel. I want to make a .write(some text); Method that whenever I call jLabel.write(some text); it writes out some text letter by letter. I can easily do this with the console, but I do now know how to do it in a JLabel.

Example Code:

public void write(String a) {
    char letter;
    String word = "";
    for(int i = 0; i < a.length(); i++) {
        letter = a.charAt(i);
        this.setText(word + letter);
        word = word + letter;
        try {
            Thread.sleep(100);
        } catch(Exception e) {
        }
    }
}

...

text.write("Hello");

For obvious reasons this does not work. But is there any way to make it?

  • 4
    You should at least start with [Concurrency in Swing](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/) and [How to Use Swing Timers](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) - [For a really basic example](http://stackoverflow.com/questions/13691339/adding-a-timer-and-displaying-label-text/13691413#13691413) – MadProgrammer May 03 '17 at 05:13
  • `JLabel` already provides methods which you can use. – Jay Smith May 03 '17 at 05:31

2 Answers2

2

Here is the complete example of the label, you're want to get:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class JPrintLabel extends JLabel {

    private Dimension storedSize;

    private Timer printTimer;

    public void write(final String text) {
        // stop old timer if required
        if (printTimer != null) {
            printTimer.stop();
        }
        // compute size
        if (!isPreferredSizeSet()) {
            setText(text);
            storedSize = getPreferredSize();
            setText("");
        }
        printTimer = new Timer(200, new ActionListener() {
            int counter;
            @Override
            public void actionPerformed(ActionEvent e) {
                if (counter >= text.length()) {
                    printTimer.stop();
                    printTimer = null;
                } else {
                    setText(text.substring(0, ++counter));
                }
            }
        });
        printTimer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet() || storedSize == null) {
            return super.getPreferredSize();
        } else {
            return storedSize;
        }
    }

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

            @Override
            public void run() {
                JFrame frm = new JFrame("Test print");
                JPrintLabel pl = new JPrintLabel();
                frm.add(pl);
                pl.write("Here is the text, we want to print!");
                frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frm.pack();
                frm.setLocationRelativeTo(null);
                frm.setVisible(true);
            }
        });
    }
}
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
1

To do this we need 4 steps:

  • 1) make a new class that extends a JLabel,
  • 2) adds a timer and a method to write the text
  • 3) create an instance of your custom JLabel, then
  • 4) use your write method

New class and method for steps 1 and 2:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.Timer;

public class MyCustomJLabel extends JLabel{
    private String text = "";

    public void write(String textToWrite) {
        int delay = 1000; //milliseconds
        ActionListener taskPerformer = new ActionListener(){
            int characterCount = 0;
            public void actionPerformed(ActionEvent evt){
                if (characterCount == textToWrite.length())
                {
                    ((Timer)evt.getSource()).stop();
                }
                getThisLabel().setText(textToWrite.substring(0, characterCount));
                characterCount++;
            }
        };
        new Timer(delay, taskPerformer).start();
    }

    private MyCustomJLabel getThisLabel(){
        return this;
    }
}

New in your main method do step 3:

MyCustomJLabel myLabel = new MyCustomJLabel():
myForm.add(myLabel);

Step 4, you can do your method by using myLabel.write:

myLabel.write("my text to print 1 letter at a time");

Thanks Sergiy Medvynskyy for the comment, the code has been corrected.

sorifiend
  • 5,927
  • 1
  • 28
  • 45
  • Your code is wrong: you'll get printed all your text at once in about 3 seconds. No letter by letter pattern. Also you should override `getPreferredSize()` method to provide correct sizing of your text. – Sergiy Medvynskyy May 03 '17 at 07:00
  • @SergiyMedvynskyy Right you are, i have corrected my answer to correctly print with a delay, but will let `getPreferredSize()` use default behavior because OP should probably be using a layout manager. – sorifiend May 03 '17 at 07:28