I have an Image named worldImageToUse and I have a Timer that is supposed to toggle worldImageToUse between two images every 1 second. But it does not seem to work. Help Please?
public void startWorldImageFlash() {
worldImageFlashTimer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
if(worldImageToUse == worldImage) setWorldImageBW();
if(worldImageToUse == worldImageBW) setWorldImageColor();
}
};
worldImageFlashTimer.scheduleAtFixedRate(task, 0, 1000);
}
public void stopWorldImageFlash() {
worldImageFlashTimer.cancel();
setWorldImageColor();
}
Checked twice, change the second if with "else if", that will solve the problem. Also, you should consider debugging in such cases :)
It looks like your code says if color set to black and white. Then says if black and white set to color. Wouldn't you end up with the same image every time. Your second if needs to be an else if.
Did you repaint() the component afer setting the image?
Related
I'm new to JAVA and trying to learn some concurrency concepts.
I have a simple GUI class that pops-up a window with 1 button which I want to use for pause/continue.
Also, I have a class that extends TimerTask, it looks like below and start with the GUI:
public class process extends TimerTask {
public void run() {
while(true) { /*some repetitive macro commands.. */ }
}
}
Real question is, how can I pause the task onClick of the button and also continue onClick of the button if already paused?
I have taken a step to use a boolean to flag the button as it changes from pause to continue on each click.
But then I had to type a lot of while(button); for busy waiting inside the while()...
Do you think I can make like Thread.sleep() or something but from outside the task thread?
OLD ANSWER
Basically, there is no support for pause and resume on TimerTask, you can only cancel, check here
perhaps you might want to read about threading as that's the alternative I know of that has an interrupt and start features and then you can keep track of the progress of what you're doing to resume where it stopped.
So, I will suggest you go through this link, because you need to understand threading not just copy a code to use, there is a sample code there that will definitely solve your problem also.
Note that running an endless while loop will basically cause your program not to respond, unless the system crashes. At a certain point, the data becomes an overload and the program will overflow. This means it will fail.
.
NEW ANSWER
So, response to the new question, I was able to run a tiny little program to demonstrate how you can achieve something that looks like multithreading when working with SWING.
To rephrase your question: You want to run an indefinite task like let say we're playing a song, and then onclick of a button to pause the song, on click again should continue the song?, if so, I think below tiny program might work for you.
public class Test{
static JLabel label;
static int i = 0;
static JButton action;
static boolean x = false; //setting our x to false initialy
public static void main(String[] args) {
JFrame f=new JFrame();//creating instance of JFrame
label = new JLabel("0 Sec"); //initialized with a text
label.setBounds(130,200,100, 40);//x axis, y axis, width, height
action=new JButton("Play");//initialized with a text
action.setBounds(130,100,100, 40);//x axis, y axis, width, height
f.add(action);//adding button in JFrame
f.add(label);
action.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(x){
x = false; //Update x here
action.setText("Play");
action.revalidate();
}else{
x = true; //Update x here also
action.setText("Pause");
action.revalidate();
if(x){ //Using x here to determind whether we should start our child thread or not.
(new Thread(new Child())).start();
}
}
}
});
f.setSize(500, 700);//500 width and 700 height
f.setLayout(null);//using no layout managers
f.setVisible(true);//making the frame visible
}
}
class Child implements Runnable{
#Override
public void run() {
while (x) {
//You can put your long task here.
i++;
label.setText(i+" Secs");
label.revalidate();
try {
sleep(1000); //Sleeping time for our baby thread ..lol
} catch (InterruptedException ex) {
Logger.getLogger("No Foo");
}
}
}
}
This is my first time trying to use another thread in java, could someone tell me how to make it work please? I've read others topics about it, but I didn't find a solution.
I'd like to draw a gif in another thread (drawn at at a random position and during the duration of its animation).
The problem is that drawImage() in the second thread just doesn't do anything. My counter works well (it prints 1.. 2.. 3 ...), but no image is drawn (or I can't see it).
The condition is false at the begining, then it is true at one moment (to create only one new thread and no more), then it is false again.
if (condition) {
(new ThreadGif(this,g)).start();
}
However when I remove the condition in paintComponent(), it draws something which means that drawImage() works. So when it creates lots of new threads, every image of the gif is drawn at a random location and it starts the gif again and again (and the counter(s) still work well).
This could be fine, but I don't think creating thousands of new thread is the answer : I just need one. And also, I need just one random position for each gif, not one different for each image of the gif.
I hope I've been clear enough. Please help me understand how to make it work :) Thank you very much.
Here are simplified versions of my two classes :
ThreadGif.java :
public class ThreadGif extends Thread {
Screen screen;
Graphics g;
boolean running = true;
public ThreadGif(Screen screen, Graphics g) {
this.g = g;
this.screen = screen;
}
public void run() {
int aleaX = new Random().nextInt(300)/100;
int aleaY = new Random().nextInt(300)/100;
int compt = 1;
while (running) {
g.drawImage(new ImageIcon("res/feu.gif").getImage(), screen.tailleCase*aleaX, screen.tailleCase*aleaY, screen.tailleCase*2, screen.tailleCase*2, screen);
System.out.println("thread " + compt);
compt++;
try {
Thread.sleep(sleepTime);
} catch(InterruptedException e) {
e.printStackTrace ();
}
}
}
}
Screen.java :
public class Screen extends JPanel implements Runnable {
Thread thread = new Thread(this);
public Screen(Frame frame) {
this.frame = frame;
thread.start();
}
public void paintComponent(Graphics g) {
g.clearRect(0, 0, this.frame.getWidth(), this.frame.getHeight());
if (condition) {
(new ThreadGif(this,g)).start();
}
}
public void run() {
while (running) {
repaint();
try {
Thread.sleep(sleepTime);
} catch(InterruptedException e) {
e.printStackTrace ();
}
}
System.exit(0);
}
}
Pretty simple: you mixed two approaches up.
The paintComponent-method launches a new ThreadGif every time it's called and ThreadGif itself paints within it's thread until it's terminated, but without refreshing the screen.
These two approaches combined might either result in strange behaviour, e.g. two images painted where pieces overlay each other, or the new ThreadGif simply renders the new image every-time you repaint the screen.
Solution: Start by assigning each class specific tasks, without mixing anything up, or splitting tasks between two classes. E.g.:
ThreadGif doesn't paint anything itself, but repaints the Screen. The Screen can request the image that should be displayed from ThreadGif.
Make ThreadGif an own Component that handles it's own rendering and ommit the Screen-class from painting anything.
I want my button to appear whenever an object reaches a certain position, that object is a sprite that is generated every second:
public void create() {
if(spritePosition>700) {
buttonObj.createButton();
}
}
public void render() {
if (condition==true) {
stage.draw();
}
}
The problem is that when the games starts no Sprite is generated yet, so the result is an error. I'm also thinking of calling the createButton() method on the render method but it would generate a new button every frame because it's called constantly.
A simple way to let your button "disappear" is to just set its position to some position outside of the visible screen area.
For example something like:
buttonObj.setPosition(-1000, -1000);
To make it visible again you can just set the real coordinates again!
How about:
public void create() {
buttonObj.createButton();
buttonObj.setVisible(false);
}
public void render() {
if (condition==true) {
buttonObj.setVisible(true);
}
}
All actors in Scene2d have the setVisible method. simply try :
yourButton.setVisible(true)
or
yourButton.setVisible(false);
I'm trying to create a sequence of actions to simulate eye blinking of my character but I have no idea how to properly do this. I need it to stand still for like 5 secs, then blink once and wait for 5 seconds again and loop forever. Hope someone could shed some light here.
This is what I've got so far which doesn't work to what I have expected (After 3f, it will keep blinking, how do I detect blinking animation end and reset back to stand?):
this.addAction( Actions.sequence(
Actions.run( new Runnable() {
#Override
public void run() {
stand();
}
}),
Actions.delay(.3f),
Actions.run( new Runnable() {
#Override
public void run() {
blink();
}
})));
Libgdx has a class RepeatAction, which is what you are looking for.
Basicly you need to call:
this.addAction(Actions.forever(Actions.sequence(
Actions.run(new Runnable {
#Override
public void run() {
stand();
}
}),
Actions.delay(0.3f),
Actions.run(new Runnable {
#Override
public void run() {
blink();
}
});
)));
But instead of using new Runnable you may use one of the methods provided by Libgdx Actions.
So for example, the stand(), isn't it only "do nothing"? This can be achieved with an Actions.delay(5f), which waits for 5 seconds.
And the blink() isn't it only switching from "visible" to "invisible"?
This could be don with Actions.alpha(0, 0.2f), which changes the characters transparency from its current to 0 in 0.2 seconds. Then you could add another delay to let the character "wait" in the invisible state and make it visible again with Actions.alpha(1, 0.2f).
Hope it helps.
Sorry for posting yet another thread about Java swing and loops. I have read through others and none of the solutions have really been appropriate for me. Okay so now onto the problem. I have a class extending JFrame in which I have a Timer running a stopwatch as below:
class StopWatch extends TimerTask{
public void run() {
time.setText(String.format("%02d:%02d", minutes_elapsed,seconds_elapsed));
seconds_elapsed++;
if(seconds_elapsed == 60){
seconds_elapsed = 0;
minutes_elapsed++;
}
}
}
Now the only way my Label "time" updates is when I call time.update(time.getGraphics()) but this paints over the previous time. Any ideas what I should do? I have also tried repaint,validate,and paint. Paint does the same thing for me that update does...Any Ideas?
P.S I don't know if it matters or not but I create the Timer in a public void start_timer() function which is like below:
public void start_timer(int minutes, int seconds){
if(timer == null)
timer = new Timer();
timer.scheduleAtFixedRate(new StopWatch(),0,1000);
}
I suspect you're using a java.util.Timer instead of a javax.swing.Timer. The latter will make sure that the timer runs on the UI thread, which I suspect is the problem.
See "How to use Swing Timers" for a tutorial on them. You'll want to convert your TimerTask into an ActionListener`, and then use
timer.setDelay(1000);
timer.setRepeats(true);
timer.start();
You can do this
public void run()
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
// do stuff
}
}
));
}
but you really should be using the javax.swing.Timer though. Remember that Swing is single-threaded and as such, its components must be modified in its thread (i.e. Event Dispatch Thread).