In this exercise, include the v option so that the JAR utility will output the results of the operation.
- The Java class files,
- manifest file, and
- image resources
for the FancyButton Bean are included with the course example source code, which you can download by clicking the Resources button on the menu bar to the left.
// FancyButtonFX.java
import javafx.beans.property.*;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Control;
import javafx.scene.control.SkinBase;
import javafx.scene.input.*;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class FancyButtonFX extends Region {
private final StringProperty label = new SimpleStringProperty("Push Me");
private final BooleanProperty sticky = new SimpleBooleanProperty(false);
private final BooleanProperty down = new SimpleBooleanProperty(false);
private final BooleanProperty hasFocus = new SimpleBooleanProperty(false);
private final Canvas canvas = new Canvas();
public FancyButtonFX() {
getChildren().add(canvas);
setFocusTraversable(true);
setFont(Font.font("System", 12));
setOnMousePressed(e -> {
down.set(!down.get());
draw();
});
setOnMouseReleased(e -> {
if (!sticky.get()) {
fireEvent(new ActionEvent());
down.set(false);
draw();
}
});
setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ENTER || e.getCode() == KeyCode.SPACE) {
if (sticky.get()) {
down.set(!down.get());
} else {
down.set(true);
fireEvent(new ActionEvent());
down.set(false);
}
draw();
}
});
focusedProperty().addListener((obs, oldVal, newVal) -> {
hasFocus.set(newVal);
draw();
});
widthProperty().addListener(e -> draw());
heightProperty().addListener(e -> draw());
label.addListener(e -> resizeToFit());
resizeToFit();
}
public final String getLabel() {
return label.get();
}
public final void setLabel(String value) {
label.set(value);
}
public final StringProperty labelProperty() {
return label;
}
public final boolean isSticky() {
return sticky.get();
}
public final void setSticky(boolean value) {
sticky.set(value);
}
public final BooleanProperty stickyProperty() {
return sticky;
}
public final boolean isDown() {
return down.get();
}
public final void setFont(Font font) {
canvas.getGraphicsContext2D().setFont(font);
resizeToFit();
}
private void resizeToFit() {
Font font = Font.font("System", 12);
Text text = new Text(label.get());
text.setFont(font);
double width = text.getLayoutBounds().getWidth() + 30;
double height = text.getLayoutBounds().getHeight() + 20;
setPrefSize(width, height);
canvas.setWidth(width);
canvas.setHeight(height);
draw();
}
private void draw() {
GraphicsContext g = canvas.getGraphicsContext2D();
double w = getWidth();
double h = getHeight();
// Background with 3D border
g.setFill(Color.LIGHTGRAY);
g.fillRect(0, 0, w, h);
boolean isPressed = down.get();
g.setStroke(Color.BLACK);
g.setLineWidth(1);
g.strokeRect(0, 0, w - 1, h - 1);
g.setStroke(isPressed ? Color.DARKGRAY : Color.WHITE);
g.strokeLine(1, h - 2, 1, 1);
g.strokeLine(1, 1, w - 2, 1);
// Draw text
g.setFill(Color.BLACK);
g.setFont(Font.font("System", 12));
double textWidth = g.getFontMetrics().computeStringWidth(label.get());
double textHeight = g.getFontMetrics().getLineHeight();
double offset = isPressed ? 2 : 0;
g.fillText(label.get(), (w - textWidth) / 2 + offset, (h + textHeight) / 2 - 4 + offset);
// Focus rectangle
if (hasFocus.get()) {
g.setStroke(Color.GRAY);
g.strokeRect(4, 4, w - 8, h - 8);
}
}
public void addActionHandler(EventHandler handler) {
addEventHandler(ActionEvent.ACTION, handler);
}
public void removeActionHandler(EventHandler handler) {
removeEventHandler(ActionEvent.ACTION, handler);
}
}