I want to implement a simple popup control, which should be styleable with CSS.
It's all working fine the only question is how to add content (a Node in JavaFX) to it?
The PopupWindow.getContent() method is deprecated in JavaFX 2.2.6 and not working with CSS, I am able to see the content but the CSS-selector will not work then.
So what is the best solution to add content myself, should I implement my own Skin class for that purpose or is there a simple way to just make it work?
I have prepared a simple use case:
import javafx.scene.control.Label;
import javafx.scene.control.PopupControl;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
public class PopupTest extends PopupControl {
public PopupTest() {
getStyleClass().add("popup"); // not working!?
StackPane pane = new StackPane();
pane.getStyleClass().add("pane");
Rectangle rectangle = new Rectangle(250, 250);
rectangle.getStyleClass().add("rect");
Label text = new Label("popup test");
text.getStyleClass().add("text");
pane.getChildren().addAll(rectangle, text);
// how to display to pane when the popup is shown?
getContent().addAll(pane);
}
}
For completeness here are my MainApplication and CSS file:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class MainApplication extends Application {
#Override
public void start(Stage stage) throws Exception {
Group root = new Group();
final Scene scene = new Scene(root);
scene.getStylesheets().add(MainApplication.class.getResource("style.css").toExternalForm());
final Button button = new Button("show popup");
button.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
PopupTest popup = new PopupTest();
popup.show(scene.getWindow());
}
});
root.getChildren().add(button);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
style.css:
.popup {
-fx-font-size: 24px;
}
.popup .rect {
-fx-fill: green;
}
.popup .text {
-fx-text-fill: white;
-fx-font-weight: bold;
}
The ".popup" selector is not working here, if I set it to the "pane" it will style the popup window so the css is correct: pane.getStyleClass().add("popup"); // working with this "fix".
That seems to work:
getScene().setRoot(pane);
About the style class not working: PopupControl doesn't have a getStylesheets() method. So maybe it can only be styled directly by setStyle(...)? You can work around that by simply styling pane or by wrapping pane in a root pane and styling that.
Related
I just want to create copiable label in JavaFX.
I have tried to create TextField that have no background, have no focus border and default background color, but I have no success.
I have found a lot of questions how to remove focus background from control but all of that looks like "hacks".
Is there are any standard solution to implement copyable text?
You can create a TextField without the border and background color with css:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CopyableLabel extends Application {
#Override
public void start(Stage primaryStage) {
TextField copyable = new TextField("Copy this");
copyable.setEditable(false);
copyable.getStyleClass().add("copyable-label");
TextField tf2 = new TextField();
VBox root = new VBox();
root.getChildren().addAll(copyable, tf2);
Scene scene = new Scene(root, 250, 150);
scene.getStylesheets().add(getClass().getResource("copyable-text.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
and
copyable-text.css:
.copyable-label, .copyable-label:focused {
-fx-background-color: transparent ;
-fx-background-insets: 0px ;
}
This is the solution I used, where there is a small button besides the label to be able to copy the text:
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import org.controlsfx.glyphfont.FontAwesome;
import org.controlsfx.glyphfont.Glyph;
import java.util.Locale;
public class CopiableLabel extends Label
{
public CopiableLabel()
{
addCopyButton();
}
public CopiableLabel(String text)
{
super(text);
addCopyButton();
}
public CopiableLabel(String text, Node graphic)
{
super(text, graphic);
}
private void addCopyButton()
{
Button button = new Button();
button.visibleProperty().bind(textProperty().isEmpty().not());
button.managedProperty().bind(textProperty().isEmpty().not());
button.setFocusTraversable(false);
button.setPadding(new Insets(0.0, 4.0, 0.0, 4.0));
button.setOnAction(actionEvent -> AppUtils.copyToClipboard(getText()));
Glyph clipboardIcon = AppUtils.createFontAwesomeIcon(FontAwesome.Glyph.CLIPBOARD);
clipboardIcon.setFontSize(8.0);
button.setGraphic(clipboardIcon);
setGraphic(button);
setContentDisplay(ContentDisplay.RIGHT);
}
}
I was wondering how to make the caret visible and/or flash whilst using a TextField or TextArea. The ones I have created in my GUI work as the letters appear when typed but there is no visible caret.
I've looked through the TextField documentation but none are about making it visible or not. I expected to find something along the lines "setCaretVisible(Boolean);"
Do I have to make it visible via CSS? If so, any suggestions would be most welcome!
Please see code that I've quickly put together to illustrate the problem:
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Test extends Application {
public static void main(String[] arguments) { launch(arguments); }
#Override public void start(Stage stage) {
Scene scene = new Scene(new Group());
scene.setRoot(new BuildLayout(stage));
stage.setTitle("Application Name");
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setFullScreen(true);
stage.setFullScreenExitHint("");
stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
stage.show();
}
}
final class BuildLayout extends BorderPane {
protected BuildLayout(Stage stage) {
TabPane tabpane = new TabPane();
Tab tab = new Tab();
tab.setGraphic(new Text("Video Browser"));
tab.setClosable(false);
tab.setContent(new Input(1));
tabpane.getTabs().addAll(tab);
setTop(new Toolbar(stage));
setCenter(tabpane);
}
}
final class Input extends VBox {
Input(int id) {
HBox hbox = new HBox();
TextField videoTitle = new TextField("video_title");
TextArea description = new TextArea( "video_description");
Button share = new Button("share");
Button unshare = new Button("unshare");
setPadding(new Insets(5,10,10,5));
setAlignment(Pos.TOP_CENTER);
hbox.getChildren().addAll(videoTitle, new Text(" Creator: " + " Date: " + " Views: " + " "));
if(true) {
videoTitle.setEditable(true);
description.setEditable(true);
if(true) {
hbox.getChildren().add(share);
} else { hbox.getChildren().add(unshare); }
}
getChildren().addAll(hbox, description);
}
}
final class Toolbar extends HBox {
protected Toolbar(Stage stage) {
Button close = new Button("close");
close.setOnAction((ActionEvent e) -> { stage.close(); });
setAlignment(Pos.CENTER_LEFT);
getChildren().addAll(close);
}
}
Many thanks,
This problem only occurs on Mac and not Windows (untested Linux). The fix is to downgrade to a JavaFX 2.2 compliant maximised window as the setMaximized() from JavaFX 8 also isn't Mac compatible.
Modifying the start method with some code found here:
#Override public void start(Stage stage) {
Scene scene = new Scene(new Group());
scene.setRoot(new BuildLayout(stage));
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setTitle("Application Name");
stage.setScene(scene);
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.show();
}
Produces a fullscreen application with visible and flashing caret.
Does anyone know of a class that i can use that is essential a rectangle, BUT it has text in the middle of the rectangle and the rectangle has a fill color along with a border color(the border can be changed to red or something along those lines)
Essentially right now i have a pane, and i want to make a 2D grid(10x10), where each individual object in the grid is a rectangle-typed object that has a number text center justified, a fill color, and a border color.
Note: I've tried to use gridpane, but the lack of documentation that i've found has led me to believe i can only set the fill color, and each cell in the grid pane does NOT look like a separate object like i want it to. I've also tried to implement rectangle but the rectangle doesn't have text or a border that i can manipulate.
Thank you for your help.
Just use a Label. Here's a proof of concept:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class CustomLabelDemo extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Hello World");
label.setStyle(
"-fx-alignment: center;"
+"-fx-padding: 6px;"
+"-fx-background-color: red, -fx-background;"
+"-fx-background-insets: 0, 4px;"
);
StackPane root = new StackPane(label);
primaryStage.setScene(new Scene(root, 350, 75));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The way the css is working here is that it defines two backgrounds: the first (and thus the one at the back) is red; the one in front is set to -fx-background, which is the color defined in the default stylesheet for the background of most controls. Corresponding to these are two insets for the two backgrounds: the first set to zero, and the second set to 4 pixels. This means that 4 pixels of the red border will be visible. The padding is just set to make sure the text doesn't overlap the outer background (the border).
In a real application, you should put the style in an external file. You can also define a "looked-up-color" for the border color; this will make it much easier to change the color at runtime:
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomLabelDemo extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Hello World");
label.getStyleClass().add("custom-label");
Button changeColorButton = new Button("Change to green");
changeColorButton.setOnAction(event -> label.setStyle("custom-label-border-color: green;"));
VBox root = new VBox(10, label, changeColorButton);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 75);
scene.getStylesheets().add("custom-label.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with custom-label.css:
.custom-label {
custom-label-border-color: red ;
-fx-alignment: center;
-fx-padding: 6px;
-fx-background-color: custom-label-border-color, -fx-background;
-fx-background-insets: 0, 4px;
}
.button {
-fx-alignment: center ;
}
If you have a fixed set of states that the colors represent, you might want to use a pseudoclass to represent the state:
import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomLabelDemo extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Hello World");
label.getStyleClass().add("custom-label");
CheckBox errorCheckBox = new CheckBox("Error");
PseudoClass errorState = PseudoClass.getPseudoClass("error");
errorCheckBox.selectedProperty().addListener((obs, wasSelected, isNowSelected) ->
label.pseudoClassStateChanged(errorState, isNowSelected));
VBox root = new VBox(10, label, errorCheckBox);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 75);
scene.getStylesheets().add("custom-label.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
custom-label.css:
.custom-label {
custom-label-border-color: green ;
-fx-alignment: center;
-fx-padding: 6px;
-fx-background-color: custom-label-border-color, -fx-background;
-fx-background-insets: 0, 4px;
}
.custom-label:error {
custom-label-border-color: red ;
}
.check-box {
-fx-alignment: center ;
}
I think your best bet is to make a custom control, exposing the properties you need.
See http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm for info and examples.
I can't figure out how can I apply this kind of effect to the text-field in javaFX 2 using css (-fx-... :...);
I need something like in the screenshot. I have an panel with that background and i need for the text field to darken it up a little (it looks like an inner shadow).
I tried using smaller opacity on the panel and high opacity on the text input but is not working properly.
Thanks.
Run this sample app:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class StyleDemo extends Application {
#Override
public void start(Stage primaryStage) {
TextField txt = new TextField("text");
txt.setLayoutY(150);
txt.setPrefHeight(50);
txt.setStyle("-fx-background-color: rgb(0,0,0,0.11); -fx-text-fill: white; -fx-font-size: 28; -fx-font-weight: bold");
Pane root = new Pane();
root.setStyle("-fx-background-image: url(\"http://i.stack.imgur.com/ThghN.png\"); -fx-background-repeat: stretch; -fx-background-size: 300 250;");
root.getChildren().add(txt);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
To give an inner shadow effect to the text field, check this link out:
http://docs.oracle.com/javafx/2.0/api/javafx/scene/doc-files/cssref.html#typeeffect
This question already has an answer here:
JavaFX: Undecorated Window
(1 answer)
Closed 8 years ago.
I am making JavaFX destop application. I want to remove the default windows border and also I want to customize the 3 standard icons of minimize , maximize and close.
The original motivation of this kind of looks or customization is new Kaspersky 2012 User Interface.... I want to design something like that... :)
This example might be a good starting point. All window decoration is removed. A class extending HBox can be used to place custom buttons for standard window operations.
package javafxdemo;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class JavaDemo extends Application {
public static void main(String[] args) {
launch(args);
}
class WindowButtons extends HBox {
public WindowButtons() {
Button closeBtn = new Button("X");
closeBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
Platform.exit();
}
});
this.getChildren().add(closeBtn);
}
}
#Override
public void start(Stage primaryStage) {
//remove window decoration
primaryStage.initStyle(StageStyle.UNDECORATED);
BorderPane borderPane = new BorderPane();
borderPane.setStyle("-fx-background-color: green;");
ToolBar toolBar = new ToolBar();
int height = 25;
toolBar.setPrefHeight(height);
toolBar.setMinHeight(height);
toolBar.setMaxHeight(height);
toolBar.getItems().add(new WindowButtons());
borderPane.setTop(toolBar);
primaryStage.setScene(new Scene(borderPane, 300, 250));
primaryStage.show();
}
}
You can also download the JavaFX Samples where you can find many more useful examples.