Wednesday, January 4, 2012

JavaFX 2's Tri-State CheckBox

JavaFX 2.0 provides the CheckBox (notice capital 'B' versus AWT's Checkbox's lowercase 'b') control that supports three states ("undefined", "checked", and "unchecked"). The AWT Checkbox only supports two states (on/true or off/false), but JavaFX's CheckBox can optionally support three states. If one desires the JavaFX version to support three states (the third being indeterminate), this is done by invoking allowIndeterminateProperty() on the CheckBox instance. Alternatively, setAllowIndeterminate(boolean) can be used to enable three states (passing it true) or only two states (passing it false).

The next code listing provides the source code for a simple JavaFX application that demonstrates the tri-state JavaFX CheckBox control. All the application does is to change the text associated with the CheckBox to indicate what state that CheckBox is in. As described in the CheckBox's Javadoc documentation, the three states of the CheckBox consist of "undefined" (indeterminate), "checked" (determinate and selected), or "unchecked" (determinate and not selected). This simple example boils these three states down to "determinate", "selected", and "unselected" and uses nested conditional ternary operators to set that String.

CheckboxExample.java
package dustin.examples;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.CheckBoxBuilder;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 * Simple example of JavaFX 2.0 Checkbox control.
 * 
 * @author Dustin
 */
public class CheckboxExample extends Application
{
   /**
    * Provides a checkbox instance with specified String and supporting three
    * states (supporting indeterminate state).
    * 
    * @param checkboxText Text to go with checkbox.
    * @return Checkbox with text.
    */
   private CheckBox buildTriStateCheckbox(final String checkboxText)
   {
      // Note that AWT's Checkbox does not have capital 'b'
      final CheckBox checkbox =
         CheckBoxBuilder.create()
                            .allowIndeterminate(true)
                            .indeterminate(true)
                            .prefHeight(50)
                            .prefWidth(300)
                            .text(checkboxText)
                            .build();

      checkbox.setOnMouseClicked(
         new EventHandler<MouseEvent>()
         {
            @Override
            public void handle(final MouseEvent mouseEvent)
            {
               final String newText =
                    checkbox.isIndeterminate()
                  ? "Indeterminate!"
                  : checkbox.isSelected() ? "Selected!": "Unselected!";
               checkbox.setText(newText);
            }
         }
      );
      return checkbox;
   }

   /**
    * Overridden method defined in parent class and used in JavaFX application
    * lifecycle.
    * 
    * @param stage
    * @throws Exception Exception during JavaFX sample application.
    */
   @Override
   public void start(final Stage stage) throws Exception
   {
      stage.setTitle("JavaFX 2 Checkbox Demo");
      final Group rootGroup = new Group();
      rootGroup.getChildren().add(buildTriStateCheckbox("Tri-State CheckBox"));
      final Scene scene = new Scene(rootGroup, 300, 50, Color.CADETBLUE);
      stage.setScene(scene);
      stage.show();
   }

   /**
    * Main function for running demonstration of JavaFX 2 Checkbox example.
    * 
    * @param arguments Command-line arguments: none expected;
    */
   public static void main(final String[] arguments)
   {
      Application.launch(arguments);
   }
}

This is another all-Java example of JavaFX and it can be compiled with the normal Java compiler (assuming JavaFX on the classpath) and executed with the normal Java application launcher (again assuming JavaFX on the classpath). When executed it behaves as demonstrated in the following series of static snapshots. The first screen snapshot is its initial appearance with initially set text and the three images following that one indicate the changing of the state of the CheckBox as it is clicked on.

The JavaFX 2 CheckBox class, like other JavaFX controls, provides significant more styling flexibility than the defaults I've shown here. The CheckBox is easy to use and can support two or three states as needed.

No comments: