Need to show an example in which you show and hide a window in JavaFX 2.
A stage is a window in javafx-2. It provide the hide and show methods:
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class HideShowApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
final Stage window = new Stage();
window.setX(10);
Scene innerScene = new Scene(new Label("inner window"));
window.setScene(innerScene);
HBox root = new HBox(10d);
Button showButton = new Button("show");
showButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
window.show();
}
});
Button hideButton = new Button("hide");
hideButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
window.hide();
}
});
root.getChildren().add(showButton);
root.getChildren().add(hideButton);
stage.setScene(new Scene(root));
stage.show();
}
}
Related
Correction: this works fine, I was being stupid.
I'm trying to disable a JavaFx ChoiceBox. Thought this would work:
shapeList = FXCollections.observableArrayList(CShape.DOT, CShape.RIGHT_GLIDER, CShape.LEFT_GLIDER);
choiceBox = new ChoiceBox<>(shapeList);
choiceBox.setDisable(true);
but it doesn't seem to.
Everything with disable/enable works just fine. You should provide more of your code to find the flaw.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class ChoiceBoxDisableApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
ObservableList<String> items = FXCollections.observableArrayList("one", "two", "three");
ChoiceBox<String> choiceBox = new ChoiceBox<>(items);
Button button = new Button("Disable");
HBox hBox = new HBox(choiceBox, button);
button.setOnMouseClicked(mouseEvent -> {
boolean disable = !choiceBox.isDisabled();
choiceBox.setDisable(disable);
button.setText(disable ? "Enable" : "Disable");
});
stage.setScene(new Scene(hBox));
stage.show();
}
}
I want to know how to clear the webview's content just by clicking on a button with javaFX? So how I can do that? For example: WebView1 contains google web page while clicking on a button should this page clear
You can clear the web view by loading some empty content:
webView.getEngine().loadContent("");
Complete example:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebBrowser extends Application {
private TextField textField ;
private WebView webView ;
#Override
public void start(Stage primaryStage) {
webView = new WebView();
textField = new TextField("https://www.google.com");
textField.setOnAction(e -> load());
load();
Button clearButton = new Button("Clear");
clearButton.setOnAction(e -> webView.getEngine().loadContent(""));
BorderPane root = new BorderPane(webView, new HBox(10, textField, clearButton), null, null, null);
textField.setPadding(new Insets(5));
root.setPadding(new Insets(5));
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private void load() {
String url = makeUrl(textField.getText()) ;
webView.getEngine().load(url);
textField.setText(url);
}
private String makeUrl(String text) {
if (Pattern.matches("[a-zA-Z]+:.+", text)) {
return text ;
} else return "http://"+text ;
}
public static void main(String[] args) {
launch(args);
}
}
What is the correct way to manipulate an Observable collection in a thread, where the collection is already bound to a JavaFX UI-node?
In my sample application, the connection between the collection and the nodes are broken before the thread can do any manipulation; and then they are re-connected after the thread is done. The methods are disconnectObservable() and connectObservable() respectively. Without these two methods, java.lang.IllegalStateException: Not on FX application thread is reported.
Ideally I would like ChangeObservableTask to make its changes to mWords, and then I would call some method to tell mObservable to refresh itself and notify its listeners. Is there such a thing?
Thanks.
package theapp;
import java.util.LinkedList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ThreadObList extends Application {
private final List<String> mWords;
private final ObservableList<String> mObservable;
private ListView mListView;
private Label mCount;
public ThreadObList() {
mWords = new LinkedList<>();
mObservable = FXCollections.observableList(mWords);
mWords.add("park");
}
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Start thread");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ChangeObservableTask task = new ChangeObservableTask();
Thread thd = new Thread(task);
disconnectObservable();
thd.start();
try {
task.get();
System.out.println("ChangeObservableTask exited normally.");
}
catch(Exception ex) {
System.out.println(ex.getMessage());
}
connectObservable();
}
});
mCount = new Label();
mListView = new ListView();
VBox root = new VBox(5, btn, mCount, mListView);
VBox.setVgrow(mListView, Priority.ALWAYS);
connectObservable();
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
private void connectObservable() {
mListView.setItems(mObservable);
mCount.textProperty().bind(Bindings.size(mObservable).asString());
}
private void disconnectObservable() {
mListView.setItems(null);
mCount.textProperty().unbind();
}
private class ChangeObservableTask extends Task<Void> {
#Override
protected Void call() throws Exception {
mObservable.add("dart");
mObservable.add("truck");
mObservable.add("ocean");
return null;
}
}
}
Once the list is used as the contents of the ListView, you can only manipulate it from the FX Application Thread. See the Task javadocs for a bunch of usage examples.
You can create a copy of your ObservableList and pass it to your task, manipulate the copy and return the results. Then update the ObservableList with the results in the onSucceeded handler.
Also note that you shouldn't make any blocking calls, such as task.get() on the FX Application Thread, as you can make the UI unresponsive by doing so.
So you should do something along the lines of:
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
ChangeObservableTask task = new ChangeObservableTask(new ArrayList<>(mObservable));
Thread thd = new Thread(task);
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
mObservable.setAll(task.getValue());
}
});
thd.start();
}
});
and
private class ChangeObservableTask extends Task<List<String>> {
private final List<String> data ;
ChangeObservableTask(List<String> data) {
this.data = data ;
}
#Override
protected List<String> call() throws Exception {
data.add("dart");
data.add("truck");
data.add("ocean");
return data;
}
}
I want to draw red borders around arbitrary javafx.scene.text.Text nodes in my JavaFX scenegraph, for example those in a Button object.
It is easy to retrieve all the Text nodes but not to find where they are in the scene, they have an x and y property which doesn't seem to get set properly but they do not have a width and height.
So far I have tried to add rectangles with a red stroke to a stack pane but the x and y are always wrong and I can't get the size.
One solution is to wrap the text nodes in layout pane (such as an HBox) and use CSS on the layout pane:
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TextBorderExample extends Application {
#Override
public void start(Stage primaryStage) {
final HBox root = new HBox(5);
root.getChildren().addAll(
new Text("This"), new Text("Is"), new Text("A"), createBorderedText("Red"), new Text("Bordered"), new Text("Text")
);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private Node createBorderedText(String text) {
final HBox hbox = new HBox();
hbox.getChildren().add(new Text(text));
hbox.setStyle("-fx-border-color: red;");
return hbox ;
}
public static void main(String[] args) {
launch(args);
}
}
Another way is to use a Rectangle, as follows:
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class TextBorderExample extends Application {
#Override
public void start(Stage primaryStage) {
final HBox root = new HBox(5);
final Text red = new Text("Red");
final Rectangle redBorder = new Rectangle(0, 0, Color.TRANSPARENT);
redBorder.setStroke(Color.RED);
redBorder.setManaged(false);
red.boundsInParentProperty().addListener(new ChangeListener<Bounds>() {
#Override
public void changed(ObservableValue<? extends Bounds> observable,
Bounds oldValue, Bounds newValue) {
redBorder.setLayoutX(red.getBoundsInParent().getMinX());
redBorder.setLayoutY(red.getBoundsInParent().getMinY());
redBorder.setWidth(red.getBoundsInParent().getWidth());
redBorder.setHeight(red.getBoundsInParent().getHeight());
}
});
root.getChildren().addAll(new Text("This"), new Text("Is"), new Text("A"), red, new Text("Bordered"), new Text("Text"));
root.getChildren().add(redBorder);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Is there a way to add MODAL capability to a context menu?
My code is below:
package snippet;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class ContextMenuSample extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage)
{
stage.setTitle("ContextMenuSample");
Scene scene = new Scene(new Group(), 450, 250);
Label toLabel = new Label("To: ");
TextField notification = new TextField();
final ContextMenu contextMenu = new ContextMenu();
contextMenu.setAutoHide(false);
contextMenu.setOnShowing(new EventHandler<WindowEvent>()
{
public void handle(WindowEvent e)
{
System.out.println("showing the context menu");
}
});
contextMenu.setOnShown(new EventHandler<WindowEvent>()
{
public void handle(WindowEvent e)
{
System.out.println("context menu has been shown");
}
});
MenuItem closeItem = new MenuItem("Close");
closeItem.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(ActionEvent e)
{
contextMenu.hide();
}
});
MenuItem colorItem = new MenuItem("Choose", new ColorPicker());
colorItem.setOnAction(new EventHandler<ActionEvent>()
{
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
GridPane contextGridPane = new GridPane();
Pane pane = new Pane();
pane.getChildren().add(contextGridPane);
contextMenu.getItems().addAll(colorItem, deleteItem// , subsystem1,
// radioItem
);
toLabel.setContextMenu(contextMenu);
GridPane grid = new GridPane();
grid.setVgap(4);
grid.setHgap(10);
grid.setPadding(new Insets(5, 5, 5, 5));
grid.add(toLabel, 0, 0);
grid.add(notification, 1, 0);
grid.add(new ColorPicker(), 2, 0);
Group root = (Group) scene.getRoot();
root.getChildren().add(grid);
stage.setScene(scene);
stage.show();
}
}
When the user clicks on the label "To", a context menu appears. I wish to have modal capability for this context menu such that the user is not able to do anything else on the application unless some operation is performed on the context menu. Also, when the context menu is active, the user should not be able to click anywhere else on the application.
Regards,
The easiest solution would be to call another Stage and set its modality with initModality before you show the stage. You probably want to use Modality.APPLICATION_MODEL as far as I understood you.
Here is a small example derived from yours (btw your code was not even runnable, it had errors)
public class ContextMenuSample extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(final Stage stageOne)
{
final Stage stageTwo = new Stage();
stageTwo.initModality(Modality.APPLICATION_MODAL);
final Pane layoutOne = new HBox(10);
Pane layoutTwo = new HBox(10);
Label labelOne = new Label("click");
Label labelTwo = new Label("other click");
labelOne.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stageTwo.show();
}
});
labelTwo.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
stageTwo.close();
}
});
Scene sceneOne = new Scene(layoutOne);
Scene sceneTwo = new Scene(layoutTwo);
layoutOne.getChildren().add(labelOne);
layoutTwo.getChildren().add(labelTwo);
stageOne.setScene(sceneOne);
stageTwo.setScene(sceneTwo);
stageOne.show();
}
}