Wednesday Nov 07, 2012

MonologFX: FLOSS JavaFX Dialogs for the Taking

(UPDATED Nov 10 with simpler button icon API) 

Some time back, I was searching for basic dialog functionality within JavaFX and came up empty. After finding a decent open-source offering on GitHub that almost fit the bill, I began using it...and immediately began thinking of ways to "do it differently."  :-)  Having a weekend to kill, I ended up creating DialogFX and releasing it on GitHub (hecklerm/DialogFX) for anyone who might find it useful. Shortly thereafter, it was incorporated into JFXtras (jfxtras.org) as well.

Today I'm sharing a different, more flexible and capable JavaFX dialog called MonologFX that I've been developing and refining over the past few months. The summary of its progression thus far is pretty well captured in the README.md file I posted with the project on GitHub:

After creating the DialogFX library for JavaFX, I received several suggestions and requests for additional or different functionality, some of which ran counter to the interfaces and/or intent of the DialogFX "way of doing things". Great ideas, but not completely compatible with the existing functionality. Wanting to incorporate these capabilities, I started over...incorporating some parts of DialogFX into the new MonologFX, as I called it, but taking it in a different direction when it seemed sensible to do so.

In the meantime, the OpenJFX team has released dialog code that will be refined and eventually incorporated into JavaFX and OpenJFX. Rather than just scrap the MonologFX code or hoard it, I'm releasing it here on GitHub with the hope that someone may find it useful, interesting, or entertaining. You may never need it, but regardless, MonologFX is there for the taking.

Things of Note

So, what are some features of MonologFX?

  • Four kinds of dialog boxes: ACCEPT (check mark icon), ERROR (red 'x'), INFO (blue "i"), and QUESTION (blue question mark)
  • Button alignment configurable by developer: LEFT, RIGHT, or CENTER
  • Skins/stylesheets support
  • Shortcut key/mnemonics support (Alt-<key>)
  • Ability to designate default (RETURN-key) and cancel (ESCAPE-key) buttons
  • Built-in button types and labels for OK, CANCEL, ABORT, RETRY, IGNORE, YES, and NO
  • Custom button types: CUSTOM1, CUSTOM2, CUSTOM3
  • Internationalization (i18n) built in. Currently, files are provided for English/US and Spanish/Spain locales; please share others and I'll add them!
  • Icon support for your buttons, with or without text labels
  • Fully Free/Libre Open Source Software (FLOSS), with latest source code & .jar always available at GitHub

Quick Usage Overview

Having an intense distaste for rough edges and gears flying when things break (!), I've tried to provide defaults for everything and "fail-safes" to avoid messy outcomes if some property isn't specified, etc. This also feeds the goal of making MonologFX as easy to use as possible, while retaining the library's full flexibility. Or at least that's the plan.  :-)

You can hand-assemble your buttons and dialogs, but I've also included Builder classes to help move that along as well. Here are a couple examples:

        MonologFXButton mlb = MonologFXButtonBuilder.create()
                .defaultButton(true)
                .icon("/testmonologfx/dialog_apply.png")
                .type(MonologFXButton.Type.OK)
                .build();

        MonologFXButton mlb2 = MonologFXButtonBuilder.create()
                .cancelButton(true)
                .icon("/testmonologfx/dialog_cancel.png")
                .type(MonologFXButton.Type.CANCEL)
                .build();

        MonologFX mono = MonologFXBuilder.create()
                .modal(true)
                .message("Welcome to MonologFX! Please feel free to try it out and share your thoughts.")
                .titleText("Important Announcement")
                .button(mlb)
                .button(mlb2)
                .buttonAlignment(MonologFX.ButtonAlignment.CENTER)
                .build();

        MonologFXButton.Type retval = mono.showDialog();


MonologFXButton mlb = MonologFXButtonBuilder.create()
        .defaultButton(true)
        .icon("/testmonologfx/dialog_apply.png")
        .type(MonologFXButton.Type.YES)
        .build();

 

MonologFXButton mlb2 = MonologFXButtonBuilder.create()
        .cancelButton(true)
        .icon("/testmonologfx/dialog_cancel.png")
        .type(MonologFXButton.Type.NO)
        .build();

 

MonologFX mono = MonologFXBuilder.create()
        .modal(true)
        .type(MonologFX.Type.QUESTION)
        .message("Welcome to MonologFX! Does this look like it might be useful?")
        .titleText("Important Announcement")
        .button(mlb)
        .button(mlb2)
        .buttonAlignment(MonologFX.ButtonAlignment.RIGHT)
        .build();

 

MonologFXButton.Type retval = mono.showDialog();

 


Extra Credit

Thanks to everyone who offered ideas for improvement and/or extension to the functionality contained within DialogFX. The JFXtras team welcomed it into the fold, and while I doubt there will be a need to include MonologFX in JFXtras, team members Gerrit Grunwald & Jose Pereda Llamas volunteered templates and i18n expertise to make MonologFX what it is. Thanks for the push, guys!

Where to Get (Git!) It

If you'd like to check it out, point your browser to the MonologFX repository on GitHub. Full source code is there, along with the current .jar file. Please give it a try and share your thoughts! I'd love to hear from you.

All the best,
Mark

Tuesday Oct 09, 2012

Seven Random Thoughts on JavaOne

As most people reading this blog may know, last week was JavaOne. There are a lot of summary/recap articles popping up now, and while I didn't want to just "add to the pile", I did want to share a few observations. Disclaimer: I am an Oracle employee, but most of these observations are either externally verifiable or based upon a collection of opinions from Oracle and non-Oracle attendees alike. Anyway, here are a few take-aways:

  1. The Java ecosystem is alive and well, with a breadth and depth that is impossible to adequately describe in a short post...or a long post, for that matter. If there is any one area within the Java language or JVM that you would like to - or need to - know more about, it's well-represented at J1.
  2. While there are several IDEs that are used to great effect by the developer community, NetBeans is on a roll. I lost count how many sessions mentioned or used NetBeans, but it was by far the dominant IDE in use at J1. As a recent re-convert to NetBeans, I wasn't surprised others liked it so well, only how many.
  3. OpenJDK, OpenJFX, etc. Many developers were understandably concerned with the change of sponsorship/leadership when Java creator and longtime steward Sun Microsystems was acquired by Oracle. The read I got from attendees regarding Oracle's stewardship was almost universally positive, and the push for "openness" is deep and wide within the current Java environs. Few would probably have imagined it to be this good, this soon. Someone observed that "Larry (Ellison) is competitive, and he wants to be the best...so if he wants to have a community, it will be the best community on the planet." Like any company, Oracle is bound to make missteps, but leadership seems to be striking an excellent balance between embracing open efforts and innovating in competitive paid offerings.
  4. JavaFX (2.x) isn't perfect or comprehensive, but a great many people (myself included) see great potential, are developing for it, and are really excited about where it is and where it may be headed. This is another part of the Java ecosystem that has impressive depth for being so new (JavaFX 1.x aside). If you haven't kicked the tires yet, give it a try! You'll be surprised at how capable and versatile it is, and you'll probably catch yourself smiling while coding again.  :-)
  5. JavaEE is everywhere. Not exactly a newsflash, but there is a lot of buzz around EE still/again/anew. Sessions ranged from updated component specs/technologies to Websockets/HTML5, from frameworks to profiles and application servers. Programming "server-side" Java isn't confined to the server (as you no doubt realize), and if you still consider JavaEE a cumbersome beast, you clearly haven't been using the last couple of versions. Download GlassFish or the WebLogic Zip distro (or another JavaEE 6 implementation) and treat yourself.
  6. JavaOne is not inexpensive, but to paraphrase an old saying, "If you think that's expensive, you should try ignorance." :-) I suppose it's possible to attend J1 and learn nothing, but you'd have to really work at it! Attending even a single session is bound to expand your horizons and make you approach your code, your problem domain, differently...even if it's a session about something you already know quite well. The various presenters offer vastly different perspectives and challenge you to re-think your own approach(es).
  7. And finally, if you think the scheduled sessions are great - and make no mistake, most are clearly outstanding - wait until you see what you pick up from what I like to call the "hallway sessions". Between the presentations, people freely mingle in the hallways, go to lunch and dinner together, and talk. And talk. And talk. Ideas flow freely, sparking other ideas and the "crowdsourcing" of knowledge in a way that is hard to imagine outside of a conference of this magnitude. Consider this the "GO" part of a "BOGO" (Buy One, Get One) offer: you buy the ticket to the "structured" part of JavaOne and get the hallway sessions at no additional charge. They're really that good.

If you weren't able to make it to JavaOne this year, you can still watch/listen to the sessions online by visiting the JavaOne course catalog and clicking the media link(s) in the right column - another demonstration of Oracle's commitment to the Java community. But make plans to be there next year to get the full benefit! You'll be glad you did.

 

All the best,
Mark

P.S. - I didn't mention several other exciting developments in areas like the embedded space and the "internet of things" (M2M), robotics, optimization, and the cloud (among others), but I think you get the idea. JavaOne == brainExpansion;  Hope to see you there next year!

Monday Sep 03, 2012

DialogFX: A New Approach to JavaFX Dialogs

How would you like a quick and easy drop-in dialog box capability for JavaFX? That's what I was thinking when a weekend presented itself. And never being one to waste a good weekend...  :-)

After doing some "roll-your-own" basic dialog building for a JavaFX app, I recently stumbled across Anton Smirnov's work on GitHub. It was a good start, but it wasn't exactly what I was after, and ideas just kept popping up of things I'd do differently. I wanted something a bit more streamlined, a bit easier to just "drop in and use". And so DialogFX was born.

DialogFX wasn't intended to be overly fancy, overly clever - just useful and robust. Here were my goals:

  • Easy to use. A dialog "system" should be so simple to use a new developer can drop it in quickly with nearly no learning curve. A seasoned developer shouldn't even have to think, just tap in a few lines and go. Why should dialogs slow "actual development"?  :-)
  • Defaults. If you don't specify something (dialog type, buttons, etc.), a good dialog system should still work. It may not be pretty, but it shouldn't throw gears.
  • Sharable. It's all open source. Even the icons are in the commons, so they can be reused at will.

Let's take a look at some screen captures and the code used to produce them.

 

DialogFX INFO dialog

Screen captures

Windows


Mac 

Sample code

        DialogFX dialog = new DialogFX();
        dialog.setTitleText("Info Dialog Box Example");
        dialog.setMessage("This is an example of an INFO dialog box, created using DialogFX.");
        dialog.showDialog();

DialogFX ERROR dialog

Screen captures

Windows


Mac 

Sample code

        DialogFX dialog = new DialogFX(Type.ERROR);
        dialog.setTitleText("Error Dialog Box Example");
        dialog.setMessage("This is an example of an ERROR dialog box, created using DialogFX.");
        dialog.showDialog();

DialogFX ACCEPT dialog

Screen captures

Windows


Mac 

Sample code

        DialogFX dialog = new DialogFX(Type.ACCEPT);
        dialog.setTitleText("Accept Dialog Box Example");
        dialog.setMessage("This is an example of an ACCEPT dialog box, created using DialogFX.");
        dialog.showDialog();

DialogFX Question dialog (Yes/No)

Screen captures

Windows


Mac 

Sample code

        DialogFX dialog = new DialogFX(Type.QUESTION);
        dialog.setTitleText("Question Dialog Box Example");
        dialog.setMessage("This is an example of an QUESTION dialog box, created using DialogFX. Would you like to continue?");
        dialog.showDialog();

DialogFX Question dialog (custom buttons)

Screen captures

Windows


Mac 

Sample code

        List<String> buttonLabels = new ArrayList<>(2);
        buttonLabels.add("Affirmative");
        buttonLabels.add("Negative");

        DialogFX dialog = new DialogFX(Type.QUESTION);
        dialog.setTitleText("Question Dialog Box Example");
        dialog.setMessage("This is an example of an QUESTION dialog box, created using DialogFX. This also demonstrates the automatic wrapping of text in DialogFX. Would you like to continue?");
        dialog.addButtons(buttonLabels, 0, 1);
        dialog.showDialog();

A couple of things to note

You may have noticed in that last example the addButtons(buttonLabels, 0, 1) call. You can pass custom button labels in and designate the index of the default button (responding to the ENTER key) and the cancel button (for ESCAPE). Optional parameters, of course, but nice when you may want them.

Also, the showDialog() method actually returns the index of the button pressed. Rather than create EventHandlers in the dialog that really have little to do with the dialog itself, you can respond to the user's choice within the calling object. Or not. Again, it's your choice.  :-)

And finally, I've Javadoc'ed the code in the main places. Hopefully, this will make it easy to get up and running quickly and with a minimum of fuss.

How Do I Get (Git?) It?

To try out DialogFX, just point your browser here to the DialogFX GitHub repository and download away! Please take a look, try it out, and let me know what you think. All feedback welcome!

All the best,

Mark 

Wednesday Aug 29, 2012

JavaFX Dialogs, Anyone?

A common question about JavaFX, especially for those coming from a Swing background, is "How do I do Dialogs?"

The reason this is a question at all is that, currently, there is no baked-in capability to do dialog boxes within a pure JavaFX 2.x application. But come on...you wouldn't be reading about this at all if you weren't a resourceful programmer. You have ways of making things happen.  :-)

I ran across a decent patch of code recently that handles many of the dialog chores for you. Pros and cons follow, but pointing your browser to this link on Github (appropriately named JavaFXDialog) will get you off to a good start.

Here are some screen shots the original code author, Anton Smirnov, provided:


Nothing fancy, just clean and functional. Now, about those pros and cons. From my perspective, here's the bottom line:

Pros

  • Already developed. Time required to implement is limited to downloading and decompressing the file, doing a bit of reading, and writing a few lines of code to try things out.
  • Easy. Most of the work is done, and the interface is pretty simple.
  • Open source. If you want to make changes - and I'm already thinking along those lines, so you may as well admit you will, too - you can do it.

Cons

  • Documentation. What you see on the Wiki page is the extent of it.
  • Lack of activity. As of the date this article was published, the code hasn't been updated in several months...so the project is a bit stale.
To be fair, the cons listed above won't cause anyone to lose sleep. After all, you don't expect constant revisions against something that works well enough for most purposes, and if your needs exceed what is there, it's easy to mod the code yourself or "roll your own" if you prefer. The lack of documentation isn't a show-stopper either due to the limited functionality and complexity of the code.

Wrapping It Up

If you need a quick, drop-in dialog capability for your JavaFX 2.x app, give it a try and see what you think. And if you're already using something you like, please share it as well! I'd love to hear from you, take a look at what you pass along, and maybe do a "dialog shoot-out" article in the future. So..what works for you?  :-)


All the best,
Mark

Wednesday Jul 25, 2012

How to Get Started (FAST!) With JavaFX 2 and Scene Builder

A question I hear all too often is "How do I get started with JavaFX and/or Scene Builder?" Like most tools/toolsets, there are as many ways to use these implements as there are developers...but shouldn't there be an easy way to "hit the ground running"? While casting about for an end-to-end example, demo, or video, I found a wealth of useful information, but I couldn't find anything that took someone from start to finish, quickly and easily. JavaFX is easy and fun. But don't take my word for it; let's give it a try!

Before we begin, you'll need to visit this page to download and install all the necessary goodies. Click the download link to go to the current downloads page, then download and install JavaFX (NOTE: if you already have a JDK installed that includes JavaFX, you can omit this step), then download and install the JavaFX Scene Builder. Specific instructions for those steps are located on that page. Go ahead, I'll wait right here.  :-)

Back now? Great! Let's get started!

First, let's fire up Scene Builder just to make sure it works. If not, you'll want to revisit the installation instructions on the downloads page. Once that's working, we're ready to roll...assuming you're running NetBeans 7.2 or higher, of course. You are running NetBeans, right? If not, you owe it to yourself to download it - it's free, and as you're about to see, it's pretty amazing. NetBeans and Scene Builder are loosely-but-effectively integrated, and using both greatly simplifies things and makes your life easier.

Okay, here's the fun part: we're going to actually create a simple JavaFX application, create/modify a window using Scene Builder, and successfully test it in under 15 minutes. Don't believe me? Buckle up friend, here we go!

NetBeans

We start this fun frenzy with NetBeans. Choose File, New Project, JavaFX, then JavaFX FXML Application. This creates a very simple JavaFX app that includes a main application class, a controller class to provide the actual backing logic for the window defined in Scene Builder, and the FXML file containing our window definition (XML) code. I used the name "EasyJavaFX" for our project.


Here's a quick summary of these three files:

EasyJavaFX.java contains the main application class. We won't really do anything with this class for this example, as its primary purpose in life is to load the window definition code contained in the FXML file and then show the main stage/scene. You'll keep the JavaFX terms straight with ease if you relate them to the theater: a platform holds a stage, which contains scenes. Simple. :-)

SampleController.java is our controller class that provides the "brains" behind the graphical interface. If you open the SampleController, you'll see that it includes a property and a method tagged with @FXML. This tag enables the integration of the visual controls and elements you define using Scene Builder. Let's take a look at that next.

Sample.fxml is the definition file for your sample window. You can right-click and Edit the filename in the tree to view the underlying XML - and you may need to do that if you change filenames or properties by hand - or you can double-click on it to open it in Scene Builder. Let's do that next, but first a quick look at our little project:


Scene Builder

Opening Sample.fxml in Scene Builder results in the display of a very spartan window.

Let's rework it a little. For a complete tour of Scene Builder, please visit this page, but here's the nickel tour: stuff and navigation to the left, picture in the middle, and properties on the right. :-) We'll make some small modifications like so:

First, we click on the Button in the Hierarchy panel (bottom left), which selects it in the middle Content panel. We'll move it down and over a bit to make room for another button.


Next, let's drag another button from the Library panel and drop it onto the canvas, lining it up with the other button using the red positioning lines that appear while dragging it.

Once the button is positioned, we turn our attention to the Properties panel. We'll assign our new button an fx:id of exitButton, change the text to Exit, and tab out of the field to see our changes dynamically applied. Next, we click on the other button to change its fx:id and text to clickmeButton and "Click Me for an Important Announcement", respectively. Finally, we click the Exit button and resize it to be a bit wider. Who likes to hunt for tiny Exit buttons?

We're nearly done with our first round with Scene Builder. To finish, we select the Label in the Hierarchy panel at the bottom left - that's often the quickest way to locate "hidden" visual controls - and then resize it using the sizing handles on the canvas, again using the red lines to line up with edges and buttons. Once we're done, things should look something like this:



Click File, Save to save our changes, and Scene Builder confirms with a brief message at the top of the Content panel. Leaving Scene Builder open for convenience, return to NetBeans for the next step.

Back to NetBeans

Let's make a few changes to the controller class. Opening SampleController.java, let's start with the only method we (currently) have. Since we now have two buttons, we will need to keep two methods straight. Renaming handleButtonAction to something like handleClickmeButtonAction is a good start. And to add something of significance to read when the button is clicked, we'll replace the wonderfully traditional "Hello World!" with "Space... the Final Frontier. These are the voyages of the starship Enterprise. Its continuing mission: to explore strange new worlds, to seek out new life and new civilizations, to boldly go where no one has gone before." For those reading this who aren't Star Trek fans, please feel free to substitute your own, slightly less-interesting text.  :-)

Next, we'll create a method for our Exit button by either copying the other method and renaming it or hand-jamming it. Either way, be sure you have the @FXML tag to allow for integration with our window definition/Scene Builder. Putting the following line in our new handleExitButtonAction method will give us a quick escape hatch for our demo app:

Platform.exit();

To fix the error shown by NetBeans, click on the light bulb to the left of the code line and allow it to import javafx.application.Platform. After a quick click on the Save All button, we're good to go from the NetBeans side. Now to go back to Scene Builder to wrap things up.

And Back to Scene Builder

In order for our buttons to tie to our new methods, we need to connect them to the names we gave those methods in our SampleController class. First, we'll select the top Button (clickmeButton) in the Hierarchy panel. Next we turn our attention to the Properties panel on the right. At the bottom of the right side is a collapsed section labeled "Code: Button". Clicking that line opens the Code properties window so we can update the OnAction property. Notice it still points to the method formerly known as handleButtonAction. Click the dropdown, select handleClickmeButtonAction, tab out of the field, and we're done with that button.

We repeat some of the same steps with the other (Exit) button, although since we already have the Code properties panel open, selecting the button takes us directly there. Choosing handleExitButtonAction from its OnAction dropdown and tabbing out of the field concludes our work with Exit. But there is one more thing, purely cosmetic though it may be...

Since we added quite a lot of text to our label (see the handleClickmeButton method in the SampleController class), we may want to change the default behavior of our display label. Labels default to using an ellipsis when the length of text to display exceeds the space available, but we want to see the text in its entirety! Clicking the "Wrap" checkbox in the label's Properties panel fixes that up nicely and concludes our work in Scene Builder. Click File, Save, and then back to NetBeans for our maiden voyage!


And Now Back to NetBeans for the Big Finale!

Right-clicking the project in the Projects window to the left and clicking Run provides these satisfying results:



Clicking the "Click Me" button displays the following:



And clicking the Exit button closes the application.

Start to finish, you just developed a JavaFX application using Scene Builder in less time than it takes to drink a cup of coffee...while learning your way around in the process. Fast, fun, and productive: THAT is JavaFX.

All the best,
Mark

P.S. - There isn't much to the code, but I'll post it to GitHub if anyone wants it. Just let me know.
P.P.S. - If there is any interest in a video, please let me know that as well by commenting below. No promises, but if enough people ask and I can find some free time...

About

The Java Jungle addresses topics from mobile to enterprise Java, tech news to techniques, and anything even remotely related. The goal is to help us all do our work better with Java, however we use it.

Your Java Jungle guide is Mark Heckler, an Oracle Senior Java/Middleware/Core Engineer with development experience in numerous environments. Mark's current work pursuits and passions all revolve around Java and leave little time to blog or tweet - but somehow, he finds time to do both anyway.

Mark lives with his very understanding wife & kids in the St. Louis, MO area.



Stay Connected

Search

Archives
« February 2015
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
       
       
Today