gbear
gbear

Reputation: 91

Java ChoiceDialog change default button order

Contrary to expectations the default order of Buttons in a ChoiceDialog is 'Cancel', to the left, and 'OK' to the right.

In this method, I create a dialog that lists the Sex of cattle (Cow, Heifer, Steer, etc). All works fine using the default dialog except the button order is the reverse of every other custom built dialog I have built.

It was my belief that the "Java Look and Feel Design Guidelines" require dialogs with "OK" left and "Cancel" to the right.

Anyway, as the code below demonstrates, I have tried to set my own Buttons. Changing the order in which they are added, makes no difference.

However, I can have the order I seek, if ButtonData.OTHER, but then I don't get the desired result (the Sex selected).

All I really want to do is change the button order, and get the desired result.

public static final String getChoice_Sex()
{
    String sex = "";
    List<String> list_Sexs = LM_Constant.getList_Sexs();

    ChoiceDialog<String> dialog = new ChoiceDialog<>(list_Sexs.get(0), list_Sexs);
    dialog.setTitle("Sex");
    dialog.setHeaderText("Please choose one.");
    dialog.setContentText("From this list:");

    //ButtonType button_OK = new ButtonType("OK", ButtonData.OK_DONE); 
    //ButtonType button_OK = new ButtonType("OK", ButtonData.OTHER); 
    //ButtonType button_Cancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);

    //dialog.getDialogPane().getButtonTypes().clear();
    //dialog.getDialogPane().getButtonTypes().add(button_Cancel);
    //dialog.getDialogPane().getButtonTypes().add(button_OK);
    //dialog.getDialogPane().getButtonTypes().add(button_Cancel);

    Optional<String> result = dialog.showAndWait();        
    if (result.isPresent())
        sex = result.get();

    return sex;
}

Upvotes: 4

Views: 1052

Answers (1)

Dave Jarvis
Dave Jarvis

Reputation: 31191

Button ordering on dialogs (and dialog panes) can be configured as follows:

  1. Create a subclass of ChoiceDialog (e.g., CattleGenderDialog)
  2. Create a subclass of DialogPane (e.g., ButtonOrderPane).
  3. Set the DialogPane for CattleGenderDialog to use the ButtonOrderPane.
  4. Have ButtonOrderPane return buttons in the preferred order.

Once the class relationships are understood, the code is trivial.

CattleGenderDialog Class

public class CattleGenderDialog extends ChoiceDialog {
  public CattleGenderDialog( final Window owner ) {
    initOwner( owner );

    // This is the key line to override button order.
    setDialogPane( new ButtonOrderPane() );

    // This line will return the button order pane.
    final DialogPane dialogPane = getDialogPane();
    dialogPane.setContent( pane );
    dialogPane.getButtonTypes().addAll( ... );
  }
}

ButtonOrderPane Class

import static javafx.scene.control.ButtonBar.BUTTON_ORDER_WINDOWS;

public class ButtonOrderPane extends DialogPane {

  // This is where the revised button order is defined.
  @Override
  protected Node createButtonBar() {
    final ButtonBar node = (ButtonBar)super.createButtonBar();
    node.setButtonOrder( getButtonOrder() );
    return node;
  }

  private String getButtonOrder() {
    return getSetting( "dialog.alert.button.order.windows", BUTTON_ORDER_WINDOWS );
  }

  private String getSetting( final String key, final String defaultValue ) {
    return getSettings().getSetting( key, defaultValue );
  }

  // How you load the settings is up to you; I prefer decoupled code.
  private Settings getSettings() {
    return Services.load( Settings.class );
  }
}

Settings

The settings include the following property definitions:

dialog.alert.button.order.mac=L_HE+U+FBIX_NCYOA_R
dialog.alert.button.order.linux=L_HE+UNYACBXIO_R
dialog.alert.button.order.windows=L_E+U+FBXI_YNOCAH_R

This permits consistent buttons across the application, independent of platform while providing users the flexibility to pick their preferred button order. (Maybe a Mac user prefers the Linux ordering.)

Upvotes: 1

Related Questions