I have a Java Swing application. For one of javax.swing.JFrame, I use JFXPanel to embed JavaFX content. In JFXPanel, there is ListView (JFrame => JFXPanel => ListView). Double click on ListView's item, will open new JavaFX browser Window, to load HTML content of it's URL.
Assuming 3 windows:
Window-A: Main application window (Swing).
Window-B: JFrame with JFXPanel (contain's ListView).
Window-C: JavaFX browser window
Once Window-C is open, it always stay on top of any other Windows (Window-A, Window-B, & even Netbean IDE Window). When click on Window-A / Window-B, the Window is actived but always stay behind Window-C. The only way to have complete view on Window-A / Window-B, is to move Window-C away so not to overlap with them.
I tried setting these for Window-C, but with no effect:
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.initModality(Modality.NONE);
The intended behaviour is, whenever Window-A / Window-B / Window-C is clicked, it should stay on top, all the other windows should go behind it.
Any idea how to make this work? Is it a mistake to invoke pure JavaFX Window (Window-C) from Swing application?
Below is my code snippet:
public class StockNews extends JFrame {
private final JFXPanel jfxPanel = new JFXPanel();
Scene scene;
VBox vbox;
java.util.List<FeedItem> messages;
ListView<FeedItem> newsListView;
ObservableList<FeedItem> messages_o;
public StockNews(java.util.List<FeedItem> messages) {
super();
this.messages = messages;
initComponents();
}
private void initComponents() {
Platform.runLater(new Runnable() {
#Override
public void run() {
vbox = new VBox();
scene = new Scene(vbox, 500, 500);
jfxPanel.setScene(scene);
messages_o = FXCollections.observableArrayList (messages);
newsListView = new ListView<>(messages_o);
newsListView.setCellFactory(new Callback<ListView<FeedItem>,
ListCell<FeedItem>>() {
#Override
public ListCell<FeedItem> call(ListView<FeedItem> list) {
// draw single cell
return new DisplaySingleNews();
}
}
);
// Double-clicked ListView's item, will open new JavaFX browser Window, loading HTML content of it's URL
newsListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1) {
FeedItem msg = newsListView.getSelectionModel().getSelectedItem();
URL link = msg.getLink();
Stage stage = new Stage(StageStyle.UTILITY);
// This window always stay on top, even not active. below 2 lines have no effect
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.initModality(Modality.NONE);
WebView browser = new WebView();
stage.setScene(new Scene(browser));
stage.show();
WebEngine webEngine = browser.getEngine();
webEngine.load(link.toString());
}
}
});
vbox.getChildren().addAll(newsListView);
}
});
this.add(jfxPanel, BorderLayout.CENTER);
this.setVisible(true);
}
}
Related
Please see the following code which resembles our use case:
public class SwingEmbedJavaFXExample extends JDialog {
public static void main(String[] args) {
new SwingEmbedJavaFXExample().setJFX();
}
private void setJFX() {
JFXPanel jfxPanel = new JFXPanel();
GridPane grid = createGridWithJavaFXLabelTextFieldAndAButton();
getContentPane().add(jfxPanel);
// initialize FX with JFXPanel which has scene get by gridPane
//embedding jfxPanel to JDialog
Platform.runLater(() -> initFX(jfxPanel, grid));
this.setVisible(true);
}
private void initFX(JFXPanel jfxPanel, GridPane grid) {
Scene scene = new Scene(grid, 300, 275);
jfxPanel.setScene(scene);
}
#NotNull
private GridPane createGridWithJavaFXLabelTextFieldAndAButton() {
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
Label label = new Label("Label: ");
grid.add(label, 0, 1);
TextField textField = new TextField();
textField.setId("PropertyNameTextfield");
textField.setPromptText("promptText");
grid.add(textField, 1, 1);
grid.add(new Button("Hit me!"), 2, 1);
return grid;
}
}
and the problem looks like this IMAGE: Swing Embed Java Fx Problem with Japanese input
Problem is an extra text field with "ENTER" sign with prediction box and prediction box is displaying away from UI
NOTE:
We can not use pure Javafx or pure Swing.
The issue is with Platform.runLater what is happening is that it does not treat JavaFX Runnable differently and that's why it is not in sync with window-text-suggestion-service.
The solution is to use PlatformImpl.runAndWait which actually does not wait to run JavaFX Runnable to run and this causes a good synchronization with the window-text-suggestion service.
Mantra: With JavaFX application always use PlatformImpl.runAndWait instead of Platform.runLater.
I'm currently trying to show a BorderPane inside my AnchorPane (that is also inside my StackPane). I tried to show a new Scene but it show me 2 items in my Windows taskbar, and this is not really what I want.
For exemple, when you open the Preference in Eclipse, u get another window that is not visible in the taskbar.
So basically, the only thing I need is a window that looks like an ImageView, like anchored in the AnchorPane , not resizable and undecorated.
Expected result at end
This is what I tried:
btnDice.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent arg0) {
Scene newScene = new Scene(new BorderPane(), 230, 100);
Stage newWindow = new Stage();
newWindow.setScene(newScene);
newWindow.show();
}
});
Does exists a Java FX component like one that appears from top and goes down, as in the gif below?
I was able to implement a demo based on transition of pane. It looks like:
The weakness of this approach is it doesn't work with a Window which has standard border, buttons, etc. A developer is responsible to build a nice window based on a Pane.
The other problem is resizing of the parent window will resize the sub pane as well. But if you have not resizable parent dialog it should not be a problem.
You are welcome to copy-paste this code and play with it:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
final SubPane subPane = new SubPane();
final TranslateTransition dialogAnimator =
new TranslateTransition(new Duration(500), subPane);
final Button showSubPaneButton = new Button("Slide a sub pane");
showSubPaneButton.setOnAction(event -> {
dialogAnimator.setToY(10);
dialogAnimator.play();
});
subPane.setCloseAction(event -> {
dialogAnimator.setToY(-subPane.getHeight());
dialogAnimator.play();
});
final Pane rootPane = new StackPane(showSubPaneButton, subPane);
rootPane.setPrefWidth(400);
rootPane.setPrefHeight(300);
// By default hide the given pane by moving to the top.
Platform.runLater(() -> subPane.setTranslateY(-subPane.getHeight()));
primaryStage.setTitle("Drop slided dialog");
primaryStage.setScene(new Scene(rootPane));
primaryStage.show();
}
}
class SubPane extends BorderPane {
private final Button dialogButton = new Button("Close");
SubPane() {
final Pane centralPane = new StackPane(dialogButton);
centralPane.setStyle(
"-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.8), 10, 0, 0, 0);-fx-padding: 10;" +
"-fx-background-color: firebrick;-fx-background-radius: 10;");
setCenter(centralPane);
final Pane blankLeftPane = new StackPane();
blankLeftPane.setPrefWidth(100);
setLeft(blankLeftPane);
final Pane blankRightPane = new StackPane();
blankRightPane.setPrefWidth(100);
setRight(blankRightPane);
final Pane blankBottomPane = new StackPane();
blankBottomPane.setPrefHeight(200);
setBottom(blankBottomPane);
}
void setCloseAction(final EventHandler<ActionEvent> closeCallback) {
dialogButton.setOnAction(closeCallback);
}
}
If you're talking about the dialog window, ControlsFX have something similar NotificationPane.
Say, I have a MenuBar with few MenuItem's in it. Each MenuItem is responsible for opening a different Stage window. How can I avoid the "freeze" of the application after clicking one of the above mentioned MenuItem's, when the app is diggesting the code of the new Stage?
You could try something like the following:
new Thread( new Task<Pane>()
{
protected Pane call()
{
Pane gui = .... ;
// this part runs on a background thread
// build or load your GUI here.
return gui;
}
protected void succeeded()
{
// this part will run on fx thread
// add your GUI to the scene here
Pane gui = getValue();
}
}).start();
This question already has an answer here:
JavaFX 2 custom popup pane
(1 answer)
Closed 7 years ago.
I want to create a popup window in a JavaFX application. Give me some ideas.
When I click on Check button it opens the popup window.
How to do it?
You can either create a new Stage, add your controls into it or if you require the POPUP as Dialog box, then you may consider using DialogsFX or ControlsFX(Requires JavaFX8)
For creating a new Stage, you can use the following snippet
#Override
public void start(final Stage primaryStage) {
Button btn = new Button();
btn.setText("Open Dialog");
btn.setOnAction(
new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
VBox dialogVbox = new VBox(20);
dialogVbox.getChildren().add(new Text("This is a Dialog"));
Scene dialogScene = new Scene(dialogVbox, 300, 200);
dialog.setScene(dialogScene);
dialog.show();
}
});
}
If you don't want it to be modal (block other windows), use:
dialog.initModality(Modality.NONE);
The Popup class might be better than the Stage class, depending on what you want. Stage is either modal (you can't click on anything else in your app) or it vanishes if you click elsewhere in your app (because it's a separate window). Popup stays on top but is not modal.
See this Popup Window example.
Take a look at jfxmessagebox (http://en.sourceforge.jp/projects/jfxmessagebox/) if you are looking for very simple dialog popups.
Have you looked into ControlsFx Popover control.
import org.controlsfx.control.PopOver;
import org.controlsfx.control.PopOver.ArrowLocation;
private PopOver item;
final Scene scene = addItemButton.getScene();
final Point2D windowCoord = new Point2D(scene.getWindow()
.getX(), scene.getWindow().getY());
final Point2D sceneCoord = new Point2D(scene.getX(), scene.
getY());
final Point2D nodeCoord = addItemButton.localToScene(0.0,
0.0);
final double clickX = Math.round(windowCoord.getX()
+ sceneCoord.getY() + nodeCoord.getX());
final double clickY = Math.round(windowCoord.getY()
+ sceneCoord.getY() + nodeCoord.getY());
item.setContentNode(addItemScreen);
item.setArrowLocation(ArrowLocation.BOTTOM_LEFT);
item.setCornerRadius(4);
item.setDetachedTitle("Add New Item");
item.show(addItemButton.getParent(), clickX, clickY);
This is only an example but a PopOver sounds like it could accomplish what you want. Check out the documentation for more info.
Important note: ControlsFX will only work on JavaFX 8.0 b118 or later.