Display delayed text on User's screen - java

Hello!
I am trying to display a text on the Screen (with Java), but I want it to be delayed, like, every 0.1 seconds, a letter of the text would appear on the screen. It's like Pokemons dialogs. Here's what I am talking about: https://www.youtube.com/watch?v=yUS1IcC5CBY
I don't want the fade and the acceleration of the text, I just want the text to appear letter-by-letter. Also, I would like the text to be a String. Please, can you help me?
Thanks a lot in advance!

You can use two methods:
One is Thread.sleep(), which is shown above:
private static String message = "Your Message";
private static JLable label = new JLabel();
private static String labelMessage = "";
for(int i = 0; i < message.length(); i++){
labelMessage += Character.toString(message.charAt(i));
label.setText(labelMessage);
try{
Thread.sleep(howManyMillisecondsYouShouldWait);//if you want to do it every .1
//seconds, just wait 100 milliseconds.
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
that will forever print it to the screen every 100 milliseconds. However, the only trouble with using Thread.sleep is (and I somehow just learned this the other day, even though I've been programming for a long while) it is not always accurate. It may sleep 100 ms, it may sleep 150, etc. Secondly, a slower computer may take longer to sleep through it.
The other method which you will use more often (probably) is to check the actual time of your system and see if it's been long enough since you last printed it to the screen, like this:
private static long timeOfLastWrite;//at what time did you last update the text?
private static long deltaTimeSinceLastWrite;//how long has it been since you last updated the text?
private static long timeOfFirstWrite;//when did you start?
private static long deltaTimeSinceFirstWrite;//how long has it been since you started?
private static String message = "Your Message";
private static JLabel label = new JLabel();
private static String labelMessage = "";
//print once here:
timeOfFirstWrite = System.currentTimeMillis();
timeOfLastWrite = System.currentTimeMillis();//every time you print to the screen, make
//sure that you make note of it by setting the timeOfLastWrite variable equal to the current time.
labelMessage += Character.toString(message.chatAt(0));
while(!labelMessage.equals(message)){
deltaTimeSinceLastWrite = System.currentTimeMillis() - timeOfLastWrite;
if(deltaTimeSinceLastWrite >= 100){
timeOfLastWrite = System.currentTimeMillis();
deltaTimeSinceFirstWrite = System.currentTimeMillis() - timeOfFirstWrite;
int currentIndexOfChain = (int) deltaTimeSinceFirstWrite / 100;
if(currentIndexOfChain >= message.length()){
currentIndexOfChain = message.length() - 1;
}
labelMessage = message.substring(0, currentIndexOfChain + 1);
label.setText(labelMessage);
}
}
This method isn't even slightly necessary for a program so simple as writing text to the screen 10 times a second. However, it's good to get into the practice of it. You'll learn that if you create a character and tell him to move 10 pixels, Thread.sleep(100), and move again and etc... that on a slower computer, the character will move slower. However, if you tell it to wait until a certain amount of time has passed according to your computer's time, if the user lags out and it takes 200 milliseconds before it tells the character to move again, you can account for that by simply making him move twice as far -- I think it's called framerate independence.
If I did anything wrong with the delta time management please let me now. Again, I just learned about this the other day even though I've been programming for awhile, so don't worry about it too much if you're just now learning to program.
And that's how you make an incredibly long (possibly too long) answer to an incredibly simple question. I hope you benefit from this response.

I'm unable to use Thread.sleep(x) or wait(): java.lang.InterruptedException; must be caught or declared to be thrown
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}

You may use this code for doing so. Simply put a thread to print the text onto a jLabel.
new Thread(new Runnable() {
#Override
public void run() {
String x="";
String txt="Hello this is a sample text. Let us see how this works.";
for(int i=0;i<txt.length();i++){
try {
jLabel1.setText(x=x+txt.charAt(i));
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}).start();

How about this?
import javax.swing.Timer;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DelayText
{
public String example = "As you can see, this sentence is being printed out a character at a time.";
public String transfer = "";
public Timer t;
public int i = 0;
public JFrame f;
public JLabel l;
public DelayText()
{
f = new JFrame("Example");
l = new JLabel();
f.add(l);
f.setSize(450, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
TimerListener tl = new TimerListener();
t = new Timer(100, tl);
t.start();
}
public static void main(String[] args)
{
DelayText d = new DelayText();
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(i < example.length())
{
transfer += (example.charAt(i));
l.setText(transfer);
i++;
}
if(i >= example.length())
{
t.stop();
}
}
}
}
I am using the timer to create a delay between each character outputted on the JFrame. I noticed a lot of these other ones were a bit more complex, thought this might make things a bit easier to understand.

Related

How to "refresh" a JFrame inside an actionperformed method?

I try to design a GUI for a neural network I made recently. I am using the MNIST-dataset and want to display the handwritten digit using JPanels with the brightness-values written inside. By pressing the "train"-button the network gets trained and every new digit is displayed. However this happens in a for loop in the actionperformed method of the button and it seems that I can´t change the background of the labels or the text(at least it doesn´t display the changes) until the last one. I don´t know whether I´m right but it seems that only the last change gets displayed. That´s why my question is whether it is possible to "refresh" the JFrame inside the actionperformed method.
I already have tried revalidate(), invalidate() & validate(), SwingUtilities.updateComponentTreeUI(frame), but none of them worked.
Here is the relevant part of my code:
train.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < iMax; i++) {
...
digitRefresh(reader.getInputs()[i], (int) reader.getInputs()[i][0], 0);
}
}
});
.
public void digitRefresh(double[] pixelValue, int target, int result) {
for (int i = 0; i < 784; i++) {
double value = pixelValue[i + 1];
int brightness = (int) (value * 255);
l_digit[i].setText(String.valueOf(value));
l_digit[i].setBackground(new Color(brightness, brightness, brightness));
}
l_target.setText(String.valueOf(target));
l_result.setText(String.valueOf(result));
this.revalidate();
}
thank you for every awnser and sorry for my bad english.
The simplest thing to do is start a new thread.
#Override
public void actionPerformed(ActionEvent e) {
new Thread( ()->{
for (int i = 0; i < iMax; i++) {
...
final int fi = i;
EventQueue.invokeLater( ()->{
digitRefresh(reader.getInputs()[fi], (int) reader.getInputs()[fi][0], 0);
});
}).start();
}
Now all of the work is being done on a separate thread, then as the ... work finishes, digit refresh method called from the EDT. Notice the final int fi part. There are caveats about going back and forth on threads so it is good to look into better controls than just using thread.
Swing worker for example:
How do I use SwingWorker in Java?

Java game keeps crashing after about 2 minutes of runtime (Intellij)

I am using Intellij to program Java.
I am currently trying to make a top down tile based shooter.
My issue is that my game, after approximately 2 minutes, crashes with a popup saying "Java(TM) Platform SE Binary has stopped working. I recorded the time it took for it to crash 3 times: 1m57s, 1m59s, 1m58s.
The game is in a very simple state right now and I am not sure what could be causing the crash. All of the relevant code is in just two classes: GameFrame.java (extends JFrame) and GamePanel.java (which extends JPanel).
GameFrame.java:
package net.magnusfrater.tds.game;
import javax.swing.*;
public class GameFrame extends JFrame {
public static final int width = 1000;
public static final int height = width / 16 * 10;
private GamePanel gp;
public GameFrame () {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width,height);
setResizable(false);
setLocationRelativeTo(null);
setTitle("Time Based Fast Paced Top Down Shooter Demo");
gp = new GamePanel();
add(gp);
setVisible(true);
}
public static void main (String[] args) {
GameFrame gf = new GameFrame();
}
}
GamePanel.java
package net.magnusfrater.tds.game;
import net.magnusfrater.tds.input.Keyboard;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel implements Runnable {
//panel
private Thread thread;
private static boolean running;
private boolean fpsLock;
//input
private Keyboard kb;
//game
private Game game;
public GamePanel () {
//panel
thread = new Thread(this, "Time Based Fast Paced Top Down Shooter Demo");
running = true;
fpsLock = true;
//input
//kb = new Keyboard();
//addKeyListener(kb);
//game
//game = new Game(1);
thread.start();
}
public void run () {
long iTimeNS = System.nanoTime();
int tickRate = 60;
long ns = 1000000000 / tickRate;
int ups = 0;
int fps = 0;
long iTimeS = System.nanoTime();
long s = 1000000000;
while (running) {
long fTimeNS = System.nanoTime();
if (fTimeNS - iTimeNS >= ns){
iTimeNS = System.nanoTime();
tick();
ups++;
if (fpsLock){
repaint();
fps++;
}
}
if (!fpsLock){
repaint();
fps++;
}
long fTimeS = System.nanoTime();
if (fTimeS - iTimeS >= s){
iTimeS = System.nanoTime();
System.out.println("ups: " + ups + "\tfps: " + fps);
ups = 0;
fps = 0;
}
}
System.exit(0);
}
public void tick () {
if (kb != null)
kb.tick();
if (game != null)
game.tick();
}
#Override
public void update (Graphics g) {
paint(g);
}
#Override
public void paint (Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0,0,GameFrame.width, GameFrame.height);
//if (game != null)
//game.paint(g);
}
public static void quitGame () {
running = false;
}
}
I originally thought that the issue was because of the way that I was loading images for spritesheets or maybe the way I was loading text files for the level design but after reworking both of those, the issue remained.
That left me curious and a little bit fed up so I tried finding out more about the explanation for the crash. First I read more from the popup but it didn't say anything useful: (See below)
Second I looked at the exit code given by Intellij: (See below)
I looked up what exit code 255 was but there wasn't anything useful. The best explanation I could find was that exit code 255 meant that the real exit code was out of range: (See below)
I was out of ideas at this point so I just started plain old googling everything I could think of. The problem with googling "Java(TM) Platform SE Binary has stopped working" is that almost every suggested link is a question about Minecraft. Limiting my search to Stack Overflow yielded me some results, but nothing conclusive. Some of the fixes I found were stuff I already tried (such as not handling input streams properly, not handling buffered reader properly, not disposing of elements, etc). I found these links but none of them were truly related to my issue:
(See below)
(See below)
(See below)
(See below)
(See below)
(See below)
The last fix I tried was to re-install Java SE Development Kit 8u101 AND Java SE Development Kit 8u102. I then restarted Intellij. I then restarted my computer.
Nothing worked.
At this point I think I'm just dumb. I've overlooked something easy I can tell. What am I missing?
(ps~ This is a possibly related issue. So if I run my game with almost no content in it with the fps not locked to 60, I get really absurd numbers of frames per second. I didn't think that fps as high as 7,000,000 was possible. I think. I don't know. Have I programmed that wrong as well? Here is a related picture of my ups/fps output: [see below])
(SEE HERE) So Stack Overflow doesn't allow members with a score within a certain threshold post more than 2 links and allows absolutely no posting of images. So here is a link to a google doc with all of the links and images I mentioned above:
https://docs.google.com/document/d/1XrBuVio19GmkFz0EfRzXVp5AJmM5zPfVO6vK3oS3Eaw/edit?usp=sharing
Try and set your -Xmx to something like 2G and see if it runs longer. If so, something is allocating memory and maybe you have that other setting set that exits instead of garbage collecting for some reason.
Also, try changing your code to limit things using Guava's RateLimiter.
…
// class level
final RateLimiter frameLimiter = RateLimiter.create(60.0);
final RateLimiter outputLimiter = RateLimiter.create(1.0);
…
// in run method
while (running) {
frameLimiter.acquire();
repaint();
fps++;
if (outputLimiter.tryAcquire()){
System.out.println("fps: " + fps);
fps = 0;
}
}
I've removed ups and tick(). You should do your work after repainting and I don't think you want to do more work than needed for the next frame, which at the soonest should be at your max rate. Later you'll need to add logic to handle skipping work when frames are being skipped. I might make more sense to increment the fps within repaint.
You could put the output in its own thread and only acquire that limiter if you synchronized the increments and resetting of fps.

Thread wont start on Java

The following code should produce a regular frame with time in it, when the time hit 90 minutes it should display a message. somehow the Thread wont start and the message Thread is working properly is never displayed. i have already read the following Oracle article but couldn't find any solution.
public class Core extends JFrame implements Runnable{
private int second;
private int minute;
private JLabel presentor;
private Thread threadObject = new Thread();
public Core(){
second = 1;
minute = 0;
presentor = new JLabel();
writeLabel();
add(presentor , BorderLayout.CENTER);
threadObject.start();
}
public void run(){
JOptionPane.showMessageDialog(null, "Thread is working properly");
try{Thread.sleep(60000);}
catch(InterruptedException e){e.printStackTrace();}
updateTime();
writeLabel();
if(minute > 89){
JOptionPane.showMessageDialog(null, "90 minutes have passed away , take a break!");
this.getParent().setFocusable(true);
}
}
public void writeLabel(){
presentor.setText(minute + ":" + second);
}
public void updateTime(){
second++;
if(second < 60)
return;
second = 0;
minute++;
}
}
there is also a class with the Main method which have the basic frame setting, nothing important there.
You didn't specify a Runnable argument for your Thread (which I assume should be this since your Core class implements Runnable):
private Thread threadObject = new Thread(this);
TNT's answer is correct, but it's not complete. Your program has more than one problem. The next problem you will face is that there's no loop in your run() method. It will call updateTime() and writeLabel() exactly once, and then the thread will terminate.
The next problem after that, is in your updateTime() method. It appears as if it's meant to count seconds, but your run() method looks like, if it had a loop, it would only call updateTime() once every minute. That means it will take 90 HOURS, not 90 minutes before your program pops up the dialogue.

Return a String from a JButton press Action Listener?

I've been trying for a while to get a JButton I have to return a string and I have it working to an extent however it only works when i'm using the System.out.println() method.
My Relevant Code:
private String answer;
public void inputDataButton(JButton inButton)
{
inButton.addActionListener(new Action1());
}
public String returnAnswer()
{
return answer;
}
private void fileAnswer(String inString)
{
answer = new String(inString);
}
public class Action1 implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String sub = JOptionPane.showInputDialog("Input The Date");
fileAnswer(sub);
}
}
With my Main controlling it:
public class test
{
protected static JTextField text;
public static void main(String[] args)
{
javaUI base = new javaUI("Date Killer", 800, 800);
JLabel label = new JLabel("Place Holder");
base.addLabel(label, 1, 0, false);
JButton button = new JButton("Press Here");
base.addButton(button, 0, 0, false);
String str = "EMPTY";
base.inputDataButton(button);
while (str == "EMPTY")
{
str = base.returnAnswer();
}
System.out.println(str + " TEST");
label.setText(str + "SETTED");
}
}
JavaUI is simply another class with simplifies the entire JFrame and Jpanel setup for Labels, Buttons etc.
Anyways, heres my problem. In the main class, in the while statement, str is successfully set to the string if I have a System.out.println() statement directly after.
This obviously makes quite a mess of the terminal as it repeates "EMPTY" 100+ times until the button is pressed.
However if I remove that statement, nothing is obviously printed out, but str is never set to the str either.
I've been messing around with this for quite a while (New to all java UI stuff, mainly just worked in the calculations part of things) and I've yet to find a working solution that doesn't make a mess of my terminal. Thanks for all the Help!!!
Cail
1) It's a little strange to use a loop to "wait" for the action to happen. You can watch your cpu usage and it could be dead if it loops forever.
2) Also, the method will return no matter whether your button is clicked -- Before the action happens, the method returns a null string according to your code. And in your main method, str == "EMPTY" soon becomes false after the first round. Then you'll see "null TEST" on your screen.
Try to put the code after while loop into actionPerformed method or fileAnswer method and delete the loop:
public void actionPerformed(ActionEvent e)
{
String sub = JOptionPane.showInputDialog("Input The Date");
System.out.println(sub + " TEST");
label.setText(sub + "SETTED");
}
Also, I am not sure why you call answer = new String(inString). If you want to assign it to another variable, you only need to call answer = inString since String is unmodifiable. And in this case, you don't to do this.

How To Reset JFrame (Restart Game)?

This is a java game that I have started working on.I have been trying to add a button that says "RESTART" which on clicking resets the whole program the way it was when it was at the beginning( i mean at the start of the game).
Here is my code:
There are 2 buttons namely "PLAY" & "CHECK WHO WON!"
For "PLAY" This is the code:
int delay = 1000;
final Timer timer = new Timer();
timer.schedule(new TimerTask(){
public void run(){
String b = "C:\\Users\\COMPUTER\\Desktop\\deck\\.png";
Random r = new Random();
r1 = r.nextInt(upplim)+lolim;
String a = Integer.toString(r1);
String c = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+a+".png";
l1.setIcon(new ImageIcon(c));
}
},delay, 50);
For "CHECK WHO WON!" This is the code:
final int p = h;
System.out.println("ANSWER IS:"+p);
int delay2 = 1000;
for (int i = 1; i < 53; i++)
{
while(true)
{
next = rng.nextInt(Ulim) + Llim;
if (!generated.contains(next))
{
generated.add(next);
break;
}
}
if ( i % 2 == 0 )
{count++;
deck1[e] = next;deck1count++;
e++;
}
else {count++;
deck2[f] = next;deck2count++;
f++;
}
System.out.println(""+next);
if(next==p)
{break;}
}
if(deck1count==deck2count)
{
count=count-2;
fcard=99;}
final Timer timer2 = new Timer();
timer2.schedule(new TimerTask(){
public void run(){
do
{
System.out.println("dec2 "+deck2[z]);
String a = Integer.toString(deck2[z]);
String c = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+a+".png";
l3.setIcon(new ImageIcon(c));
System.out.println("dec1 "+deck1[z]);
String b = Integer.toString(deck1[z]);
String d = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+b+".png";
l4.setIcon(new ImageIcon(d));
System.out.println("count"+count);
z++;
count=count-2;
if(fcard==99&&count<0)
{l3.setIcon(new ImageIcon("C:\\Users\\COMPUTER\\Desktop\\deck\\99.png"));
}
}while(count>0&&z==p);
if(count<0)
{timer2.cancel();
reschk=11;
timer2.purge();
}
}
},delay2, 1000);
There is also another set of code which is written on the MouseClicked event of a label but I don't think it would be of much help here.
I have tried:
classname.this.dispose();
classname classname = new classname();
But it just shuts the whole program down.Is there any other way to reset the game?
Thanks for reading.
Any help would be appreciated.
You obviously have values which update so that you can represent your game during different states. If you want to restart your game, you simply need to set all of these values back to the original start values. You can write a Restart method to this.
Also, dispose() is designed to close the window.
edit: There is no magic method you can call to reset your program.
For Swing based container use Swing Timer rather than util.Timer, otherwise output from util.Timer should be out of EDT.
You don't need to dispose old container and recreate a new for fresh game, you can remove its contents.
anything else isn't clear from code posted here, nor question
Keep the state of the game in a distinct class and replace that with a fresh instance.

Categories

Resources