Reputation: 214
I'm looking for an example where is needed to change dinamically the image x.png
when an certain variable x
getting value 1 into y.png
, when this variable going back to 0 restore the old image. If this is possible , how? thanks for help
im trying whith this code but have no succes...
this is my controller class
public class FXMLDocumentController implements Initializable {
@FXML
private ImageView myImage;
@Override
public void initialize(URL url, ResourceBundle rb) {
Random random = new Random();
while (true) { // <-- this is the problem how i can do that without while(true)??
int x = random.nextInt(1);
if (x == 0) {
Image image = new Image(getClass().getResource("x.png").toExternalForm());
myImage.setImage(image);
}
if (x == 1) {
Image image = new Image(getClass().getResource("y.png").toExternalForm());
myImage.setImage(image);
}
}
}
}
Upvotes: 0
Views: 3944
Reputation: 21829
A quite robust solution is to use a binding between an IntegerProperty
and the imageProperty
of the ImageView
:
ImageView im = new ImageView();
IntegerProperty intValue = new SimpleIntegerProperty();
List<Image> images = Arrays.asList(new Image(getClass().getResource("aa.png").toString()),
new Image(getClass().getResource("bb.png").toString()));
im.imageProperty().bind(Bindings.createObjectBinding(() -> images.get(intValue.getValue()),
intValue));
The images are put into a List
(or array, or any indexable container), and then the binding returns the Image
on the corresponding index.
To make the images flickering, you can start a new Thread
:
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
Random random = new Random();
while (true) {
Thread.sleep(50);
intValue.set(random.nextInt(images.size()));
}
}
};
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
Upvotes: 2
Reputation: 182
If I understood you correctly, you want to switch images whenever the value of an integer-variable changes. You could put your x in a SimpleIntegerProperty and add a Listener to it.
SimpleIntegerProperty xProperty = new SimpleIntegerProperty();
xProperty.addListener((observable, oldValue, newValue) -> {
if (newValue.intValue() == 0) {
myImage.setImage(image1);
}
if (newValue.intValue() == 1) {
myImage.setImage(image2);
}
});
xProperty.set(random.nextInt());
Each time you call set on xProperty, your listener gets triggered.
As pointed out in a comment to my answer, you shoud not reload the images each time - so I removed that code and just used the variables image1 and image2. You could intiialize them in the constructor.
Upvotes: 2
Reputation: 3239
So I do not believe your problem is in JavaFX presentation logic but rather in the blocking-nature of the source-data your trying to consume. In this sense I suggest you take-up @Tobi in his view code, and add the following class:
import javafx.application.Platform;
import java.util.concurrent.Executors;
class XAdapter {
private static final ExecutorService blockableThread = Executors.newCachedThreadPool();
public void pushChangesTo(IntegerProperty notifier){
blockableThread.submit(() -> {
int newX = random.nextInt(); //insert your long running call here.
Platform.runLater(() -> {
notifier.setValue(newX);
pushChangesTo(notifier)
});
});
}
}
Then you can modify your Document like this:
public class FXMLDocumentController {
//...
IntegerProperty xProperty = new SimpleIntegerProperty();
private final XAdapter adapter = new XAdapter()
@Override public void initialize(){
adapter.pushChangesTo(xProperty)
}
}
note: this is java concurrency, and its very easy to get concurrency wrong. You might consider spending some time with a book like Java Concurrency In Practice to udnerstand why what you were doing was problematic, and what the exact purpose of executors
and Platform.runLater
is. There are a great many better ways to do this, and the solution I wrote here might well not be acceptable to a project lead. In particular, you probably want to mark blockableThread
as being a daemon thread.
notice the last attributed author of the book I linked you to, and the author of the class
Executors
, are the same person.
Upvotes: 0