Usage of Toolkit firePulse
Ryan Jaeb
ryan at jaeb.ca
Tue Sep 29 00:58:18 UTC 2015
Hi Benjamin,
Yes, it's a NoNodesFoundException using TestFX 3.1.2.
As far as I know, using firePulse() is the only way to guarantee all
previous model changes are rendered in the scene. I've created an example
to show what I mean:
https://gist.github.com/ryanjaeb/74685a002e2b402e7fac
It's a small example, so I'll post it inline too:
...
public class FirePulseApplication extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
printEnv();
ListView<String> listView = new ListView<>();
Scene scene = new Scene(listView, 200, 400);
primaryStage.setScene(scene);
primaryStage.show();
for (int i = 1; i < 6; i++) {
listView.getItems().add("list-item-" + i);
}
System.out.println("Before firePulse():");
printVisibleRowInfo(listView);
Toolkit.getToolkit().firePulse();
System.out.println("After firePulse():");
printVisibleRowInfo(listView);
Platform.exit();
}
private void printVisibleRowInfo(ListView<?> listView) {
// Item count according to the list model
System.out.println(" Item count: " + listView.getItems().size());
// Extract the VirtualFlow so it can be used to determine which
// list items are rendered in the scene.
ObservableList<Node> children = listView.getChildrenUnmodifiable();
VirtualFlow<?> flow = (VirtualFlow<?>) children.get(0);
IndexedCell<?> firstCell = flow.getFirstVisibleCell();
System.out.println(" First visible cell: " + firstCell);
IndexedCell<?> lastCell = flow.getLastVisibleCell();
System.out.println(" Last visible cell: " + lastCell);
}
private void printEnv() {
String osName = System.getProperty("os.name");
String jvm = System.getProperty("java.version") +
" (" + System.getProperty("java.vm.version") +
" - " + System.getProperty("os.arch") + ")";
System.out.println("OS: " + osName);
System.out.println("JVM: " + jvm);
System.out.println("");
}
}
...
The output I get when running the example:
...
OS: Windows 8.1
JVM: 1.8.0_40 (25.40-b25 - amd64)
Before firePulse():
Item count: 5
First visible cell: null
Last visible cell: null
After firePulse():
Item count: 5
First visible cell: ListViewSkin$2 at 7820053f[styleClass=cell indexed-cell
list-cell]'list-item-1'
Last visible cell: ListViewSkin$2 at 8be9262[styleClass=cell indexed-cell
list-cell]'list-item-5'
...
Until there's a pulse, the nodes that represent the list items don't exist,
so the NoNodesFoundException is expected.
Ryan
On Sun, Sep 27, 2015 at 12:40 AM, Benjamin Gudehus <hastebrot at gmail.com>
wrote:
> Hi Ryan!
>
> >Otherwise the drag(...) command will throw an exception because it
> can't find the node for "list-item-name" (it doesn't exist yet).
>
> Well, this is very interesting. This must be a NoNodesFoundException in
> TestFX 3.
>
> >I don't actually needto call firePulse(). I just need a way to know the
> scene is up to date with a re-validated model. Is there a better way of
> accomplishing that right now?
>
> TestFX should try to find the Node within the JavaFX Application Thread
> using Platform.runLater(...). Maybe this is a better way than to call
> firePulse(),
>
> --Benjamin
>
> On Thu, Sep 24, 2015 at 12:49 PM, Ryan Jaeb <ryan at jaeb.ca> wrote:
>
>> I use firePulse() in GUI test code. I'm using TestFX (v3) for testing.
>> Is
>> there a way to ensure model updates are reflected in the scene without
>> using firePulse()? Consider something like this:
>>
>> ...
>> // TestFX starts us on the main thread. Maybe I'm using it wrong?
>>
>> CountDownLatch latch = new CountDownLatch(1);
>>
>> Platform.runLater(() -> {
>> // Add "list-item-name" to an empty list that's used as the model for
>> // a ListView.
>> Toolkit.getToolkit().firePulse();
>> latch.countDown();
>> });
>>
>> try {
>> latch.await(1, TimeUnit.SECONDS);
>> }
>> catch (InterruptedException e) {
>> throw new RuntimeException(e);
>> }
>>
>> // TestFX runs this on the application thread.
>> drag("list-item-name").to("trash");
>>
>> assertTrue(list.isEmpty);
>> ...
>>
>> In a case like the above, firePulse() is used to ensure a node (ListCell)
>> for "list-item-name" is added to the scene before continuing with the
>> test. Otherwise the drag(...) command will throw an exception because it
>> can't find the node for "list-item-name" (it doesn't exist yet).
>>
>> I don't actually needto call firePulse(). I just need a way to know the
>> scene is up to date with a re-validated model. Is there a better way of
>> accomplishing that right now?
>>
>> Ryan
>>
>>
>> On Wed, Sep 23, 2015 at 5:49 PM, Jonathan Giles <
>> jonathan.giles at oracle.com>
>> wrote:
>>
>> > Hi all,
>> >
>> > Today I am keen to get your help on understanding use of the
>> > Toolkit.getToolkit().firePulse() private API. If you could spare a few
>> > minutes to grep your source directory for any usage of 'firePulse', and
>> > email me your findings, that would be really interesting.
>> >
>> > As a gentle motivational tool I'll conclude by saying that,
>> surprisingly,
>> > this private API is barely used inside the openjfx production code. If
>> you
>> > look at the openjfx unit tests, it is used massively. The question is -
>> how
>> > much is this being used by other community members. If the answer is
>> 'not
>> > much' or less, then this private API may not be made public in JDK 9.
>> Your
>> > feedback therefore is critical!
>> >
>> > Thanks,
>> > -- Jonathan
>> >
>>
>
>
More information about the openjfx-dev
mailing list