I want to add a context menu on right click of my Line Chart.
Its basically for re-sizing the chart.Is there any way i can achieve this?
Here is a code snippet to bring up a resizing context menu on a line chart when the line chart is right clicked.
final MenuItem resizeItem = new MenuItem("Resize");
resizeItem.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
System.out.println("Resize requested");
}
});
final ContextMenu menu = new ContextMenu(
resizeItem
);
lineChart.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
menu.show(stage, event.getScreenX(), event.getScreenY());
}
}
});
Some complete sample code:
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.stage.Stage;
public class LineChartWithContextMenu extends Application {
#Override public void start(final Stage stage) {
stage.setTitle("Line Chart Sample");
//defining the axes
final NumberAxis xAxis = new NumberAxis();
xAxis.setLabel("Number of Month");
final NumberAxis yAxis = new NumberAxis();
//creating the chart
final LineChart<Number,Number> lineChart =
new LineChart<>(xAxis,yAxis);
lineChart.setTitle("Stock Monitoring, 2010");
//defining a series
XYChart.Series series = new XYChart.Series();
series.setName("My portfolio");
//populating the series with data
series.getData().setAll(
new XYChart.Data(1, 23),
new XYChart.Data(2, 14),
new XYChart.Data(3, 15),
new XYChart.Data(4, 24),
new XYChart.Data(5, 34),
new XYChart.Data(6, 36),
new XYChart.Data(7, 22),
new XYChart.Data(8, 45),
new XYChart.Data(9, 43),
new XYChart.Data(10, 17),
new XYChart.Data(11, 29),
new XYChart.Data(12, 25)
);
lineChart.getData().add(series);
//adding a context menu item to the chart
final MenuItem resizeItem = new MenuItem("Resize");
resizeItem.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
System.out.println("Resize requested");
}
});
final ContextMenu menu = new ContextMenu(
resizeItem
);
lineChart.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
menu.show(stage, event.getScreenX(), event.getScreenY());
}
}
});
stage.setScene(
new Scene(
lineChart,800,600
)
);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
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....
Can you help me to fix this code. It's not working working properly as I expected.
package javafxapplication2;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Callback;
class Person {
private StringProperty aliasName;
private StringProperty newPanelName;
private StringProperty newPanelDescription;
private ObservableList<Person> panels = FXCollections.observableArrayList();
public final void setAliasName(String value) {
aliasNameProperty().set(value);
}
public final String getAliasName() {
return aliasNameProperty().get();
}
public StringProperty aliasNameProperty() {
if (aliasName == null) {
aliasName = new SimpleStringProperty();
}
return aliasName;
}
public final void setNewPanelName(String value) {
newPanelNameProperty().set(value);
}
public final String getNewPanelName() {
return newPanelNameProperty().get();
}
public StringProperty newPanelNameProperty() {
if (newPanelName == null) {
newPanelName = new SimpleStringProperty();
}
return newPanelName;
}
public final void setNewPanelDescription(String value) {
newPanelDescriptionProperty().set(value);
}
public final String getNewPanelDescription() {
return newPanelDescriptionProperty().get();
}
public StringProperty newPanelDescriptionProperty() {
if (newPanelDescription == null) {
newPanelDescription = new SimpleStringProperty();
}
return newPanelDescription;
}
public ObservableList<Person> panelsProperty() {
return panels;
}
public Person(String alias, String newPanelName, String newPanelDescription) {
setAliasName(alias);
setNewPanelName(newPanelName);
setNewPanelDescription(newPanelDescription);
}
}
public class JavaFXApplication2 extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(final Stage primaryStage) {
primaryStage.setTitle("test");
Group root = new Group();
Scene scene = new Scene(root, 500, 250, Color.WHITE);
// create a grid pane
GridPane gridpane = new GridPane();
gridpane.setPadding(new Insets(5));
gridpane.setHgap(10);
gridpane.setVgap(10);
ObservableList<Person> leaders = FXCollections.observableArrayList();
leaders.add(new Person("test 1", "test 11", "test 111"));
leaders.add(new Person("test 2", "test 22", "test 222"));
leaders.add(new Person("test 3", "test 33", "test 333"));
leaders.add(new Person("test 4", "test 44", "test 444"));
final ListView<Person> leaderListView = new ListView<>(leaders);
leaderListView.setPrefWidth(450);
leaderListView.setPrefHeight(150);
//
leaderListView.setCellFactory(new Callback<ListView<Person>, ListCell<Person>>() {
#Override
public ListCell<Person> call(ListView<Person> param) {
final Label leadLbl = new Label();
final Tooltip tooltip = new Tooltip();
final ListCell<Person> cell = new ListCell<Person>() {
#Override
public void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
leadLbl.setText(item.getAliasName());
setText(item.getNewPanelName());// + " " + item.getNewPanelDescription());
tooltip.setText(item.getAliasName());
setTooltip(tooltip);
}
}
}; // ListCell
return cell;
}
}); // setCellFactory
// Double click
leaderListView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 2) {
Person item = leaderListView.getSelectionModel().getSelectedItem();
if (item != null) {
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
pane.getChildren().add(new TextField(item.getAliasName()));
stage.show();
}
}
}
}
});
gridpane.add(leaderListView, 0, 1);
// Buttons
// Button "Open"
Button btnYes = new Button("Open");
btnYes.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
leaderListView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Person>() {
#Override
public void changed(ObservableValue<? extends Person> observable, Person oldValue, Person newValue) {
Person item = leaderListView.getSelectionModel().getSelectedItem();
if (item != null) {
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
pane.getChildren().add(new TextField(item.getAliasName()));
stage.show();
}
System.out.println("selection changed");
}
});
}
});
// Button "Cancel"
Button btnNo = new Button("Cancel");
btnNo.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
primaryStage.close();
}
});
HBox hbox = new HBox();
hbox.setSpacing(10);
hbox.setAlignment(Pos.CENTER);
hbox.getChildren().add(btnYes);
hbox.getChildren().add(btnNo);
gridpane.add(hbox, 0, 2);
root.getChildren().add(gridpane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I want to select one row and then to open a new window when I click the button Select to open a new window. Can you help me to fix the code?
Replace the btnYes.setOnAction with the following :
btnYes.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Person item = leaderListView.getSelectionModel().getSelectedItem();
if (item != null) {
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
pane.getChildren().add(new TextField(item.getAliasName()));
stage.show();
}
}
});
It should be this the action of the btnYes:
btnYes.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent event)
{
Person item = leaderListView.getSelectionModel().getSelectedItem();
if (item != null) {
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
pane.getChildren().add(new TextField(item.getAliasName()));
stage.show();
}
}
});
(there might be an axtra braket, just edited online.)
Also, this is exactly the same code as in the list doubleclick event, might want to put it in a diferent method, so that you dont repeat code:
public void openNewWindow(){
Person item = leaderListView.getSelectionModel().getSelectedItem();
if (item != null) {
StackPane pane = new StackPane();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
pane.getChildren().add(new TextField(item.getAliasName()));
stage.show();
}
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'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();
}
});
}
}
Following the Oracle's example for a ListView, I have been able to get a ComboBox color rendering a list of color
My problem is that once a color is selected, ComboBox display the string name while I would like to display the color itself, with or without the color name aside.
How to change this code in order to get the selected color displayed?
Thanks all.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Callback;
public class ProvaComboRendering extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ComboBox<String> cb = new ComboBox<String>();
cb.setPrefSize(150, 20);
root.getChildren().add(cb);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
cb.setItems(data);
cb.setCellFactory(new Callback<ListView<String>, ListCell<String>>(){
#Override
public ListCell<String> call(ListView<String> list){
return new ColorRectCell();
}
});
}
static class ColorRectCell extends ListCell<String>{
#Override
public void updateItem(String item, boolean empty){
super.updateItem(item, empty);
Rectangle rect = new Rectangle(120,18);
if(item != null){
rect.setFill(Color.web(item));
setGraphic(rect);
}
}
}
public static void main(String[] args) {
launch(args);
}
}
Edit: Is it possibile to show a tooltip displaing the name of the color while the mouse pointer is over one of the color list?
Use ComboBox's button cell property. You can use the same cellfactory:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ComboBox<String> cb = new ComboBox<String>();
cb.setPrefSize(150, 20);
root.getChildren().add(cb);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
cb.setItems(data);
Callback<ListView<String>, ListCell<String>> factory = new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
return new ColorRectCell();
}
};
cb.setCellFactory(factory);
cb.setButtonCell(factory.call(null));
}
or define a new cell factory for button cell, like below which adds a tooltipablity :
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ComboBox<String> cb = new ComboBox<String>();
cb.setPrefSize(150, 20);
root.getChildren().add(cb);
Scene scene = new Scene(root, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
ObservableList<String> data = FXCollections.observableArrayList(
"chocolate", "salmon", "gold", "coral", "darkorchid",
"darkgoldenrod", "lightsalmon", "black", "rosybrown", "blue",
"blueviolet", "brown");
cb.setItems(data);
Callback<ListView<String>, ListCell<String>> factory = new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
return new ColorRectCell();
}
};
cb.setCellFactory(factory);
Callback<ListView<String>, ListCell<String>> factoryTooltip = new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
return new ColorRectTooltipCell();
}
};
cb.setButtonCell(factoryTooltip.call(null));
}
static class ColorRectTooltipCell extends ColorRectCell {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
Tooltip.install(this.getParent(), new Tooltip(item));
}
}
}