This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information

Zoom support for applications

Some weeks ago, JavaFX links of the week contained a very interesting link: It was about ZoomFX 1.0.1.

It's a zoomable pane for your JavaFX application.
There's another small project, called MagniFiX. It's a "simple" magnifier but different than ZoomFX.

Why was this so interesting for us?

In the past we had a lot of requests from customers for automatic application scaling for simple touch devices (terminals). Usually we solved the problem with extra source code and specific fonts/control settings - horrible.

We had other requests about image zoom in/out features and charts, ...

So we thought that ZoomFX could be a very useful extension for our JavaFX UI. We tried the demo and configured a simple test application. But first: Maven. Not new: We aren't big fans.
Sure, it wasn't hard to start a test application but we were suprised about the dependencies:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-math3</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-binding</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-geometry</artifactId>
</dependency>

<dependency>
    <groupId>com.github.dejv78.commons.jfx</groupId>
    <artifactId>jfx-input</artifactId>
</dependency>

The overlays were saved as FXML and we thought that it's not a good idea for a library like ours. Anyway, we tried the integration in our lib and stopped suddenly because ZoomFX didn't work with our dynamic layouts. It simply didn't work out-of-the-box and it had too many dependencies for such a "simple" feature.

We had no luck... but we love researching new things. So we started with our own zoom implementation without any dependencies and also integrated in our UI. We made a short screencast of the result.

Application coder

Every application and internal frame has this zoom feature because it was integrated in the UI implementation. We need to do some fine tuning, but it works great!

JVx' JavaFX UI - first release

We're happy to announce our first beta release of JVx' JavaFX UI with version number 0.9 :)

The release is two weeks later than planned but we had some extra tasks to do. We didn't set 1.0 as version number because we have some open tickets which are important, in our opinion, for 1.0. The 0.9 beta is already feature complete with some known bugs.

We also released an extra library: JFXtensions
It contains all standalone controls and extensions which are independent of JVx. The MDI system, our layouts, styled scene and much more.

Here are the download links:

All libraries are available on maven central as well.

We've released DnDTabPane as external lib on maven central, because it wasn't available and our UI needs the dependency. The DnDTabPane is licensed under EPL 1.0 and JVxFX UI, JFXtensions are Apache 2.0 licensed.

The DnDTabPane is still based on Tom Schindls implementation for Efxclipse.

We've a very cool video of our work during the last 4 months. It's the visualizaton of our dev repository:

Respository visualization


The visualization was created with Gource.

Developer Information

The dev2015 branch was merged back to trunk. If you're working with our branch, please switch to trunk.

Meet us

Wir sind wieder auf Achse und wenn du in der Nähe bist bietet sich die Gelegenheit mit uns über JVx, VisionX und Technologie im allgemeinen, zu sprechen.

Die Termine:

Application Coder

This article is about our new Research project: Application Coder.

The application is a very simple Java Code Editor. It shows a tree with Java files and has a Code Editor for modifying files. The code editor is the popular Ace Editor and we use Eclipse JDT for java compilation. The application was written as standard JVx application with vaadin UI.

We made tests as single-page vaadin application, embedded with iframes and embedded with div areas. All versions work without problems but the last one is preferred. If you embedd a vaadin application with divs, it's a little bit tricky because you have to configure the client-side on your own, but you get full access to the whole html page. This wouldn't be possible if you use an iframe because you can't access the main html page.

Some cool features of our editor are: error annotations and error markers. And the best feature is our LIVE Preview of code changes!

Annotations and marker

Annotations and marker


Watch this video:

Application coder


The application coder is not only a Java code editor, it was designed especially for JVx applications, because it groups client code and business logic. The preview also starts a JVx application and LIVE preview reloads the application.

Our coder application has a push mechanism and reloads every preview window automatically and immediate after compilation.

Above video shows multiple instances of our coder application, embedded in divs and it's possible to drag around and resize the applications (thanks to jquery-ui).

The application is a perfect showcase of JVx because it's not a database application as many other JVx applications. We've used vaadin, jquery-ui and vaadin-addons to create a great UX. JVx is technology independent and open for other technologies.

JavaFX Table and Tree lazy loading

JavaFX doesn't define a specific model for table or tree. The implementations are based on ObservableList which is not more than an extension of standard List interface with some additional listeners and sorting, filtering. The general design doesn't take care of one important feature: Lazy loading of records.

This is an important feature if you're working with databases or large datasets. If you have millions of records, it's not a good idea to show all records in your GUI. You shouldn't load more than needed and of course, not more than the user is able to handle.

We have a model in our JVx framework which supports lazy loading of records (not only database records). To use our model with JavaFX, we had to do some Trial and Error because an ObservableList is too lightweight. Sure it wasn't a problem to simulate more entries than the list really had. This was needed to load records on demand. If a "virtual" element was requested it was simply loaded from the datasource. Sounds simple enough. To be honest - it was that simple!

A bigger problem was the scrollbar handling of the controls because it didn't set the scrollhandle position correctly after loading "virtual" records. We didn't find a perfect solution for this problem but our current solution works and is user-friendly enough. We've used our JVx model implementation for TableView and TreeView.
Means: One model for all UI controls.

A simple screencast of our test application is available on YouTube. The video shows a simple TableView which loads records from a remote server via http. The remote server reads data from a HSQLDB. The table contains 317027 records with filenames and additional filesystem information. The remote server returns exactly 100 records, per request, for our test application.

LazyLoading JavaFX TableView


We have the same lazy loading mechanism for TreeView.

Our implementation was done for JVx' model (IDataBook), but the mechanism should work with any other model definition. The complete source code is available in our dev repository. Simply start with ObservableDataBookList.

JavaFX Tree with self-joined table

Trees are always tricky, because it's not easy to fill a tree with data. The problem is not the tree itself, but the preparation of data for the three. It's easy if your data is structured or if you have only few records to prepare. If you have differnet datasources, it could be very tricky to build a tree.

The official tree documentation from Oracle has some examples.

It's boring to create trees because it needs a lot of boilerplate code - per tree. You need more boilerplate code if your trees should be editable.

We solved the "boilerplate code problem" with JVx and the active model implementation. I'll show you a simple example with a self-joined database table. The database table contains all filesystem folders of our Linux test VM.

The table was created with following statement:

CREATE TABLE FOLDERS
(
  ID        INTEGER IDENTITY,
  FOLDER    VARCHAR(256) NOT NULL,
  FOLD_ID   INTEGER,
  constraint FOLD_UK UNIQUE (FOLD_ID, FOLDER),
  constraint FOLD_FOLD_ID_FK FOREIGN KEY (FOLD_ID) REFERENCES FOLDERS (ID) ON DELETE CASCADE
)

Not really tricky. The table contains an unique identifier, the folder name and the identifier of the parent folder. A simple self-joined table.

The UI code for the tree:

IDataBook dataBook = createDataBook();

FXDataBooksTree tree = new FXDataBooksTree();
tree.getDataBooks().addAll(dataBook);

Short and no boilerplate code!
The missing piece is the createDataBook() method, because it defines the access to our database table:

RemoteDataBook rdbData = new RemoteDataBook();
rdbData.setDataSource(getDataSource());
rdbData.setName("folders");
rdbData.setMasterReference(new ReferenceDefinition(new String[] {"FOLD_ID"},
                                                   rdbData,
                                                   new String[] {"ID"}));
rdbData.open();

The code is similar to other examples likeJavaFX, JVx and data binding or Plain JDBC vs. DBStorage.

The tree will look like this one:

Self-joined tree

Self-joined tree

The whole source code is available in our dev branch.

Above test application reads records from a remote database via http, but it could also use a memory databook without database access, like this one:

IDataBook dataBook = new MemDataBook();
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("ID",
                                                new BigDecimalDataType()));
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("PARENT_ID",
                                                new BigDecimalDataType()));
dataBook.getRowDefinition().addColumnDefinition(new ColumnDefinition("NAME",
                                                new StringDataType()));
dataBook.setMasterReference(new ReferenceDefinition(new String[] { "PARENT_ID" },
                                                    dataBook,
                                                    new String[] { "ID" }));
dataBook.setName("MASTER");
dataBook.open();

An example with a MemDataBook is available in our kitchensink application.