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();
}
}
Related
my problem is the following:
I have a JavaFX application with a Button called "bindB";
Button bindB = new Button("None");
bindB.setOnAction(event -> {
bindB.setText("...");
BindKey.bindKey(scene, bindB);
});
with the text "None". Is this button pressed, his text first changes to "..."
and by then calling the method "BindKey.bindKey();", the text will change to the
name of the key, the user is pressing on his keyboard.
This is the code of the method "BindKey.bindKey();":
public static void bindKey(Scene scene, Button bindB){
scene.setOnKeyPressed(event -> {
bindB.setText(String.valueOf(event.getCode()));
});
}
As you can see, in the args of the method we give the button "bindB", so that the method knows
what button to change the name of, aswell as the current scene.
This code does work, but the problem is, that even after the button was
pressed, and its text has already be changed, the text still changes to the name of different
keys if you press them afterwards WITHOUT having to press the button a second time.
I thought that you had to end the "setOnAction" event by calling
event.consume();
but that didnt work...
So how do I make the buttons text only change, if the button has actually been pressed a second or third time?
Otherwise, the task which the button performs is toggled by EVERY key because technically
every key is the toggle key as the task reads the name of the button to know what key is for toggling.
Full code example:
Main class:
public class Main {
// Initialize GUI
public static void main(String[] args) {
GUI gui = new GUI();
gui.run();
}
}
GUI class:
public class GUI extends Application {
public void run() {
launch();
}
#Override
public void start(Stage window) throws Exception {
// When closing Window
window.setOnCloseRequest(event -> {
exitApplication(window);
});
// GridPane
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10,10));
grid.setVgap(15);
grid.setHgap(30);
// Scene
Scene scene = new Scene(grid, 200, 200);
window.setScene(scene);
// Bind Button
Button bindB = new Button("None");
GridPane.setConstraints(bindB, 1, 1);
bindB.setOnAction(event -> {
bindB.setText("...");
BindKey.bindKey(scene, bindB);
});
// Add to Grid
grid.getChildren().addAll(bindB);
// Show Window
window.show();
}
// Provide a clean exit
private void exitApplication(Stage window){
window.close();
Platform.exit();
System.exit(0);
}
}
BindKey class:
public class BindKey {
// Changes Buttons text
public static void bindKey(Scene scene, Button bindB){
scene.setOnKeyPressed(event -> {
bindB.setText(String.valueOf(event.getCode()));
});
}
}
I am not to 100% sure if this is the problem, but I think the only thing you have to do is the following:
scene.setOnKeyPressed(event -> {
bindB.setText(String.valueOf(event.getCode()));
scene.setOnKeyPressed(null);
});
}
You just have to remove the Key-Listener from the scene after you set the text. Because otherwise it will listen for keys the entire time.
On my app, there is a primary window and a secondary for some changes. When the user want to close the app (= primary window) i want to ask from the user the confirmation for closing the secondary window of the changes to avoid being lost of changes.
This code is on my main class.
My problem is that i can't check from my main class if the secondary window is open or not.
Notice: The secondary window is being created on my maincontroller class.
Thanks!
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("style.css").toExternalForm());
primaryStage.getIcons().add(new Image("image.png"));
primaryStage.setTitle("Κάβα ποτών");
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent event) {
event.consume();
closing();
}
});
}
public void closing() {
//if(the secondary window is closed)
//Platform.exit();
//else
//ask confirmation with confirm alert
}
public static void main(String[] args) {
launch(args);
}
}
Use isShowing method do determine if SecondaryStage is opened.
To use it, you should assign SecondaryStage to a variable when you create the stage and provide access to it by making it public or providing getters.
And this is how to access controller from your Main class.
Hope it helps.
I am building an alarm and it consists of two parts
an animated button created in javafx class and the engine which is created normally
what I need is whenever user press the animated button that closes the button and fire up the engine then after the engine is closed there will be some time then animated button appears again and so on
so I used ::
notify_me.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new engine();
Platform.exit();
}
});
and in order to repeat this process I used
Timer t = new Timer(0,new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
while(true){
javafx.launch(javafx.class);
//some extra code goes here including sleep for
//some time and check for engine window state
}
}
});
t.start();
but I am facing two problems:
some extra code isn`t implemented until platform is exited,
launch() cannot be called more than once
so how can I achieve that without using threads ?? thanks
You probably won't get around using Threads. I'd recommend not shutting down the fx application thread however. Just close all windows and show (some of) them again after the delay:
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Hide me 5 sec");
// prevent automatic exit of application when last window is closed
Platform.setImplicitExit(false);
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
// timer should be a daemon (-> not prevent jvm shutdown)
Timer timer = new Timer(true);
btn.setOnAction((ActionEvent event) -> {
timer.schedule(new TimerTask() {
#Override
public void run() {
// make window reappear (needs to happen on the application thread)
Platform.runLater(primaryStage::show);
}
}, 5000l);
// hide window
primaryStage.close();
});
// allow exiting the application by clicking the X
primaryStage.setOnCloseRequest(evt -> Platform.exit());
primaryStage.show();
}
I have a Webview (JavaFX 8) that load an article from Wikipedia.
I put a refresh button to allow a refresh, basically, it does another call to the load method of the webEngine of the WebView with the same URL. But about 50% of the time the article is never rendered. In this case, I can right-click on the web view to manually refresh, then it will be rendered successfully.
I tried to look at the LoadWorker state, it always says "SUCCEED"...
Below is a short runnable Test class that demonstrates my point.
public class Test1 extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
final WebView webView = new WebView();
webView.getEngine()
.load("http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard");
Tab tab = new Tab("webView", webView);
TabPane tabPane = new TabPane(tab);
BorderPane borderPane = new BorderPane(tabPane);
Button buttonRefresh = new Button("Refresh");
buttonRefresh.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
webView.getEngine()
.load("http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard");
}
});
borderPane.setBottom(buttonRefresh);
Scene scene = new Scene(borderPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main (String[] args) {
launch(args);
}
}
Am I doing something wrong? Does anyone know where this problem might come from?
EDIT
I added a few lines to bypass the problem, I check the header in the DOM when the state of the loadWorker becomes SUCCESS. If it is empty, I reload. Now it (looks) 100% ok, but still I am very curious why it didn't simply work all the time first.
Some thoughts that may be useful
The link http://fr.wikipedia.org/wiki/Sp%C3%A9cial:Page_au_hasard redirects to a random article (that's why my refresh button can't use webView.getEngine.reload()).
Putting a ChangeListener on the stateProperty of the workLoader to call the reload method of webEngine actually works. Each page is rendered successfully, but already rendered page will also be re-rendered, which is terrible.
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.