I have added a custom toolbar (where my window actions are placed) to my application. So far everything works well. Related to the window handling I'm searching for a possibility to handle the "fullscreen got closed" event. Scenario:
App starts in windowed mode -> user clicks on (custom) toolbar button to get into fullscreen. The Toolbar will now be set its visibility to false. The users now exits fullscreen mode via button (native macOS Button to exit fullscreen) --> I need now to react for this (to set the toolbar to visible again) but cannot find a way how to do it.
main.java
MainController mc = new MainController();
Parent root = FXMLLoader.load(getClass().getResource("welcome-view.fxml"));
stage.initStyle(StageStyle.TRANSPARENT);
mc.doSwitchScenes(stage, root);
stage.show();
MainController.java
...
private String title = "Project Apollo";
private Color fillColor = TRANSPARENT;
private int minWidth = 800;
private int minHeight = 600;
...
public void btnMinimize(MouseEvent mouseEvent) {
Stage stage = (Stage)((Circle)mouseEvent.getSource()).getScene().getWindow();
// is stage minimizable into task bar. (true | false)
stage.setIconified(true);
};
public void btnCloseApp(MouseEvent mouseEvent) {
Platform.exit();
System.exit(0);
}
public void btnFullscreen(MouseEvent mouseEvent) {
Stage stage = (Stage)((Circle)mouseEvent.getSource()).getScene().getWindow();
stage.setFullScreen(true);
Scene actualScene = ((Node)mouseEvent.getSource()).getScene();
Parent hbc = (Parent) actualScene.lookup("#headerBarContainer");
if(hbc != null){
hbc.setVisible(false);
}
System.out.println("clicked FS");
}
...
The point is that at least on MacOS the window has its native os control to exit fullscreen - is it possible to target this event or at least the change of the stage size maybe?
Listen to stage.fullScreenProperty() and respond to changes:
stage.fullScreenProperty().addListener((ChangeListener) (obs,oldValue,newValue) ->
{/*TODO respond to changes in full screen */;});
Related
I'm making an application with JavaFX and Scene Builder. I have a method that make animation of Anchor Pane. Translate transition and rotate transition.
When I press "1" on keyboard that method is called.
The problem is when I press on key 1 so fast animation works
incorrectly. It seems when I press too fast on a key animation of
Anchor Pane is shifted.
How can I prohibit key press during animation or how can I set a delay between key presses?
Controller:
#FXML private AnchorPane randomCard;
#FXML public void initialize(URL location, ResourceBundle resources) {
//key commands
mainAnchor.setOnKeyPressed(event -> {
switch (event.getCode()) {
case DIGIT1:
showRandomCard();
break;
}
});
//show random card in main window
private void showRandomCard(){
TranslateTransition tt = new TranslateTransition();
tt.setDuration(Duration.millis(400));
tt.setNode(randomCard);
tt.setFromY(950);
tt.setFromX(-600);
tt.setToY(0);
tt.setToX(0);
RotateTransition rt = new RotateTransition(Duration.millis(500), randomCard);
rt.setByAngle(360);
rt.setRate(1);
rt.setCycleCount(1);
tt.play();
rt.play();
}
Just use a boolean field and use the onFinished handler of the animation that finishes last to reset it to a state that allows execution of the logic for creating/starting the animations:
private boolean animationRunning = false;
private void showRandomCard(){
if (!animationRunning) {
animationRunning = true;
TranslateTransition tt = new TranslateTransition();
tt.setDuration(Duration.millis(400));
tt.setNode(randomCard);
tt.setFromY(950);
tt.setFromX(-600);
tt.setToY(0);
tt.setToX(0);
RotateTransition rt = new RotateTransition(Duration.millis(500), randomCard);
rt.setByAngle(360);
rt.setRate(1);
rt.setCycleCount(1);
rt.setOnFinished(evt -> animationRunning = false);
tt.play();
rt.play();
}
}
I'm trying to figure out if blocking the GUI is possible. Basically, my application (which is using the NetBeans Platform and JavaFX) has a connection to the server.
Independently on which screen the user is seeing, if the application loses the connection to the server I'd like to block everything (the users cannot open any new windows or click anywhere) until the application is connected again (it doesn't matter if that needs 5 minutes or 5 hours). Nevertheless, on the top of everything should appear an alert message (always on the top).
The java class which is listening to the server connection doesn't have any reference to JavaFX containers. That's what I actually have:
public class StatusConnectionObserver implements ConnectionObserver {
private final Led led;
private final Label label;
public StatusConnectionObserver(Led led, Label label) {
this.led = led;
this.label = label;
}
#Override
public void setConnected(boolean connected) {
if (connected) {
Platform.runLater(() -> {
led.setLedColor(Color.rgb(59, 249, 53));
label.setText("Connected");
});
} else {
Platform.runLater(() -> {
led.setLedColor(Color.RED);
label.setText("Disconnected");
});
}
}
}
and:
public class ConnectionComponent {
private Led led;
private Label label;
private HBox container;
private VBox ledContainer;
public ConnectionComponent() {
initGraphics();
}
public Parent getView() {
return this.container;
}
public void initGraphics() {
//Here I set up the elements (label and Led) inside the container
}
Which is called here:
#ServiceProvider(service = StatusLineElementProvider.class)
public class ConnectionIndicator implements StatusLineElementProvider {
#Override
public Component getStatusLineElement() {
JFXPanel fxPanel = new JFXPanel();
Platform.setImplicitExit(false);
new JavaFXUIThread().runOnUiToolkitThread(() -> {
Scene scene = new Scene(new ConnectionComponent().getView());
scene.getStylesheets().add(FXTheme.getDefault().getStylesheet());
fxPanel.setScene(scene);
});
return fxPanel;
}
}
The idea is to showing something on the top (even a simple text message) and, in the meanwhile, make the application in background more opaque.
You need a modal Dialog. Create such a dialog and show it when your connection goes down. Then use a Thread which periodically checks if your connection is back up. The time the connection comes alive kill the dialog. Since the dialog is modal it means that you can do nothing to the UI until it is resolved. See this.
Use Alert or Dialog components. You can style them by CSS or add custom content. Try this simplest solution:
Alert a = new Alert(Alert.AlertType.ERROR, "Connection error");
public void createAlert() {
a.getDialogPane().getButtonTypes().clear();
a.initModality(Modality.APPLICATION_MODAL);
//*************** EDIT ***************
a.initStyle(StageStyle.UNDECORATED);
a.initOwner(label.getScene().getWindow());
//************************************
}
#Override
public void setConnected(boolean connected) {
if (connected) {
Platform.runLater(() -> {
label.setText("Connected");
a.show();
});
} else {
Platform.runLater(() -> {
label.setText("Disconnected");
a.close();
});
}
}
You can also add additional Pane on top of your entire Scene:
StackPane root = new StackPane();
root.getChildren().addAll(applicationContent);
Pane p = new Pane();
p.setStyle("-fx-background-color: rgba(31,31,31,0.6);");
//add Pane to root when disconnected
//root.getChildren().add(p);
Scene scene = new Scene(root, 300, 250);
I have tried searching for this many times with no luck. I am writing a software where I want the user to input their resolution before moving on to the main UI, as the main UI will change size based on the resolution given. How would I open a popup window without a button event handler and then proceed to the main application?
You can just open the popup window in your start() method:
public class MyApp extends Application {
#Override
public void start(Stage primaryStage) {
// make sure application doesn't exit when we close the dialog window:
Platform.setImplicitExit(false);
Stage popup = new Stage();
TextField resolutionField = new TextField();
// ... populate popup, etc...
popup.setOnHidden(() -> {
int resolution = Integer.parseInt(resolutionField.getText());
// now create main UI...
primaryStage.show();
});
popup.show();
}
}
I designed an undecorated stage and I want to move it around the screen clicking in the stage and dragging it.
My controller handles two event: mousePressendHandler and mouseDraggedHandler.
The first event is fired when the user click with the mouse on the stage. In this method I store the coordinates relatives to the stage of the mouse pointer.
The second event is fired when the user moves the mouse without relasing the button. Than I move the stage subtracting the coordinates of the mouse pointer in the screen and setting the result to the stage.
Examples:
#FXML
public void mousePressedHandler(MouseEvent me) {
dragAnchorX = me.getScreenX() - stage.getX();
dragAnchorY = me.getScreenY() - stage.getY();
}
#FXML
public void mouseDraggedHandler(MouseEvent me) {
double stageX = me.getScreenX() - dragAnchorX;
double stageY = me.getScreenY() - dragAnchorY;
stage.setX(stageX);
stage.setY(stageY);
}
I want to avoid the stage to go out of the screen, so I modified the second method:
#FXML
public void mouseDraggedHandler(MouseEvent me) {
double stageX = me.getScreenX() - dragAnchorX;
if (stageX > 0) {
stage.setX(stageX);
}
double stageY = me.getScreenY() - dragAnchorY;
if (stageY > 0) {
stage.setY(stageY);
}
}
But if I move the mouse too fast, the mouse pointer is moved in the scene and so the result is not correct.
where am I wrong?
I have the last version of java(8_40) and javaFX.
I have a checkbox with 10 items.
I compile and run the program.
If i move the program window to the bottom of the monitor screen, the dropdown list go out from the monitor screen. It is impossible to click the items out the screen.
Instead, if I try to do the same layout with scenes builder 2.0, click on preview, the dropdown is moved automatically up for not exit the screen.
Why with scenes builder is properly displayed, instead with "compile and run" not?
The problem is the same that if I do graphics via code is that if I use the files fxml.
I put below a small program example that gives me this error:
Component CustomControl.java
public class CustomControl extends VBox {
public CustomControl() {
ComboBox<String> asd = new ComboBox<String>();
ObservableList<String> data = FXCollections.observableArrayList();
asd.setItems(data);
data.add("1");
data.add("2");
data.add("3");
data.add("4");
data.add("5");
data.add("6");
data.add("7");
data.add("8");
data.add("9");
data.add("10");
getChildren().add(asd);
}
}
Main.java
public class CustomControlExample extends Application {
public static void main(String[] args) {
launch(args);
}
String address = " ";
#Override public void start(Stage stage) {
stage.setTitle("ComboBoxSample");
Scene scene = new Scene(new CustomControl());
stage.setScene(scene);
stage.show();
}
}
EDIT:
Screen-shot on the left the pop-up go out of the screen border (eclipse)
While, on the right the pop-up is automatically moved (Scene builder)
See this image:
It is easy to solve, just change the visible row count.