I've got a working example for defining a ContextMenu on a Pane in JavaFX FXML, but am not sure it is optimal. Currently, only JavaFX standard controls (e.g. Button, TextField) define a property for specifying a popup ContextMenu. Yet I wanted to have a popup menu appear anywhere in a Pane, in my case a VBox.
I took the approach of extending VBox to support a context menu. It is a 'clunky' solution but works. Is there a better approach? Am I missing some fundamental concept?
Here is my solution...
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import custommenu.view.ContextMenuPane?>
<AnchorPane xmlns:fx="http://javafx.com/fxml" fx:controller="custommenu.controller.CustomMenuController">
<children>
<VBox fx:id="vbox" onContextMenuRequested="#showMenu"
onMousePressed="#hideMenu" prefHeight="200" prefWidth="200">
</VBox>
<ContextMenuPane>
<contextMenu>
<ContextMenu fx:id="menu">
<items>
<MenuItem text="add" onAction="#add" />
</items>
</ContextMenu>
</contextMenu>
</ContextMenuPane>
</children>
</AnchorPane>
CustomMenuPane...
package custommenu.view;
import javafx.scene.control.ContextMenu;
import javafx.scene.layout.Pane;
public class ContextMenuPane extends Pane {
private ContextMenu contextMenu;
public void setContextMenu(ContextMenu contextMenu) {
this.contextMenu = contextMenu;
}
public ContextMenu getContextMenu() {
return contextMenu;
}
}
Controller...
package custommenu.controller;
import javafx.fxml.FXML;
import javafx.scene.control.ContextMenu;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.layout.VBox;
public class CustomMenuController {
#FXML private VBox vbox;
#FXML private ContextMenu menu;
#FXML public void add() {
System.out.println("add");
}
#FXML
public void showMenu(ContextMenuEvent event) {
System.out.println("showMenu");
menu.show(vbox, event.getScreenX(), event.getScreenY());
event.consume();
}
#FXML public void hideMenu() {
menu.hide();
}
}
Main App...
package custommenu;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class CustomMenuApplication extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Pane myPane = (Pane)FXMLLoader.load(getClass().getResource("/custommenu/custom_menu_main.fxml"));
Scene scene = new Scene(myPane);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Tried to do it within a Popup? Catch the MouseEvent check for MouseButton.SECONDARY and display your VBox in the Popup.
private void showContextMenu() // showContextMenu(MouseEvent event)
{
Popup popup = new Popup();
VBox content = new VBox();
Button b = new Button("Click Me!");
b.setOnAction(new EventHandler<ActionEvent>() { });
content.getChildren().addAll(b);
popup.getContent().add(content);
popup.setX(0); // or get mouse event x and y
popup.setY(0); // event.getY()
popup.setAutoHide(true);
popup.show(your popup owner);
}
In This example there is button which has context menu when click on left/right it will open the popup when you click on other area except button it will hide the popup context menu
public class Main extends Application{
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Scene scene = new Scene(new Group(), 450, 250);
Button notification = new Button();
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item4 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item5 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item6 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
MenuItem item7 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("About");
}
});
MenuItem item8 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
System.out.println("Preferences");
}
});
final ContextMenu contextMenu = new ContextMenu(item1, item2,item3, item4,item5, item6,item7, item8);
contextMenu.setMaxSize(50, 50);
contextMenu.setOnShowing(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("showing");
}
});
contextMenu.setOnShown(new EventHandler<WindowEvent>() {
public void handle(WindowEvent e) {
System.out.println("shown");
}
});
// contextMenu.hide();
notification.setContextMenu(contextMenu);
GridPane grid = new GridPane();
grid.setVgap(4);
grid.setHgap(10);
grid.setPadding(new Insets(5, 5, 5, 5));
grid.add(new Label("To: "), 0, 0);
grid.add(notification, 1, 0);
Group root = (Group) scene.getRoot();
root.getChildren().add(grid);
stage.setScene(scene);
stage.show();
notification.addEventHandler(MouseEvent.MOUSE_CLICKED, (MouseEvent me)->{
if(me.getButton()==MouseButton.PRIMARY ){
System.out.println("Mouse Left Pressed");
System.out.println(notification.getScaleX());
System.out.println(notification.getScaleY());
System.out.println(me.getScreenX());
System.out.println(me.getScreenY());
contextMenu.show(notification,me.getScreenX(),me.getScreenY());
}else{
contextMenu.hide();
}
});
}
}
Related
I am building a menu (file, view, help, etc.). For ex. in File you have upload and exit (both working fine). In help I have some topics: ACF, ARIMA, HoltWinter, the idea is when you chose one of these a text to be displayed in a GridPane. The problem is when you chose one, it displays its text, but it also locks the whole app and you can do nothing, except close the app.
This is a file chooser and it's working just fine:
MenuItem upload = new MenuItem("Upload");
upload.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.showOpenDialog(primaryStage);
}
});
And here is an event, which is blocking the app:
MenuItem acfH = new MenuItem("ACF");
acfH.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent event){
fr.md.pack.TextClass.acfText.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.acfText.setText(fr.md.pack.StringClass.aboutACF);
grid.add(fr.md.pack.TextClass.acfText,1,10);
}
});
Any suggestions how to solve the issue?
Thanks in advance.
Here is the whole code:
public class MD extends Application {
#Override
public void start(final Stage primaryStage) throws IOException {
primaryStage.setTitle("Crude oil price prediction");
primaryStage.getIcons().add(new Image("file:resources/images/DukeWithHelmet.png"));
final GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 25, 25, 25));
Group root = new Group();
MenuBar menuBar = new MenuBar();
Scene scene = new Scene(root, 500,500, Color.WHITE);
scene.getStylesheets().add(this.getClass().getResource("style.css")
.toExternalForm());
primaryStage.setTitle("Crude oil price predicition");
menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
Menu file = new Menu("File2");
MenuItem upload = new MenuItem("Upload");
upload.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.showOpenDialog(primaryStage);
}
});
MenuItem exit = new MenuItem("Exit");
exit.setMnemonicParsing(true);
exit.setAccelerator(new KeyCodeCombination(KeyCode.X,KeyCombination.CONTROL_DOWN));
exit.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
Platform.exit();
}
});
Menu test = new Menu("Test");
MenuItem arima = new MenuItem ("ARIMA");
arima.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
}
});
MenuItem acf = new MenuItem ("ACF");
acf.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
}
});
MenuItem pacf = new MenuItem ("PACF");
pacf.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
}
});
MenuItem hw = new MenuItem ("HoltWinters");
hw.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
}
});
Menu help = new Menu("Help");
MenuItem arimaH = new MenuItem ("ARIMA");
arimaH.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.arimaText.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.arimaText.setText(fr.md.pack.StringClass.aboutArima);
grid.add(fr.md.pack.TextClass.arimaText, 1, 10);
}
});
MenuItem acfH = new MenuItem("ACF");
acfH.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent event){
fr.md.pack.TextClass.acfText.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.acfText.setText(fr.md.pack.StringClass.aboutACF);
grid.add(fr.md.pack.TextClass.acfText,1,10);
}
});
MenuItem pacfH = new MenuItem ("PACF");
pacfH.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.pacfText.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.pacfText.setText(fr.md.pack.StringClass.aboutPACF);
grid.add(fr.md.pack.TextClass.pacfText, 1, 10);
}
});
MenuItem hwH = new MenuItem ("HoltWinters");
hwH.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.hwText.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.hwText.setText(fr.md.pack.StringClass.aboutHW);
grid.add(fr.md.pack.TextClass.hwText, 1, 10);
}
});
Menu about = new Menu("About");
MenuItem thisS = new MenuItem ("About this software");
thisS.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.textRef.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.aboutSoft.setText(fr.md.pack.StringClass.aboutSofttext);
grid.add(fr.md.pack.TextClass.aboutSoft, 1, 40);
}
});
MenuItem R = new MenuItem ("About R");
R.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.textRef.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.aboutR.setText(fr.md.pack.StringClass.aboutRtext);
grid.add(fr.md.pack.TextClass.aboutR, 1, 40);
}
});
MenuItem RServe = new MenuItem ("About RServe");
RServe.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
fr.md.pack.TextClass.textRef.setFill(Color.FIREBRICK);
fr.md.pack.TextClass.textRef.setText(fr.md.pack.StringClass.aboutText);
grid.add(fr.md.pack.TextClass.textRef, 1, 40);
}
});
file.getItems().addAll(upload,exit);
test.getItems().addAll(arima,acf,pacf,hw);
help.getItems().addAll(arimaH,acfH,pacfH,hwH);
about.getItems().addAll(thisS, R, RServe);
menuBar.getMenus().addAll(file,test,help,about);
root.getChildren().addAll(menuBar,grid);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
The classes used are just containing the strings to display:
package fr.md.pack;
public class StringClass {
final static String aboutText = "Малко информация за RServe.";
final static String aboutRtext = "Малко инфо за Р";
final static String aboutSofttext = "Малко инфо за софта";
final static String aboutArima = "Малко инфо за ARIMA";
final static String aboutACF = "Малко инфо за ACF";
final static String aboutPACF = "Малко инфо за PACF";
final static String aboutHW = "Малко инфо за Holt Winters";
}
Well, I just installed Java 8 and surprise....everything is working just fine. I used till now Java 1.7 update 45 and it was locking my application as soon as I try to use the Action event. With Java 8 it's working but not without some bugs....
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();
}
}
I have a FlowPane which use used as stage for many BorderPane components. I created Context menu for the BorderPane components. I want to add second context menu also for the FlowPane but it turns out that I now have two context menus when I click on BorderPane. I need a way to exclude the second context menu from the BorderPane.
FlowPane flow;
public ScrollPane infrastructurePane()
{
flow = new FlowPane();
flow.setPadding(new Insets(5, 5, 5, 5));
flow.setVgap(15);
flow.setHgap(15);
flow.setAlignment(Pos.CENTER);
ScrollPane scroll = new ScrollPane();
scroll.setStyle("-fx-background-color:transparent;");
Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds();
scroll.setPrefSize(primaryScreenBounds.getWidth(), primaryScreenBounds.getHeight());
scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // Horizontal scroll bar
scroll.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // Vertical scroll bar
scroll.setContent(flow);
scroll.viewportBoundsProperty().addListener(new ChangeListener<Bounds>()
{
#Override
public void changed(ObservableValue<? extends Bounds> ov, Bounds oldBounds, Bounds bounds)
{
flow.setPrefWidth(bounds.getWidth());
flow.setPrefHeight(bounds.getHeight());
}
});
//flow.setPrefWrapLength(170); // preferred width allows for two columns
flow.setStyle("-fx-background-color: white;");
for (int i = 0; i < 28; i++)
{
flow.getChildren().add(generatePanel(flow));
}
scroll = makeTabContextMenu(scroll);
String cssURL = "/com/dx57dc/css/ButtonsDemo.css";
String css = this.getClass().getResource(cssURL).toExternalForm();
flow.getStylesheets().add(css);
return scroll;
}
public BorderPane generatePanel(FlowPane flow)
{
HBox thb = new HBox();
thb.setPadding(new Insets(10, 10, 10, 10));
thb.setStyle("-fx-background-color: #006699;");
HBox bhb = new HBox();
bhb.setPadding(new Insets(10, 10, 10, 10));
bhb.setStyle("-fx-background-color: #B0B0B0;");
DropShadow ds = new DropShadow();
ds.setOffsetY(3.0);
ds.setOffsetX(3.0);
ds.setColor(Color.GRAY);
BorderPane bp = new BorderPane();
bp.setEffect(ds);
bp.setCache(true);
bp.setPrefSize(320, 180);
bp.setMaxSize(320, 180);
bp.setId("app");
bp.setStyle("-fx-background-color: linear-gradient(to bottom, #f2f2f2, #d4d4d4);"
+ " -fx-border: 2px solid; -fx-border-color: white;");
bp.setTop(thb);
bp.setBottom(bhb);
ScrollPane sp = new ScrollPane();
bp = panelContextMenu(bp);
bp = mouseOver(bp);
return bp;
}
public BorderPane mouseOver(final BorderPane bp)
{
bp.setOnMouseEntered(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent t)
{
bp.setStyle("-fx-border: 2px solid; -fx-border-color: black;");
}
});
bp.setOnMouseExited(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent t)
{
bp.setStyle("-fx-border: 2px solid; -fx-border-color: white;");
}
});
bp.setOnMouseClicked(new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent me)
{
if (me.getButton().equals(MouseButton.PRIMARY) && me.getClickCount() % 1 == 0)
{
bp.setPrefSize(480, 280);
bp.setMaxSize(480, 280);
}
if (me.getButton().equals(MouseButton.PRIMARY) && me.getClickCount() % 2 == 0)
{
bp.setPrefSize(320, 180);
bp.setMaxSize(320, 180);
}
}
});
return bp;
}
private ScrollPane makeTabContextMenu(ScrollPane scroll)
{
ContextMenu contextMenu = new ContextMenu();
MenuItem item1 = new MenuItem("New");
item1.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("New");
flow.getChildren().add(generatePanel(flow));
}
});
// Rename
MenuItem rename = new MenuItem("Rename");
final TextField textField = new TextField();
rename.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Rename");
//textField.setText(label.getText());
//tab.setGraphic(textField);
textField.selectAll();
textField.requestFocus();
}
});
textField.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
//label.setText(textField.getText());
//tab.setGraphic(label);
}
});
textField.focusedProperty().addListener(new ChangeListener<Boolean>()
{
#Override
public void changed(ObservableValue<? extends Boolean> observable,
Boolean oldValue, Boolean newValue)
{
if (!newValue)
{
//label.setText(textField.getText());
//tab.setGraphic(label);
}
}
});
// Orientation
Menu tabOrientation = new Menu("Orientation");
// Orientation sub menu - Top, Left, Right, Bottom
MenuItem tabOrientationSubTop = new MenuItem("Top");
tabOrientationSubTop.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
//tabPane.setSide(Side.TOP);
}
});
MenuItem tabOrientationSubLeft = new MenuItem("Left");
tabOrientationSubLeft.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
//tabPane.setSide(Side.LEFT);
}
});
MenuItem tabOrientationSubRight = new MenuItem("Right");
tabOrientationSubRight.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
//tabPane.setSide(Side.RIGHT);
}
});
MenuItem tabOrientationSubBottom = new MenuItem("Bottom");
tabOrientationSubBottom.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
//tabPane.setSide(Side.BOTTOM);
}
});
tabOrientation.getItems().addAll(tabOrientationSubTop, tabOrientationSubLeft, tabOrientationSubRight, tabOrientationSubBottom);
MenuItem item3 = new MenuItem("Close Tab");
item3.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Close Tab");
// Close the Tab and remove it from the TabPane
//tabPane.getTabs().remove(tab);
// If there are no tabs into the TabPane fill all empty space by resizing the near components
// if (tabPane.getTabs().size() == 0)
// {
// ActionTabs.getMainPane().setManaged(false); // Exclude the panel to fill the empty space
// }
}
});
MenuItem item4 = new MenuItem("Close All Panels");
item4.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Close All Panels");
flow.getChildren().clear();
}
});
contextMenu.getItems().addAll(item1, rename, tabOrientation, item3, item4);
scroll.setContextMenu(contextMenu);
return scroll;
}
public BorderPane panelContextMenu(final BorderPane bp)
{
final ContextMenu contextMenu = new ContextMenu();
MenuItem item1 = new MenuItem("About");
item1.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("About");
}
});
MenuItem item2 = new MenuItem("Preferences");
item2.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
System.out.println("Preferences");
}
});
MenuItem item3 = new MenuItem("Close");
item3.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
flow.getChildren().remove(bp);
}
});
contextMenu.getItems().addAll(item1, item2, item3);
bp.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>()
{
#Override
public void handle(ContextMenuEvent event)
{
contextMenu.show(bp, event.getScreenX(), event.getScreenY());
}
});
bp.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>()
{
#Override
public void handle(MouseEvent event)
{
contextMenu.hide();
}
});
return bp;
}
Is there a way to show makeTabContextMenu() only visible for the FlowPane body?
Have you tried to set the event consumed?
#Override
public void handle(MouseEvent t)
{
...
t.consume()
...
}
I want to develop a client app for website .
I want the app to reside in system tray when minimised.
I dont know how to accomplish this task .
Is their any example for this type of operation.
The key here is to set the implicit exit to false Platform.setImplicitExit(false);
Also is important to show and hide the stage in a new thread.
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.show();
}
});
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.hide();
}
});
Next, the whole code:
import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javax.imageio.ImageIO;
/**
*
* #author alvaro
*/
public class TrayTest extends Application {
private boolean firstTime;
private TrayIcon trayIcon;
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
createTrayIcon(stage);
firstTime = true;
Platform.setImplicitExit(false);
Scene scene = new Scene(new Group(), 800, 600);
stage.setScene(scene);
stage.show();
}
public void createTrayIcon(final Stage stage) {
if (SystemTray.isSupported()) {
// get the SystemTray instance
SystemTray tray = SystemTray.getSystemTray();
// load an image
java.awt.Image image = null;
try {
URL url = new URL("http://www.digitalphotoartistry.com/rose1.jpg");
image = ImageIO.read(url);
} catch (IOException ex) {
System.out.println(ex);
}
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent t) {
hide(stage);
}
});
// create a action listener to listen for default action executed on the tray icon
final ActionListener closeListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
System.exit(0);
}
};
ActionListener showListener = new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
Platform.runLater(new Runnable() {
#Override
public void run() {
stage.show();
}
});
}
};
// create a popup menu
PopupMenu popup = new PopupMenu();
MenuItem showItem = new MenuItem("Show");
showItem.addActionListener(showListener);
popup.add(showItem);
MenuItem closeItem = new MenuItem("Close");
closeItem.addActionListener(closeListener);
popup.add(closeItem);
/// ... add other items
// construct a TrayIcon
trayIcon = new TrayIcon(image, "Title", popup);
// set the TrayIcon properties
trayIcon.addActionListener(showListener);
// ...
// add the tray image
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(e);
}
// ...
}
}
public void showProgramIsMinimizedMsg() {
if (firstTime) {
trayIcon.displayMessage("Some message.",
"Some other message.",
TrayIcon.MessageType.INFO);
firstTime = false;
}
}
private void hide(final Stage stage) {
Platform.runLater(new Runnable() {
#Override
public void run() {
if (SystemTray.isSupported()) {
stage.hide();
showProgramIsMinimizedMsg();
} else {
System.exit(0);
}
}
});
}
}
As far as I know it will be possible in JFX 8. Right now the best solution is to embed your application into AWT and hide the AWT window itself.
I have a problem with a Context menu in JavaFx 2:it never disappers when I left click on the graph of the JFXPanel
Does anybody knows how to solve this problem?
Thanks
Here is my code
final ContextMenu cm = new ContextMenu();
MenuItem chartItem1 = new MenuItem("Chart Settings");
cm.getItems().add(chartItem1);
getScene().setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if(cm.isShowing()){
cm.hide();
}
if(mouseEvent.getButton() == MouseButton.SECONDARY)
{
cm.show(getScene().getRoot(), mouseEvent.getScreenX(), mouseEvent.getScreenY());
}
}
});
chartItem1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
dialogs.ChartFormat cs = new dialogs.ChartFormat(null, true);
cs.setLocationRelativeTo(null);
cs.setVisible(true);
}
});
Reproduced the described behavior. Don't know the reason but you can use ContextMenu#hide():
final ContextMenu cm = new ContextMenu();
MenuItem menuItem = new MenuItem("Item 1");
menuItem.addEventHandler(EventType.ROOT, new EventHandler<Event>() {
#Override
public void handle(Event t) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel messagePane = new JPanel();
messagePane.add(new JLabel("label"));
JDialog jDialog = new JDialog();
jDialog.getContentPane().add(messagePane);
jDialog.pack();
jDialog.setVisible(true);
}
});
}
});
cm.getItems().add(menuItem);
scene.setOnMouseReleased(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
// if(cm.isShowing())
cm.hide();
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
cm.show(lineChart, mouseEvent.getScreenX(), mouseEvent.getScreenY());
}
}
});
Also you can check out these links:
http://pixelduke.wordpress.com/2011/12/11/popupmenu-in-javafx/
http://javafx-jira.kenai.com/browse/RT-17853
http://javafx-jira.kenai.com/browse/RT-14899
Adding sample code to your question would be more descriptive.