I created this example of tabs which I want to close after I display confirm dialog and I click Yes button.
public static Tab testconfirmTabClose(Tab tab)
{
tab.setOnClosed(new EventHandler<Event>()
{
#Override
public void handle(Event t)
{
t.consume();
// Dialog Stage init
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
Button btnYes = new Button("Yes");
btnYes.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
dialog.close();
}
});
Button btnNo = new Button("No");
btnNo.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
dialog.close();
}
});
// Layout for the Button
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(btnYes);
hbox.getChildren().add(btnNo);
// Layout for the Label and hBox
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
// Text
Text tc = new Text();
tc.setText("Do you want to quit?");
// Layout for the Button
HBox thbox = new HBox();
thbox.setSpacing(10);
thbox.setPadding(new Insets(20, 20, 20, 90)); // Place the dialog text right
thbox.setAlignment(Pos.CENTER_LEFT);
thbox.getChildren().add(tc);
BorderPane bp = new BorderPane();
bp.setPadding(new Insets(15, 15, 10, 15));
bp.setTop(null);
bp.setLeft(vbox);
bp.setCenter(thbox);
bp.setRight(null);
bp.setBottom(hbox);
Scene scene = new Scene(bp, 500, 140);
dialog.setScene(scene);
dialog.show();
}
});
return tab;
}
I have this issue: When I click on the tab to close it the tab is closed and the confirm dialog is displayed. I cannot "freeze" the tab for the user response. Can you tell me how I can fix this problem?
I'm afraid there is no clean way to do this in JavaFX 2.2. JavaFX 8 will (probably) offer a method called Tab#setOnCloseRequest(...) that will do what you want. For 2.2, the only way I see right now is pulling the source from OpenJDK and creating your own adapted TabPane implementation - sorry :-/.
Related
I need to implement a text editor JavaFX, but I have a problem with the creation of the function of adding the image in the text editing area.
It's exactly that when you click the button it was possible to add an image as the screenshot:
Now, I tried to use WebView where I put TextArea code below:
private WebView view;
private WebEngine engine;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
view = new WebView();
engine = view.getEngine();
engine.loadContent("<body><textarea id='content'></textarea><p id='ding' style='display:none;'></p></body>");
view.setPrefHeight(240);
Button btn = new Button("Click Me!");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
append();
engine.executeScript(
"document.getElementById('ding').innerHTML=document.getElementById('content').value;"
);
}
});
Button btn2 = new Button("Click Me 2!");
btn2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
append();
engine.executeScript(
"document.getElementById('ding').innerHTML=document.getElementById('content').value;"
);
}
});
StackPane root = new StackPane();
root.getChildren().addAll(view, btn, btn2);
Scene scene = new Scene(root, 300, 250);
stage.setScene(scene);
stage.show();
}
private void append() {
Document doc = engine.getDocument();
Element el = doc.getElementById("ding");
String s = el.getTextContent();
s += "<img src='http://bluebuddies.com/gallery/Historical_Smurfs/jpg/Smurfs_Historical_Figure_20506_Abraham_Lincoln.jpg'/>";
el.setTextContent(s);
System.out.println(s);
}
After clicking the button adds to the text in the text area link to the photo but unfortunately TextArea This is not supported and when I wanted to use some html editor problem so that I will not have the opportunity to extract all the text correctly with the formatting.
I tried solutions such as RichTextFX but unfortunately he does not have the ability to add images. The HTML editor also did not meet my expectations because I have entered text later saved to a file, for example type: docx. extract text from this editor with formatting is unfortunately difficult.
Are there any other solutions to create word processing with advanced features in JavaFX?
Ideally it was that it could be solved with normal controls TextArea without the use of WebView.
I was wondering if JavaFX included a way to make the accordion or titled panes horizontal. I can't find anything, but I thought I should ask. Essentially, the end goal is to have a sidebar that can expand to reveal a tree view. Here are pictures of my intention:
Collapsed
Expanded
There is no standard horizontal orientation TitledPane in JavaFX 2.2.
You can create a feature request for one in the JavaFX issue tracker.
Implementing your own horizontal TitledPane is pretty easy.
Here is a demo of a similar thing just using animation on a standard Pane.
Further explanations of the techniques involved are in Sai's blog post: Sliding in JavaFX (It’s all about clipping).
/** Animates a node on and off screen to the left. */
class SideBar extends VBox {
/** #return a control button to hide and show the sidebar */
public Button getControlButton() { return controlButton; }
private final Button controlButton;
/** creates a sidebar containing a vertical alignment of the given nodes */
SideBar(final double expandedWidth, Node... nodes) {
getStyleClass().add("sidebar");
this.setPrefWidth(expandedWidth);
// create a bar to hide and show.
setAlignment(Pos.CENTER);
getChildren().addAll(nodes);
// create a button to hide and show the sidebar.
controlButton = new Button("Collapse");
controlButton.getStyleClass().add("hide-left");
// apply the animations when the button is pressed.
controlButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
// create an animation to hide sidebar.
final Animation hideSidebar = new Transition() {
{ setCycleDuration(Duration.millis(250)); }
protected void interpolate(double frac) {
final double curWidth = expandedWidth * (1.0 - frac);
setPrefWidth(curWidth);
setTranslateX(-expandedWidth + curWidth);
}
};
hideSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
setVisible(false);
controlButton.setText("Show");
controlButton.getStyleClass().remove("hide-left");
controlButton.getStyleClass().add("show-right");
}
});
// create an animation to show a sidebar.
final Animation showSidebar = new Transition() {
{ setCycleDuration(Duration.millis(250)); }
protected void interpolate(double frac) {
final double curWidth = expandedWidth * frac;
setPrefWidth(curWidth);
setTranslateX(-expandedWidth + curWidth);
}
};
showSidebar.onFinishedProperty().set(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
controlButton.setText("Collapse");
controlButton.getStyleClass().add("hide-left");
controlButton.getStyleClass().remove("show-right");
}
});
if (showSidebar.statusProperty().get() == Animation.Status.STOPPED && hideSidebar.statusProperty().get() == Animation.Status.STOPPED) {
if (isVisible()) {
hideSidebar.play();
} else {
setVisible(true);
showSidebar.play();
}
}
}
});
}
}
there you go:
#Override
public void start(Stage stage) throws Exception {
Label label1 = new Label("label 1");
label1.setRotate(90);
TitledPane pane1 = new TitledPane("titled pane 1", label1);
pane1.setAlignment(Pos.CENTER);
Label label2 = new Label("label 2");
label2.setRotate(90);
TitledPane pane2 = new TitledPane("titled pane 2", label2);
pane2.setAlignment(Pos.CENTER);
Accordion accordion = new Accordion();
accordion.setRotate(270);
accordion.getPanes().add(pane1);
accordion.getPanes().add(pane2);
HBox mainPane = new HBox(accordion);
accordion.prefWidthProperty().bind(mainPane.heightProperty());
accordion.prefHeightProperty().bind(mainPane.widthProperty());
stage.setTitle("Horizontal Accordion");
stage.setScene(new Scene(mainPane, 800, 600));
stage.show();
}
Perhaps JavaFx don't provide horizontal TitledPane, but what you can do is rotate your TitledPane to 90 degree and rotate the node which you want to set in it's content to 270 degree, and you are done.
Here is a code sample for you.
TitledPane titledPane = new TitledPane();
BorderPane borderPane = new BorderPane();
borderPane.setCenter(new Label("My Label")); //Or your tree view
borderPane.setRotate(270);
titledPane .setContent(borderPane);
Just add following line to accordion and your done.
accordion.setRotate(270);
I have this code which displays confirmation dialog to exit application.
public class DialogPanels
{
public void initClosemainAppDialog(final Stage primaryStage)
{
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
// Frage - Label
Label label = new Label("Exit from the program");
// Button "Yes"
Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
//primaryStage.close();
//dialog.close();
//Platform.exit();
System.exit(0);
}
});
// Button "No"
Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.show();
dialog.close();
}
});
// Layout for the Button
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(label);
vbox.getChildren().add(hbox);
// Stage
Scene scene = new Scene(vbox);
dialog.setScene(scene);
dialog.show();
}
});
}
}
The problem is that when close the main application the dialog box is displayed and the main stage is hidden. I want to display the dialog box in front of the main stage. Can you help me to correct this?
UPDATE
I tested this code, it's working but when the dialog is displayed the mainstage is not responsible(frozen). How I an make the mainstage responsible when I display dialog?
Consume the closing event and set the owner of the stage if you do not want to see another window when the windows are minimized:
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
// other stuff
}
});
You need to set the proper relationships between primaryStage and dialog stage. Here's a hint to get you going:
...
dialog.initOwner(primaryStage);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.showAndWait();
You can find more information in Oracle's JavaFX 2 JavaDocs.
More example code (edit)
I'm using setOnHiding(..) instead of setOnCloseRequest(..):
stage.setOnHiding(new AskUserIfHeReallyWantsToQuitWindowHandler(stage));
I extracted your code into a seperate event handler class and fixed the issues I mentioned (sorry, I am little short on time right now):
public class AskUserIfHeReallyWantsToQuitWindowHandler implements EventHandler<WindowEvent> {
private final Stage primaryStage;
public AskUserIfHeReallyWantsToQuitWindowHandler(final Stage primaryStage) {
Objects.requireNonNull(primaryStage);
this.primaryStage = primaryStage;
}
#Override
public void handle(final WindowEvent event) {
event.consume();
final Stage dialog = new Stage();
final Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(final ActionEvent event) {
dialog.close();
primaryStage.close();
}
});
// Button "No"
final Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(final ActionEvent event) {
dialog.close();
Platform.runLater(new Runnable() {
#Override
public void run() {
primaryStage.show();
}
});
}
});
// Layout for the Button
final HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(new Label("Do your really want to exit?"));
vbox.getChildren().add(hbox);
// Stage
final Scene scene = new Scene(vbox);
dialog.setScene(scene);
dialog.initOwner(primaryStage);
dialog.initModality(Modality.NONE);
dialog.showAndWait();
}
}
I have this very simple modal dialog:
public class DialogPanels
{
public void initClosemainAppDialog(final Stage primaryStage)
{
primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
#Override
public void handle(WindowEvent event)
{
event.consume(); // Do nothing on close request
// Dialog Stage init
final Stage dialog = new Stage();
// If you want to freeze the background during dialog appearence set Modality.APPLICATION_MODAL
// or to allow clicking on the mainstage components set Modality.NONE
// and set dialog.showAndWait();
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(primaryStage);
// Frage - Label
Label label = new Label("Exit from the program");
// Button "Yes"
Button okBtn = new Button("Yes");
okBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
//primaryStage.close();
//dialog.close();
//Platform.exit();
System.exit(0);
}
});
// Button "No"
Button cancelBtn = new Button("No");
cancelBtn.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.show();
dialog.close();
}
});
// Layout for the Button
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(okBtn);
hbox.getChildren().add(cancelBtn);
// Layout for the Label and hBox
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.getChildren().add(label);
vbox.getChildren().add(hbox);
// Stage
Scene scene = new Scene(vbox, 450, 150, Color.WHITESMOKE);
dialog.setScene(scene);
dialog.show();
}
});
}
}
I want to add image and to make it to look like this:
But I admin that it's too complex for my short knowledge to get the appropriate result. Can you show me how I can split the dialog, add second background and make my code to look the same as this example please?
Have a look at the ControlsFX project, they have some sophisticated dialogs and it's open source, so you can look up how it's done. For example, your dialog looks like this confirmation dialog of ControlsFX:
There is also support for custom dialogs.
€dit:
With the "show Masthead" option enabled it actually looks exactly like it:
I am wanting to add an empty javafx.scene.control.Menu to a MenuBar and have it call a method when it is clicked.
I have tried using menu.setOnShowing(new EventHandler<Event>(){}); with no luck.
Here is what I am currently working with:
public MenuBar createMenuBar() {
MenuBar menuBar = new MenuBar();
Menu file = new Menu("File");
Menu addAccountTab = new Menu("Add Tab");
addAccountTab.setOnShowing(new EventHandler<Event>() {
public void handle(Event e) {
System.out.println("addAccountTab Menu clicked.");
}
});
menuBar.getMenus().add(addAccount);
return menuBar;
}
However, clicking the Menu does not call the onShowing event.
Your Menu needs to contain at least one MenuItem for the event to fire.
public class MenuApplication extends Application {
#Override
public void start(Stage primaryStage) {
MenuBar menuBar = new MenuBar();
Menu file = new Menu("File");
Menu addAccountTab = new Menu("Add Tab");
addAccountTab.setOnShowing(new EventHandler<Event>() {
#Override
public void handle(Event e) {
System.out.println("addAccountTab Menu clicked.");
}
});
MenuItem NewMenuItem = new MenuItem("New");
addAccountTab.getItems().add(NewMenuItem);
menuBar.getMenus().addAll(file, addAccountTab);
StackPane root = new StackPane();
root.getChildren().add(menuBar);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The output I get is shown below:
Although the API suggests otherwise, the onShowing event doesn't get called when there are no MenuItems in the Menu or when they are all hidden.
I was able to solve the issue by using Menu's hide() method inside of the onShown event like this.
public MenuBar createMenuBar() {
MenuBar menuBar = new MenuBar();
Menu addAccount = MenuBuilder.create()
.onShown(new EventHandler<Event>() {
public void handle(Event e) {
((Menu)e.getSource()).hide();
System.out.println("addAccount Clicked");
}
}).items(new MenuItem())
.text("Add Account").build();
menuBar.getMenus().addAll(addAccount);
return menuBar;
}