Changing the drop down indicator image on a JavaFX MenuButton? - styling

In my application I am using a MenuButton to provide a drop down list of actions. The default drop down indicator on a MenuButton is a black triangle pointing down. I want to change that to a white triangle pointing down to match the color of my text.
Just in case I am not being clear, here is a screen shot that should clear it up.
I have tried placing a graphic in the fxml file like so:
<MenuButton contentDisplay="RIGHT" graphicTextGap="10.0" layoutX="92.0" layoutY="73.0" mnemonicParsing="false" styleClass="toolbar-button" text="MenuButton">
<graphic>
<ImageView fitHeight="4.0" fitWidth="7.0" mouseTransparent="true" preserveRatio="true">
<image>
<Image url="#Arrow_Down.png" preserveRatio="true" smooth="false" />
</image>
</ImageView>
</graphic>
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</MenuButton>
but that gives me both a black and white triangle:
If I could somehow hide the black triangle that would work, but it sure seems like there should be a way to style the menu button for it to be white instead.
Here is Sample.fxml for those wanting to help:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200.0" prefWidth="320.0" xmlns:fx="http://javafx.com/fxml">
<children>
<MenuButton contentDisplay="RIGHT" graphicTextGap="10.0" layoutX="92.0" layoutY="73.0" mnemonicParsing="false" styleClass="toolbar-button" text="MenuButton">
<graphic>
<ImageView fitHeight="4.0" fitWidth="7.0" mouseTransparent="true" preserveRatio="true">
<image>
<Image url="#Arrow_Down.png" preserveRatio="true" smooth="false" />
</image>
</ImageView>
</graphic>
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</MenuButton>
</children>
<stylesheets>
<URL value="#test.css" />
</stylesheets>
</AnchorPane>
The test.css:
root {
display: block;
}
.toolbar-button {
-fx-background-color: #006699;
-fx-padding: 2 4 4 4;
-fx-text-base-color: #FFFFFF;
-fx-font-weight: bold;
-fx-font-size: 12px;
}
.toolbar-button:hover {
-fx-background-color: #B2E1FF;
-fx-padding: 2 4 4 4;
-fx-text-base-color: #000000;
-fx-font-weight: bold;
-fx-font-size: 12px;
}
And the Test.java to run it:
package test;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Test extends Application {
public static void main(String[] args) {
Application.launch(Test.class, args);
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
stage.setScene(new Scene(root));
stage.show();
}
}
So how do I make the black triangle a white triangle?

After some digging I found the answer. Turns out MenuButton does not use an image for the button but instead us -fx-shape css property to do this. In the caspian.css file it is applied in the .menu-button .arrow and .menu-button:openvertically .arrow sections. Since I was already applying the toolbar-button to my MenuButton, I simply added the following to the my css file:
.toolbar-button .arrow {
-fx-background-insets: 1 0 -1 0, 0;
-fx-background-color: -fx-mark-color, #FFFFFF;
-fx-padding: 0.25em; /* 3 */
-fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z";
}
.toolbar-button:hover .arrow {
-fx-background-insets: 1 0 -1 0, 0;
-fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
-fx-padding: 0.25em; /* 3 */
-fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z";
}
.toolbar-button:openvertically .arrow {
-fx-padding: 0.166667em 0.333333em 0.166667em 0.333333em; /* 2 4 2 4 */
-fx-shape: "M 0 0 h 7 l -3.5 4 z";
}
Which even allows me to change the color of the arrow back to black on hover.

Related

JavaFX : Rotated TitledPane does not fill the layout

I'm making a desktop application and was trying to create a vertical TitledPane to represent a "vertical collapsible toolbar".
I have done some researches on how to do it and was able to create my vertical TitledPane correctly, but I can't figure out how to set the size of the TitledPane to fill the layout.
Here is a screenshot of what I've done, and what I want. My VerticalTitledPane is an FXML included in a root layout, which is a BorderPane, and is set to be placed on the left container. Do you know if it is possible to tell the TitledPane to fill the layout (where TitledPane.height = BorderPane.left.height in pseudo-code) ?
Here is the FXML of the vertical TitledPane. The BorderPane just includes and sets it to the left (if needed please ask) :
<Group xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.aardex.widgets.toolbar_vertical.VerticalToolbarCtrl" fx:id="group">
<stylesheets>
<URL value="#/ch/aardex/widgets/toolbar_vertical/toolbar_vertical.css"/>
</stylesheets>
<children>
<Accordion rotate="90.0" fx:id="accordion">
<panes>
<TitledPane onMouseClicked="#expandMenu" >
<content>
<HBox spacing="15.0">
<children>
<Button fx:id="btShowHome" styleClass="vertical-bar-button" onAction="#showHome" rotate="270.0" >
<graphic>
<ImageView>
<Image url="/ch/aardex/widgets/images/logo_home_48.png"/>
</ImageView>
</graphic>
</Button>
<Button fx:id="btShowInitPatient" styleClass="vertical-bar-button" onAction="#showInitPatient" rotate="270.0" >
<graphic>
<ImageView>
<Image url="/ch/aardex/widgets/images/user_add_48.png"/>
</ImageView>
</graphic>
</Button>
<Button fx:id="btShowReadMems" styleClass="vertical-bar-button" onAction="#showReadMems" rotate="270.0">
<graphic>
<ImageView>
<Image url="/ch/aardex/widgets/images/mems_read_48.png"/>
</ImageView>
</graphic>
</Button>
<Button fx:id="btShowPatientList" styleClass="vertical-bar-button" onAction="#showPatientList" rotate="270.0">
<graphic>
<ImageView>
<Image url="/ch/aardex/widgets/images/user_group_48.png"/>
</ImageView>
</graphic>
</Button>
</children>
</HBox>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
Thank you very much !
I finally found a way to implement what I wanted. Since I have not found many answers, I'll post mine hoping this could help someone else.
The best I've found to implement this is to use a simple VBox with some animations.
Here is the FXML :
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.*?>
<VBox minWidth="75.0" alignment="CENTER_RIGHT" styleClass="vertical-bar" fx:id="toolbarVertical" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.aardex.root.ToolbarVerticalCtrl">
<padding>
<Insets top="10" right="10" bottom="10" left="10"/>
</padding>
<Button fx:id="btExpandMenu" styleClass="vertical-bar-button" onAction="#expandMenu" >
<graphic>
<ImageView>
<Image url="..."/>
</ImageView>
</graphic>
</Button>
<VBox VBox.vgrow="ALWAYS"/>
<GridPane alignment="CENTER_RIGHT" >
<Label fx:id="homeLabel" text="Go to the dashboard view" GridPane.columnIndex="0" GridPane.rowIndex="0" managed="false" wrapText="true" />
<Button fx:id="homeBt" styleClass="vertical-bar-button" onAction="#showHome" GridPane.columnIndex="1" GridPane.rowIndex="0" >
<graphic>
<ImageView>
<Image url="..."/>
</ImageView>
</graphic>
</Button>
<Label fx:id="addLabel" text="Read a patient or add a new one" GridPane.columnIndex="0" GridPane.rowIndex="1" managed="false" wrapText="true"/>
<Button fx:id="addBt" styleClass="vertical-bar-button" onAction="#showInitPatient" GridPane.columnIndex="1" GridPane.rowIndex="1" >
<graphic>
<ImageView>
<Image url="..."/>
</ImageView>
</graphic>
</Button>
<Label fx:id="listLabel" text="Show the list of patients" GridPane.columnIndex="0" GridPane.rowIndex="2" managed="false" wrapText="true"/>
<Button fx:id="listBt" styleClass="vertical-bar-button" onAction="#showPatientList" GridPane.columnIndex="1" GridPane.rowIndex="2">
<graphic>
<ImageView>
<Image url="..."/>
</ImageView>
</graphic>
</Button>
<Label fx:id="confLabel" text="Settings of the app" GridPane.columnIndex="0" GridPane.rowIndex="3" managed="false" wrapText="true"/>
<Button fx:id="confBt" styleClass="vertical-bar-button" onAction="#showConfiguration" GridPane.columnIndex="1" GridPane.rowIndex="3">
<graphic>
<ImageView>
<Image url="..."/>
</ImageView>
</graphic>
</Button>
</GridPane>
</VBox>
And the controller :
import ch.aardex.common.IController;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.Animation;
import javafx.animation.Transition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.util.Duration;
public class ToolbarVerticalCtrl extends IController implements Initializable {
// FXML controls
#FXML private VBox toolbarVertical;
#FXML private Label homeLabel;
#FXML private Button homeBt;
#FXML private Label addLabel;
#FXML private Button addBt;
#FXML private Label listLabel;
#FXML private Button listBt;
#FXML private Label confLabel;
#FXML private Button confBt;
// Constants
private final double EXPANSION = 90.0; // the expansion of the vertical toolbar
private final double MARGIN = 10.0; // the margin of the vertical toolbar
// margin is used to set the offset when sliding the toolbar
// Variables
private boolean hidden = true; // is the bar hidden ?
#Override
public void initialize(URL url, ResourceBundle rb) {
}
#FXML
private void showHome(ActionEvent event) {
getRoot().initViewWithTopOnly(DASHBOARD_VIEW);
}
#FXML
private void showInitPatient(ActionEvent event) {
getRoot().initViewWithTopAndVertical(WORKFLOW_VIEW);
}
#FXML
private void showPatientList(ActionEvent event) {
getRoot().initViewWithTopAndVertical(LIST_VIEW);
}
#FXML
private void showConfiguration(ActionEvent event) {
getRoot().initViewWithTopAndVertical(CONFIG_VIEW);
}
#FXML
private void expandMenu(ActionEvent event){
final Animation hideSideBar = new Transition() {
{ setCycleDuration(Duration.millis(250)); }
#Override
protected void interpolate(double frac) {
double current = EXPANSION - EXPANSION * frac;
toolbarVertical.setPrefWidth(EXPANSION + current);
}
};
final Animation showSideBar = new Transition() {
{ setCycleDuration(Duration.millis(250)); }
#Override
protected void interpolate(double frac) {
double current = MARGIN + EXPANSION * frac;
toolbarVertical.setPrefWidth(EXPANSION + current);
}
};
showSideBar.onFinishedProperty().set((ActionEvent event1) -> {
setLabelsManagement(true);
});
if(showSideBar.statusProperty().get() == Animation.Status.STOPPED &&
hideSideBar.statusProperty().get() == Animation.Status.STOPPED){
if(!hidden){
hideSideBar.play();
setLabelsManagement(false);
System.out.println(toolbarVertical.getWidth());
} else {
showSideBar.play();
System.out.println(toolbarVertical.getWidth());
}
}
}
private void setLabelsManagement(boolean b){
homeLabel.setManaged(b);
homeLabel.setVisible(b);
addLabel.setManaged(b);
addLabel.setVisible(b);
listLabel.setManaged(b);
listLabel.setVisible(b);
confLabel.setManaged(b);
confLabel.setVisible(b);
hidden = !b;
}
}
The important part is the expandMenu function, which is in charge of sliding the VBox and hiding / managing or not the Labels (because in this case, they can be laid out even when hidden, and thus add some extra space when not required).
The original source can give you a few more hints, the idea comes from here.
Hope this can help someone, cheers !

How to keep rotating image or canvas

This code only fire once to rotate the canvas. Why it does not rotate when user press the rotate button second time?
--update with button
<AppBarButton x:Name="CamRotate90" Margin="0,2,2,0" Width="90" Height="90" FontSize="16" Label="Rotate-Right" Icon="Rotate" Click="CamRotate90_Click">
</AppBarButton>
<Canvas x:Name="canvas" Margin="231,28,321,111" Width="700" Height="525" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0">
<Image Canvas.Top="0" Canvas.Left="0" Margin="0" x:Name="preview" Width="700" Height="525" Stretch="UniformToFill" >
</Image>
</Canvas>
private void CamRotate90_Click(object sender, RoutedEventArgs e)
{
CompositeTransform ct = new CompositeTransform();
ct.CenterX = canvas.ActualWidth / 2;
ct.CenterY = canvas.ActualHeight/2;
ct.Rotation = 90;
canvas.RenderTransform = ct;
}
Instead of replacing the RenderTransform each time create the RenderTransform once and reuse it:
Xaml:
<Canvas x:Name="canvas" Margin="231,28,321,111" Width="700" Height="525" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0">
<Canvas.RenderTransform>
<CompositeTransform />
</Canvas.RenderTransform>
<Image Canvas.Top="0" Canvas.Left="0" Margin="0" x:Name="preview" Width="700" Height="525" Stretch="UniformToFill" >
</Image>
</Canvas>
Code:
private void CamRotate90_Click(object sender, RoutedEventArgs e)
{
CompositeTransform ct = canvas.RenderTransform as CompositeTransform;
if (ct != null) // Just to make sure
{
ct.CenterX = canvas.ActualWidth / 2;
ct.CenterY = canvas.ActualHeight / 2;
ct.Rotation += 90;
}
}

Popup goes behind stage only on Mac but not on Windows/Linux in Full Screen

I'm extending javafx.stage.Popup to display a popup message. The entire app works fine on Windows and Ubuntu but on Mac Popups go behind the current stage when the app is full screen. I've tried using z-index,.toFront(), setting owner window and everything. But the popups just never showup! Same problem is with javafx.stage.FileChooser. Since the app must be fullscreen all the time, what is the solution?
EDIT: In another page,the textfield has cursor blinking in fullscreen but does not receive typed keys! And this happens ONLY in full screen! If I lose fullscreen, the textfield recieves typed keys. Quite annoying :( Please suggest if I should file a bug or something
I've figured out workaround for popup but problem persists for DirectoryChooser/FileChooser.
This is the class that extends Popup:
public class PopupDisplay extends Popup
{
String Title=new String("Information");
String Prompt=new String("Prompt Text");
#FXML
private AnchorPane anchorMain;
#FXML
private Label lblTitle=new Label();
#FXML
private Font x1;
#FXML
private Label lblPrompt=new Label();
#FXML
private Button btnOk;
#FXML
private GridPane gridMain;
#FXML
private HBox hboxTitle;
static PopupDisplay instance;
private ColorDxDesktop application;
public void show(Stage stage, String titleKey,String promptKey, Locale enLocale)
{
AnchorPane root;
FXMLLoader loader=new FXMLLoader();
ResourceBundle rb;
Prompt=promptKey;
Title=titleKey;
try
{
loader.setLocation(getClass().getResource("/com/sc/colordx/resources/"));
rb=ResourceBundle.getBundle("com.sc.colordx.resources.lang.Popup",application.getLocale());
loader.setResources(rb);
PopupController.prompt=Prompt;
PopupController.title=Title;
root = (AnchorPane)loader.load(getClass().getResource("/com/sc/colordx/presentation/Popup.fxml").openStream());
getScene().setRoot(root);
PopupController popupController=loader.getController();
Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
root.setPrefWidth(application.getStage().getWidth());
root.setPrefHeight(application.getStage().getHeight());
Node n=root.getChildren().get(0);
n.setLayoutX(screenBounds.getWidth()/2.5);
n.setLayoutY((screenBounds.getHeight()/2.5));
//root.toFront();
show(stage);
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
public static PopupDisplay getInstance()
{
return instance;
}
#FXML
private void hide(MouseEvent event)
{
this.hide();
}
public void showInProgress()
{
PopupController.showInProgress();
}
And this is the FXML for Popup:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.net.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane id="AnchorPane" fx:id="anchorMain" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" styleClass="mainFxmlClass" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="com.sc.colordx.controller.PopupController">
<children>
<GridPane id="GridPane" fx:id="gridMain" alignment="CENTER" layoutX="309.0" layoutY="330.0" minWidth="400.0" style="-fx-background-color:black;" styleClass="visibleWindow, gridpane, gridpane-boder" vgap="20.0">
<children>
<Label fx:id="lblPrompt" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefWidth="271.0" text="%keyPrompt" textFill="WHITE" textOverrun="CLIP" wrapText="true" GridPane.columnIndex="0" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
<font>
<Font name="System Bold" size="14.0" fx:id="x1" />
</font>
<GridPane.margin>
<Insets bottom="6.0" left="6.0" right="6.0" top="6.0" />
</GridPane.margin>
</Label>
<HBox id="HBox" fx:id="hboxButtons" alignment="CENTER" spacing="7.0" style="" styleClass="hbox" GridPane.columnIndex="0" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS">
<children>
<Button fx:id="btnOk" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onMouseClicked="#exitOkay" text="%keyYes" HBox.hgrow="ALWAYS" />
<Button id="btnOk" fx:id="btnCancel" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onMouseClicked="#hide" text="%keyNo" HBox.hgrow="ALWAYS" />
</children>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
<stylesheets>
<URL value="#../resources/css/Popup.css" />
</stylesheets>
</HBox>
<ProgressIndicator fx:id="progress" cache="true" cacheHint="QUALITY" progress="0.0" visible="false" GridPane.columnIndex="0" GridPane.rowIndex="1">
<GridPane.margin>
<Insets left="300.0" />
</GridPane.margin>
</ProgressIndicator>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<padding>
<Insets />
</padding>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
<stylesheets>
<URL value="#../resources/css/Popup.css" />
</stylesheets>
</AnchorPane>
The same thing I was getting with Popup while running JavaFx application in MAC so what I did was created new Stage (dummy/invisible with height and width = 0) with initStyle(StageStyle.UTILITY); and bind my popup with that. Everytime I need to display popup I use dummyStage.show(); and popup.toFront(); so it will cause a trick to handle my problem in mac.

Determine maximum dimensions a Canvas could grow to?

I am using a BorderPane, where the right area is unused. In the center area I have a HBox with a Canvas and another control e.g. a Button. I want the Canvas to have the same width and height with a value of
Canvas width and height = minimum{maximum possible Canvas height, maximum possible Canvas width}
(in other words: Canvas should be a square)
My problem is: How do I determine the maximum width and the maximum height that a Canvas could grow to?
Here is my FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<BorderPane id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<bottom>
<Label text="Bottom area" />
</bottom>
<center>
<HBox>
<children>
<Canvas width="300" height="300" />
<Button mnemonicParsing="false" text="some button next to the Canvas" />
</children>
</HBox>
</center>
<left>
<Button mnemonicParsing="false" text="Left area"/>
</left>
<top>
<MenuBar>
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
</BorderPane>
Thanks for any hint!
The easiest way I can see this being done is: canvas.getwidth() and canvas.getHeight()
You have to add canvas manually, after the GUI is constructed, so you can calculate its size:
public class YourController implements Initializable {
#FXML HBox mHBox;
#FXML Button mButton;
#Override
public void initialize(final URL paramURL, final ResourceBundle paramResourceBundle) {
Platform.runLater(new Runnable() { public void run() {
double w0 = mHBox.getWidth();
double w1 = mButton.getWidth();
double h0 = mHBox.getHeight();
double size = Math.min(w0-w1, h0);
Canvas canvas = new Canvas(size, size);
mHBox.getChildren().add(0, canvas);
}});
}
}
Problem with the Canvas is that is is not resizable :(

How to center a JavaFX 2.0 application on a browser's window

I am building a application in JavaFx 2.0 and would like to, when the application is deployed, to have it show up on the center of the window of a browser. I have looked for this topic in google and yahoo and found nothing. Any help is greatly appreciated.
Look at the source code for the JavaFX Ensemble example. The Ensemble application is configured to run to fill a browser window, no matter the size of the window. The way it is done is by configuration in the JavaScript which launches the app as well as via css styling of the div the application is embedded in.
Here is an extract of the relevant parts of the html.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JavaFX 2.0 - Ensemble</title>
<SCRIPT src="http://java.com/js/dtjava.js"></SCRIPT>
<script>
function javafxEmbed_ensemble() {
dtjava.embed(
{
id : 'ensemble',
url : 'Ensemble.jnlp',
placeholder : 'javafx-app-placeholder',
width : '100%',
height : '100%',
jnlp_content : '...'
},
{
javafx : '2.0+'
},
{}
);
}
dtjava.addOnloadCallback(javafxEmbed_ensemble);
</script>
<style>
html, body, #javafx-app-placeholder, #ensemble-app {
margin: 0;
overflow: hidden;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body><div id='javafx-app-placeholder'></div></body>
</html>
If you need something other than 100% coverage, you can the 100% tags to, say 75%, and adjust the css styling to get centering in the page with the margins you want.
The current Java packaging tools (e.g. the javafxpackager utility), do not allow specification of percentange widths. I've created a feature request for this in the javafx jira - you can create an account there to view the request. If you use those tools to generate your deployment html, then you might have to modify the deployment html by hand or by a post-processing ant script, as can be seen in the build.xml for the Ensemble sample application.
You can use combination of HBox and VBox panels in your FXML. Hier is my tested code:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="panel1" xmlns:fx="http://javafx.com/fxml" fx:controller="app.MainController">
<HBox alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<VBox alignment="CENTER">
<Pane fx:id="panel2"></Pane> <!-- YOUR CENTERED CONTENT HERE! -->
</VBox>
</HBox>
</AnchorPane>
The 'panel1' will stretch in the browser area. So the HBox and VBox will also. Because they have 'center' attributes for their childeren, the 'panel2' will be centered.
Use this FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml">
<children>
<HBox id="HBox" alignment="CENTER" spacing="5.0" AnchorPane.bottomAnchor="213.0" AnchorPane.leftAnchor="168.0" AnchorPane.rightAnchor="168.0" AnchorPane.topAnchor="214.0">
<children>
<GridPane id="gridPane1" alignment="CENTER" hgap="2.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="2.0">
<children>
<Label id="label1" alignment="CENTER_RIGHT" contentDisplay="RIGHT" text="Username" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Label id="label2" alignment="CENTER_RIGHT" text="Password" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<TextField id="textField1" fx:id="userid" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="0" />
<PasswordField id="passwordField1" fx:id="password" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Button id="button1" alignment="CENTER_RIGHT" text="Signin" GridPane.columnIndex="1" GridPane.halignment="RIGHT" GridPane.rowIndex="2" />
</children>
<columnConstraints>
<ColumnConstraints halignment="CENTER" hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" percentWidth="0.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<padding>
<Insets bottom="2.0" left="4.0" right="4.0" top="2.0" />
</padding>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
</children>
</HBox>
</children>
</AnchorPane>
Might solve your problem
Try to use a StackPane as container. It will center all nodes it includes.
Torsten

Resources