EDIT:
I've determined that the following line is the cause:
primaryStage.initStyle(StageStyle.UNIFIED);
Can any explain why it would be causing this issue?
JDK: 13.0.1
FX: 13
Eclipse: 2019-09 R (4.13.0)
Maybe I'm going crazy, because I feel like I do pretty good with JavaFX... But for some reason, the buttons don't appear, but I can press them, and my logger says the buttons are pressed. I can press the exit button (although invisible), and it quits as expected... so why are the button invisible?
I've attempted to set visibility to true, but that did nothing too. The button sizes appear to be set properly too.
public class test extends Application {
private Button gameButton = new Button("Game");
private Button mapEditorButton = new Button("Map Editor");
private Button exitButton = new Button("Exit");
private static final int buttonHeight = 25;
private static final int buttonWidth = 100;
private static final int screenwidth = 350;
private static final int screenHeight = 150;
private Scene theScene;
private Stage primaryStage;
private VBox root = new VBox(30);
private HBox top = new HBox(10);
public void start(Stage stage) {
primaryStage = stage;
setButtonSizes();
root.setPrefSize(screenwidth, screenHeight);
root.resize(screenwidth, screenHeight);
root.setAlignment(Pos.CENTER);
root.getChildren().addAll(top, exitButton);
top.getChildren().addAll(gameButton, mapEditorButton);
top.setAlignment(Pos.CENTER);
theScene = new Scene(root);
primaryStage.setTitle("Menu Selector");
primaryStage.setWidth(screenwidth);
primaryStage.setHeight(screenHeight);
primaryStage.setResizable(false);
primaryStage.initStyle(StageStyle.UNIFIED);
primaryStage.setScene(theScene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void setButtonSizes() {
gameButton.setMinSize(buttonWidth, buttonHeight);
gameButton.setMaxSize(buttonWidth, buttonHeight);
gameButton.setPrefSize(buttonWidth, buttonHeight);
mapEditorButton.setMinSize(buttonWidth, buttonHeight);
mapEditorButton.setMaxSize(buttonWidth, buttonHeight);
mapEditorButton.setPrefSize(buttonWidth, buttonHeight);
exitButton.setMinSize(buttonWidth, buttonHeight);
exitButton.setMaxSize(buttonWidth, buttonHeight);
exitButton.setPrefSize(buttonWidth, buttonHeight);
}
}
Here's an image of the problem:
After commenting out lines of your code to try to discover what was causing the behavior, I found that it was this line...
primaryStage.initStyle(StageStyle.UNIFIED);
Then I looked at the javadoc for class StageStyle. It states...
Specifies the style for this stage. This must be done prior to making the stage visible. The style is one of: StageStyle.DECORATED, StageStyle.UNDECORATED, StageStyle.TRANSPARENT, or StageStyle.UTILITY
Hmm, UNIFIED isn't mentioned there. Nonetheless, your code compiles and runs without error, so UNIFIED must be a valid value. So then I looked at the javadoc for UNIFIED and read this...
This is a conditional feature, to check if it is supported see javafx.application.Platform.isSupported
So running this method...
Platform.isSupported(ConditionalFeature.UNIFIED_WINDOW)
returned true on my Windows 10 64-bit machine running [Oracle] JDK 13.0.1
Despite this, using StageStyle.UNIFIED causes a problem. My guess is it may be a bug. In any case, if you remove this line (or comment it out), you will see your buttons.
Related
In JavaFx I'm currently trying to change the height of
primaryStage via binding.
primaryStage.setScene(scene);
primaryStage.setHeight(400.0);
primaryStage.widthProperty().bindBidirectional(textField.textProperty());
It's just a homework problem, not meaningful.
Unfortunately primaryStage is readOnlyDoubleProperty. May I change this settings to gain write-permissions?
I know, there is the possibility to change the window size via EventHandler, but I would like to change the window size on the fly through the TextField with bindings.
So any newly entered number enlarges the window.
Any ideas?
It's definitely possible and I hope there is a better way and no one should ever use this code ever but this is what I managed to make work
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
//Allows for only numeric input
textField.setTextFormatter(new TextFormatter<>(change -> {
if (change.getText().matches("[0-9]*"))
return change;
else
return null;
}));
primaryStage.setScene(new Scene(textField));
primaryStage.setHeight(200.0);
//Allows Program to start without error
primaryStage.setMaxWidth(200);
//Binds min and max to ensure stage width change due to only 1 possible size
primaryStage.minWidthProperty().bind(primaryStage.maxWidthProperty());
//Bind textfield to width
textField.textProperty().bindBidirectional(primaryStage.maxWidthProperty(), new NumberStringConverter());
primaryStage.show();
}
}
I am working on a GUI, where I need to move objects in exact part of GUI. Main windows is split into few parts and I want to be able to move objects in one of these parts.
I tried to write simple code, where I just move simple rectangle in root Group, to understand how transition translation works. Everything went well. When I wanted to do the exact same thing in my GUI (in one of nested Group), it didn't work.
It shows, that new translations were set to object, but object didn't move at all.
I did the exact same thing, except Groupt isn't root.
Code:
/* imports, main() */
public void start(Stage primaryStage) throws Exception {
Button tmpButton = new Button("Just fill the space");
Rectangle rect = new Rectangle(0, 0, 20, 20);
rect.setOnMousePressed(mousePressedEvent);
rect.setOnMouseDragged(mouseDraggedEvent);
Group movablePlace = new Group();
movablePlace.getChildren().add(rect);
VBox root = new Root();
root.geChildren().addAll(tmpButton, movablePlace);
primaryStage.setScene(new Scene(root, 500, 400));
primaryStage.show();
}
EventHandler<MouseEvent> mousePressedEvent = new EventHandler<MouseEvent>() {
/* getting coordinates works fine */
};
EventHandler<MouseEvent> mouseDraggedEvent = new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
/* actualize new coordinates and offset - works fine */
((Rectangle)event.getSource).setTranslateX(newTranslationX);
((Rectangle)event.getSource).setTranslateY(newTranslationY);
/* translations of rectangle are set correctly, but it doesn't move */
}
};
Can someone clear up to me, what I did wrong or misunderstood?
Thank you!
I have a PopOver with a TextField with a strange behavior, this PopOver it's owned by other TextField because when I type the word 'Fernández' all keys are processed by the internal TextField except when I type a stressed vowel like 'á' that it's collected by the external TextField.
PopOver owned by TextField
But when i show the same PopOver owned by a button works fine and the internal TextField receives the letter 'á'
PopOver owned by Button
I would appreciate any help to solve it.
EDIT: Here you can see an example code to show this.
public class PopOverTest extends Application {
#Override
public void start(Stage primaryStage) {
CustomTextField externo = new CustomTextField();
ImageView imgView = new ImageView(new Image("test/image.png"));
externo.setLeft(imgView);
CustomTextField interno = new CustomTextField();
PopOver popOver = new PopOver();
popOver.setContentNode(interno);
popOver.stArrowLocation(PopOver.ArrowLocation.TOP_LEFT);
imgView.setOnMouseClicked(e -> {
popOver.show(imgView);
});
StackPane root = new StackPane();
root.getChildren().add(externo);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I found a solution for this.
Changing the external Textfield EventDispatcher and the problem is resolved
EventDispatcher dispatcher = externalTextField.getEventDispatcher();
then on focus of the internal TextField
externalTextField.setEventDispatcher(interntalTextField.getEventDispatcher());
and when lost focus restore the EventDispatcher
externalTextField.setEventDispatcher(dispatcher);
That's all folks!
A few days ago I started studying JavaFX, and came across the desire to perform 2 experiments. Firstly, I would like to know if it is possible to put an animated background behind an user interface. I've succeeded in creating an animated background, and now I'm having great difficulties to position some controls in the middle of my interface.
I'd like to introduce you 2 pictures of my program. The first demonstrates the undesirable result that I'm getting:
I believe this is my nodes tree:
This is the code of my application:
public class AnimatedBackground extends Application
{
// #########################################################################################################
// MAIN
// #########################################################################################################
public static void main(String[] args)
{
Application.launch(args);
}
// #########################################################################################################
// INSTÂNCIAS
// #########################################################################################################
private Group root;
private Group grp_hexagons;
private Rectangle rect_background;
private Scene cenario;
// UI
private VBox lay_box_controls;
private Label lab_test;
private TextArea texA_test;
private Button bot_test;
// #########################################################################################################
// INÍCIO FX
// #########################################################################################################
#Override public void start(Stage stage) throws Exception
{
this.confFX();
cenario = new Scene(this.root , 640 , 480);
this.rect_background.widthProperty().bind(this.cenario.widthProperty());
this.rect_background.heightProperty().bind(this.cenario.heightProperty());
stage.setScene(cenario);
stage.setTitle("Meu programa JavaFX - R.D.S.");
stage.show();
}
protected void confFX()
{
this.root = new Group();
this.grp_hexagons = new Group();
// Initiate the circles and all animation stuff.
for(int cont = 0 ; cont < 15 ; cont++)
{
Circle circle = new Circle();
circle.setFill(Color.WHITE);
circle.setEffect(new GaussianBlur(Math.random() * 8 + 2));
circle.setOpacity(Math.random());
circle.setRadius(20);
this.grp_hexagons.getChildren().add(circle);
double randScale = (Math.random() * 4) + 1;
KeyValue kValueX = new KeyValue(circle.scaleXProperty() , randScale);
KeyValue kValueY = new KeyValue(circle.scaleYProperty() , randScale);
KeyFrame kFrame = new KeyFrame(Duration.millis(5000 + (Math.random() * 5000)) , kValueX , kValueY);
Timeline linhaT = new Timeline();
linhaT.getKeyFrames().add(kFrame);
linhaT.setAutoReverse(true);
linhaT.setCycleCount(Animation.INDEFINITE);
linhaT.play();
}
this.rect_background = new Rectangle();
this.root.getChildren().add(this.rect_background);
this.root.getChildren().add(this.grp_hexagons);
// UI
this.lay_box_controls = new VBox();
this.lay_box_controls.setSpacing(20);
this.lay_box_controls.setAlignment(Pos.CENTER);
this.bot_test = new Button("CHANGE POSITIONS");
this.bot_test.setAlignment(Pos.CENTER);
this.bot_test.setOnAction(new EventHandler<ActionEvent>()
{
#Override public void handle(ActionEvent e)
{
for(Node hexagono : grp_hexagons.getChildren())
{
hexagono.setTranslateX(Math.random() * cenario.getWidth());
hexagono.setTranslateY(Math.random() * cenario.getHeight());
}
}
});
this.texA_test = new TextArea();
this.texA_test.setText("This is just a test.");
this.lab_test = new Label("This is just a label.");
this.lab_test.setTextFill(Color.WHITE);
this.lab_test.setFont(new Font(32));
this.lay_box_controls.getChildren().add(this.lab_test);
this.lay_box_controls.getChildren().add(this.texA_test);
this.lay_box_controls.getChildren().add(this.bot_test);
this.root.getChildren().add(this.lay_box_controls);
}
}
I've tried to make the use of a StackPane as the root of my scene graph, but also found an undesired result. Despite the controls have stayed in the center of the window, the circles begin to move in as they grow and shrink, making it appear that everything is weird.
The second thing I would like to know is if it is possible to customize the controls so they perform some animation when some event happens. Although we can change the appearance of controls using CSS, it's harder to create something complex. For example, when a control changes its appearance due to a change of state, the transition state change is not made in an animated way, but in an abrupt and static way. Is there a way to animate, for example, a button between its states? This would be done using the JavaFX API? Or would that be using CSS? Or would not be possible in any way?
Thank you for your attention.
after much struggle, I and some users of the Oracle community could resolve this issue. I see no need to repeat here all the resolution made by us, so I'll post the link so you can access the solution of the problem. I hope this benefits us all. Thanks for your attention anyway.
https://community.oracle.com/thread/2620500
I can't figure out how to create a modal window in JavaFX. Basically I have file chooser and I want to ask the user a question when they select a file. I need this information in order to parse the file, so the execution needs to wait for the answer.
I've seen this question but I've not been able to find out how to implement this behavior.
In my opinion this is not good solution, because parent window is all time active.
For example if You want open window as modal after click button...
private void clickShow(ActionEvent event) {
Stage stage = new Stage();
Parent root = FXMLLoader.load(
YourClassController.class.getResource("YourClass.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(
((Node)event.getSource()).getScene().getWindow() );
stage.show();
}
Now Your new window is REALY modal - parent is block.
also You can use
Modality.APPLICATION_MODAL
Here is link to a solution I created earlier for modal dialogs in JavaFX 2.1
The solution creates a modal stage on top of the current stage and takes action on the dialog results via event handlers for the dialog controls.
JavaFX 8+
The prior linked solution uses a dated event handler approach to take action after a dialog was dismissed. That approach was valid for pre-JavaFX 2.2 implementations. For JavaFX 8+ there is no need for event handers, instead, use the new Stage showAndWait() method. For example:
Stage dialog = new Stage();
// populate dialog with controls.
...
dialog.initOwner(parentStage);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.showAndWait();
// process result of dialog operation.
...
Note that, in order for things to work as expected, it is important to initialize the owner of the Stage and to initialize the modality of the Stage to either WINDOW_MODAL or APPLICATION_MODAL.
There are some high quality standard UI dialogs in JavaFX 8 and ControlsFX, if they fit your requirements, I advise using those rather than developing your own. Those in-built JavaFX Dialog and Alert classes also have initOwner and initModality and showAndWait methods, so that you can set the modality for them as you wish (note that, by default, the in-built dialogs are application modal).
You can create application like my sample. This is only single file JavaFX application.
public class JavaFXApplication1 extends Application {
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Stage stage;
stage = new Stage();
final SwingNode swingNode = new SwingNode();
createSwingContent(swingNode);
StackPane pane = new StackPane();
pane.getChildren().add(swingNode);
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("Swing in JavaFX");
stage.setScene(new Scene(pane, 250, 150));
stage.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
private void createSwingContent(final SwingNode swingNode) {
SwingUtilities.invokeLater(() -> {
try {
Path currentRelativePath = Paths.get("");
String s = currentRelativePath.toAbsolutePath().toString();
JasperDesign jasperDesign = JRXmlLoader.load(s + "/src/reports/report1.jrxml");
String query = "SELECT * FROM `accounttype`";
JRDesignQuery jrquery = new JRDesignQuery();
jrquery.setText(query);
jasperDesign.setQuery(jrquery);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint JasperPrint = JasperFillManager.fillReport(jasperReport, null, c);
//JRViewer viewer = new JRViewer(JasperPrint);
swingNode.setContent(new JRViewer(JasperPrint));
} catch (JRException ex) {
Logger.getLogger(AccountTypeController.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}