Just getting started with TestFX and I'm wondering how to refer to the top Node (i.e. the Stage).
Here I see it says
All TestFX tests should use verifyThat(Node, Matcher, Function) when
writing tests, so that the developer can use DebugUtils to provide
additional info as to why a test failed.
This is a useful pointer... so say I want to say verify that "the JavaFX dialog/window is at least 600 pixels wide and at most 400 pixels high"?
NB for what it's worth I'm using the org.junit approach because the examples on the TestFX github site seem to. Actually I'm a Groovy fan and would hope to switch to the Spock TestFX implementation before too long.
NB2 it occurs to me that one way to get the Stage in testing code is to make the Stage a field of the class under test:
class ClickApplication extends Application {
Stage allTheWorldsA
public void start(Stage stage) {
Parent sceneRoot = new ClickPaneGG()
Scene scene = new Scene(sceneRoot, 500, 1000)
stage.setScene(scene)
stage.show()
allTheWorldsA = stage
}
... but somehow this feels the wrong way to do things: if the Stage is passed as a parameter of start it feels like the designers didn't want you to make a class field of it.
Related
I currently have a few integration tests that are running fine, however I'm using the annotation #QuarkusTestResource to launch containers via testcontainers before quarkus is launched and I adapt my properties to the random test container port by overriding the start method of my container class extending QuarkusTestResourceLifecycleManager.
To optimize a little bit I'd like for example to reuse my container that launches kafka since it takes 6-8 seconds to start it and reuse it for several of my integration tests. I've not been able to do so. Since Quarkus manages the lifecycle every times it stops, between every test class, it also stops every container. I tried mixing singleton containers from testcontainers with the Quarkus test resources but it doesn't work. Here's a snippet of the start of one of my integration test class :
#QuarkusTest
#Tag(INTEGRATION_TEST)
#QuarkusTestResource(value = KafkaNode.class, restrictToAnnotatedClass = true, parallel = true)
class MyIntegrationTest { ... }
And my KafkaNode class :
public class KafkaNode implements QuarkusTestResourceLifecycleManager {
static KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.1"))
.withNetworkAliases("kafkaNode")
.withNetwork(CommonNetwork.getInstance());
#Override
public Map<String, String> start() {
kafka.start();
return Collections.singletonMap("myapp.kafka.servers",
kafka.getBootstrapServers());
}
#Override
public void stop() {
kafka.close();
}
}
I'm open to ideas to reuse of even rework my tests so that I can reuse containers in another way.
You can use the experimental reusable mode for your container via .withReuse(true).
Please note that in order for this to work you need to:
set the testcontainers.reuse.enable=true property in the ~/.testcontainers.properties file
NOT call .close() (which programmatically stops the container in any way)
Once you've setup everything accordingly your container should
not be stopped/garbage collected at the end of the test run anymore
be picked up again at the next test run - avoiding a new container start
Please note that all runtime modifications (configuration, data, topics etc.) will still be there at the next test run. You need to take suitable measures to avoid non-deterministic tests - like using different / random topic names for each test run.
Also note that you'll need to manually stop/delete the container when you're done with it. Testcontainers will not remove the container for you anymore.
You can also read this article that describes how to do it from spring for inspiration: Reuse Containers With Testcontainers for Fast Integration Test
When using multiple QuarkusTestProfile's, the test context will be reseted completely, so that even static variables are not preserved.
I have not yet found a way to use e.g. a single database across all QuarkusTest's in one test when using different QuarkusTestProfiles.
Even if it seems that the container exists across test run boundaries, I can't reference it in later test runs to determine the mapped port, etc.
I am completely new to Java and I am learning it while developing an app for a school project.
Image Link
I want to code the above program. In it ,
The user will click Ready button in screen 1.
Then screen two will appear and an image of a butterfly will be shown in a order given by me[Preset using a CSV file] Like shown in screen 2 and 3.
Finally, a button set will appear in the grid and user has to select the buttons in the order of the butterfly appearance.
I am stuck in finding a way to start screen 2 and automatically play the butterfly sequence.
I tried putting the image.setimage() on the initialize() block in my screen 2 controller with a delay in-between each setimage() . but it dosent work.
Anyone can suggest me a way to handle this kind of task? Thank a lot in advance.
The issues often seen with this kind of code for beginners are doing sleep or some other long-running operation on the application thread to do some animation. However blocking the javafx application thread results in the scene not being updated resulting in a freeze of the gui.
You either need to move the long-running parts of this animation to a background thread and use Platform.runLater for any GUI updates or use something designed for this exact purpose. There are multiple classes that could be useful in the javafx.animation package, but the most convenient of them seems to be Timeline:
Store the sequence of movements in a suitable data structure and use the Timeline to trigger an event handler in regular intervals to update the gui:
List<FieldIndices> fieldIndices = ...
final Iterator<FieldIndices> iterator = fieldIndices.iterator();
final Timeline timeline = new Timeline();
timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(1), evt -> {
if (iterator.hasNext()) {
moveButterfly(iterator.next());
} else {
removeButterfly();
timeline.stop();
}
}));
timeline.setCycleCount(Animation.INDEFINITE); // repeat until stop is called
timeline.play();
Now all that's left for you to implement is reading the data to a list and implementing the logic of moving the butterfly to a new position.
Note that I do not actually recommend using more than 2 scenes: The user will expect the same position for the buttons and the "fields" showing the butterfly. If you design 2 fxmls any adjustment to one of the scene would require you to do the same adjustments to the other scene. This makes the layout hard to maintain. The alternative requires you to create the scene in java code, but the repetitive nature of the scenes makes this a good idea anyways. (The alternative is injecting 16 fields to the controller and collecting them into a suitable data structure; This is error prone and any change of one of the buttons would probably require 16 changes in the fxml. Use a nested for loop and you need to write the logic for creating a button only once storing the buttons in e.g. a nested array can be done at the same time...)
As I understand, you wanna play butterfly sequence once 2nd stage is shown...To achieve that, you could try something like:
List positions = new ArrayList(); //places to show butterfly (e.g. table cells)
secondStage.setOnShown(windowEvent -> {
// update UI with Pltform.runLater()
// moveButerflyTo() is your method to place butterfly on given place
positions.forEach(position -> Platform.runLater(() -> moveButerflyTo(position)));
});
I didn't try this but it do the job...
Is there a way to clone a scene in JavaFX ?
I currently want to keep a reference of the previous scene but can't find a simple way of doing it (except passing in the previous scene as a parameter to every new class responsible for scene creation).
Heres what I was thinking of doing (this is a snipped of my view controller)
public void switchScene(Scene newScene){
previousScene = currentScene; // something which achieves this without aliasing
currentScene = newScene;
window.setScene(newScene);
}.
However as one can observe this leads to aliasing problems.
Any way to solve this problem ?
Im trying to build a Chat Program. i can do it when i use java awt package but with java fx i seem to be a bit confused. when you first build a java fx project all your methods even the public static void main(string args[]) is in there and there's a place where you Start the primaryStage of the coding...I have no problem coding the visual side of my program its just i dont know where i should setup the Network part of my program and where to put it when im done..
**CODE: This is Just a View**
Server extends Application{
public void start(Stage primaryStage){
//Where you setup the visual of your program
}
public static void main(String args[]){
launch(args); // Where the program will run
}
public void ServerConnection(){
//where i put the codes to setup my streams and SOCKET
}
The ServerConnection method contains other methods as well But all of those will go to the ServerConnectionMethod now My question is Where will i place my ServerConnection Method so that it will run along with the my primary Stage
Sorry for the long post..have a String ="potato";
If a JavaFX application is launched correctly, it won't use the main() method at all - you can remove it temporarily (as an experiment) and check, but chances are it's not serving any purpose other than for backwards compatibility. You certainly should not rely on the main method doing anything special in the case of an FX app; it should only call launch() and nothing else.
Instead, your main class should extend Application, and the JavaFX runtime will create an instance of it for you, create a primary stage, and call the start method providing you with a reference to that stage. From this method you can do anything you like, but bear in mind it is on the UI thread (so you should create an additional thread for any long running task, the same as you would in any other toolkit such as Swing.)
You could run this setupConnection method at the beginning of the start(Stage primaryStage) method. This way it will be executed before showing the stage. You could also just run both from the main method, but as berry120 said: You don't need to call the launch(args) method in the main, if it extends Application you're fine with just the start method.
When you are done, you could use a
stage.setOnCloseRequest(e -> {
//code to execute, something like socket.close();
});
And you could change the stage.show() to stage.showAndWait()
I've been coding a simulation in Java and now generate graphs of the results in JavaFX. However, I'm stumped as to how to call the graphs so that when I try to run the simulation (and generate the graphs) for a second time, I don't get the "can't call launch() more than once" error. I read that launch() can only be called once, so what do I need to change to call the graphs successfully on a second run of the simulation?
public class AnswerWorker extends SwingWorker<Void, Integer> {
protected Void doInBackground() throws Exception
{
AMEC.runsimulation();
return null;
}
protected void done()
{
try {
Graphs.launch(Graphs.class, "");
JOptionPane.showMessageDialog(InputGUI.this, AMEC.unsuccesfulpercentage + "% of iterations had trucks that had to sleep over");
AMEC.unsuccesfulpercentage = 0;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
with a pretty standard graphing class:
public class Graphs extends Application {
#Override public void start(Stage stage) {
....
stage.show();
}
}
Why are you using SwingWorker in a JavaFX application? If your graphs are computed for display in a JavaFX application, there is no reason for you to use the Event Dispatch Thread (AWT). If I'm not mistaken, With the release of JDK 8, the JavaFX Application Thread and the Event Dispatch Thread will become one, so there is no reason (yet) for you to use SwingWorker. If I really am wrong, still, there is no reason for you to use SwingWorker. Although it is possible the coupling of Swing components in JavaFX applications, you should only use EDT when manipulating Swing components, not JavaFX nodes. The following link says this:
...The JavaFX application thread is a different thread from the Swing and AWT Event Dispatch Thread (EDT), so care must be taken when embedding JavaFX code into Swing applications...
Source: http://docs.oracle.com/javafx/2/architecture/jfxpub-architecture.htm
To learn how you can put processes to be done in the background, and also find out which thread is responsible for handling the JavaFX elements, check out this link:
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Regarding your question, I believe the beginning of a JavaFX application should be called only once. So much is, that when a JavaFX application is started, the thread of main method is captured, and is only returned when the JavaFX application is finalized. Just see the Application DOC (Especially this part). Note also that the life cycle of a JavaFX application is given by the following steps:
Life-cycle
The entry point for JavaFX applications is the Application class. The JavaFX runtime does the following, in order, whenever an application is launched:
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of
the following occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
You might be using the wrong approach. I believe that you should leave your JavaFX application running while you're processing something. Once you have processed what you want in the background, you should make your JavaFX application show the results. The way your JavaFX application run while something is being processed in the background is entirely up to you. Maybe you should hide the window while something is processed, and display it again with your chart done. As I said, this is something you will have to decide. I recommend you to take a look at the documentation of classes referring to the window system, starting with Window, and then Stage.
Any questions, we're here. Good Luck! :)
EDIT:
From what I'm seeing, the user jewelsea is right. Apparently it is not certain that the EDT and the JavaFX Application Thread shall become one (it would be quite interesting if that happened). But anyway, be careful not to confuse yourself with the use of both threads.