JimLohse JimLohse - 9 days ago 5
Java Question

Remove JavaFX button padding?

I am building a very simple looking calculator and I can't figure out where the padding around these buttons is coming from. Here's how I am building the flow pane:

private FlowPane addFlowPaneRightSide() {

FlowPane flow = new FlowPane();
//flow.setPadding(new Insets(0, 0, 0, 0));
flow.setVgap(0);
flow.setHgap(0);
flow.setPrefWrapLength(WIDTH_OF_CENTER / 3); // width of function buttons
flow.setStyle("-fx-background-color: 978c87;");

// setup arrays to hold the buttons and images for the right column
Button operatorButtons[] = new Button[NUM_OP_BUTTONS];
ImageView operatorImages[] = new ImageView[NUM_OP_BUTTONS];

for (int i=0; i < NUM_OP_BUTTONS; i++) {
operatorImages[i] = new ImageView(
new Image(Calculator.class.getResourceAsStream(
"images/orange-"+(i)+".png")));
operatorButtons[i] = new Button();
operatorButtons[i].setGraphic(operatorImages[i]);
operatorButtons[i].setId("orange-"+(i));
flow.getChildren().add(operatorButtons[i]);
}

return flow;
}


When I was just putting the images in the flow pane it worked fine but as soon as I began creating buttons in the loop it gave me this:

Just imagine a Yosemite Calculator but with about 10-ish pixels between each button on the calculator.

My CSS:

/*
Document : stylesheet.css
for Calculator project in JavaFX
*/

.root{
-fx-font-size: 14pt;
-fx-font-family: "Tahoma";
}

.button{
-fx-text-fill: #006464;
-fx-skin: "com.sun.javafx.scene.control.skin.ButtonSkin";
/*-fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;*/
-fx-background-color: transparent;
-fx-background-insets: 0 0 0 0, 0, 0, 0;
-fx-background-radius: 0 0 0 0, 0, 0, 0;
-fx-border-width: 0 0 0 0, 0, 0, 0;
}

.button:focused {
-fx-color: -fx-focused-base;
/*-fx-background-color: -fx-focus-color, -fx-outer-border, -fx-inner-border, -fx-body-color;*/
-fx-background-color: transparent;
-fx-background-insets: 0 0 0 0, 0, 0, 0;
-fx-background-radius: 0 0 0 0, 0, 0, 0;
-fx-border-width: 0 0 0 0, 0, 0, 0;
}


And finally the entire program:

package calculator;


import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;

/**
*
* @author Jim Lohse
*/
public class Calculator extends Application {

public final int CALC_WIDTH = 500;
public final int CALC_HEIGHT = 642;
public final int NUM_BUTTONS = 15;
public final int NUM_OP_BUTTONS = 5;
public final int WIDTH_OF_CENTER = 354;

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage stage) {

// Use a border pane as the root for scene
BorderPane border = new BorderPane();

HBox hbox = addHBox();
border.setTop(hbox);

border.setRight(addFlowPaneRightSide());

border.setCenter(addFlowPaneCenter());

Scene scene = new Scene(border, CALC_WIDTH, CALC_HEIGHT);
scene.getStylesheets().add("calculator/stylesheet.css");
stage.setScene(scene);
stage.setTitle("Calculator");
stage.setResizable(false);
stage.show();
}

/*
* Creates an HBox with two buttons for the top region
*/

private HBox addHBox() {

HBox hbox = new HBox();
hbox.setPadding(new Insets(15, 12, 15, 12));
hbox.setSpacing(10); // Gap between nodes
hbox.setStyle("-fx-background-color: #336699;");

Button buttonCurrent = new Button("Current");
buttonCurrent.setPrefSize(100, 20);

Button buttonProjected = new Button("Projected");
buttonProjected.setPrefSize(100, 20);

hbox.getChildren().addAll(buttonCurrent, buttonProjected);

return hbox;
}

/*
* Creates a horizontal flow pane with the orange operations buttons
*/
private FlowPane addFlowPaneRightSide() {

FlowPane flow = new FlowPane();
//flow.setPadding(new Insets(0, 0, 0, 0));
flow.setVgap(0);
flow.setHgap(0);
flow.setPrefWrapLength(WIDTH_OF_CENTER / 3); // width of function buttons

// setup arrays to hold the buttons and images for the right column
Button operatorButtons[] = new Button[NUM_OP_BUTTONS];
ImageView operatorImages[] = new ImageView[NUM_OP_BUTTONS];

for (int i=0; i < NUM_OP_BUTTONS; i++) {
operatorImages[i] = new ImageView(
new Image(Calculator.class.getResourceAsStream(
"images/orange-"+(i)+".png")));
operatorButtons[i] = new Button();
operatorButtons[i].setGraphic(operatorImages[i]);
operatorButtons[i].setId("orange-"+(i));
flow.getChildren().add(operatorButtons[i]);
}

return flow;
}

/*
* Creates a horizontal flow pane with the orange operations buttons
*/
private FlowPane addFlowPaneCenter() {

FlowPane flow = new FlowPane();
//flow.setPadding(new Insets(0, 0, 0, 0));
flow.setVgap(0);
flow.setHgap(0);
flow.setPrefWrapLength(WIDTH_OF_CENTER); // width of function buttons

Button centerButtons[] = new Button[NUM_BUTTONS];
ImageView centerImages[] = new ImageView[NUM_BUTTONS];
for (int i=0; i < NUM_BUTTONS; i++) {
centerImages[i] = new ImageView(
new Image(Calculator.class.getResourceAsStream(
"images/button-"+(i)+".png")));
centerButtons[i] = new Button();
centerButtons[i].setGraphic(centerImages[i]);
centerButtons[i].setId("button-"+(i));
flow.getChildren().add(centerButtons[i]);
}

return flow;
}
}

Answer

I don't have a copy of the image you are using, so I can't see what it should look like. But I will try with a picture of a square.

That gets me:

This here

Now, there is no actual padding between the buttons from what I can see as you describe. What I think you might be saying is there is some padding in the label region itself that is causing the problem for you. This is very easy to fix.

Fixed version

How I fixed this was by adding a line of code (blah[i].setPadding(Insets.EMPTY)) to each of the buttons as they were being made.

for (int i=0; i < NUM_OP_BUTTONS; i++) {
    operatorImages[i] = new ImageView(
            new Image(Java.class.getResourceAsStream(
                    "art" + File.separator + "Square.png")));
    operatorButtons[i] = new Button();
    operatorButtons[i].setGraphic(operatorImages[i]);
    operatorButtons[i].setPadding(Insets.EMPTY);
    operatorButtons[i].setId("orange-"+(i));
    flow.getChildren().add(operatorButtons[i]);
}

and

for (int i=0; i < NUM_BUTTONS; i++) {
    centerImages[i] = new ImageView(
            new Image(Java.class.getResourceAsStream(
                    "art" + File.separator + "Square.png")));
    centerButtons[i] = new Button();
    centerButtons[i].setGraphic(centerImages[i]);
    centerButtons[i].setPadding(Insets.EMPTY);
    centerButtons[i].setId("button-"+(i));
    flow.getChildren().add(centerButtons[i]);
}

This should fix your little problem.

EDIT: Just thought to mention, the tiny bit of whitespace you see is part of the image itself and not padding.