Listener on MenuBar in Vaadin - listener

I want to add a ClickListener to an Item of a MenuBar in Vaadin.
I know about the normal situation, which i got working:
MenuBar menubar = new MenuBar();
menubar.addItem("Item", new MenuBar.Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
//Do sth. when item is clicked
}
});
In my application, I'm working with MVP, so the code which should run, is in an other class than the code which is defining the menubar.
Is there a way to add a listener to a specific item in the menubar ?

When you add an item to your MenuBar the function addItem(String,Command) actually returns a MenuItem which can be used later. You can do this :
MenuItem select = menuBar.addItem("Select", null);
And in another context you can add a listener on that MenuItem like this:
select.setCommand(new Command() {
#Override
public void menuSelected(MenuItem selectedItem) {
System.out.println("You clicked on "+selectedItem.getText());
}
});

Related

Making JavaFX Alerts/Dialogs Modal within Swing Application

So once again we are in the process of converting our existing Java application that was using entirely Swing to using JavaFX. However, the application will not be using JavaFX entirely. This seems to be causing some issues with Alerts/Dialogs and modality. We are currently using Java 8u40.
The main application is basically in a JFrame that has a Menu. The main content pane is JDesktopPane and clicking a MenuItem opens new JInternalFrames within the DeskopPane. Screens we are converting to JavaFX are basically JFXPanels within a JInternalFrame at the moment. Any Alerts/Dialogs that are opened from the JFXPanels are modal to the panel itself, but not to the JInternalFrame, DeskopPane, Menu, etc.
I read in the DialogPane documentation that they are planning to introduce some lightweight dialogs and even possibly InternalFrames in future releases of JavaFX, so maybe we'll just have to wait it out a little longer for this functionality. But, ideally when opening a new Alert/Dialog it would be modal to the entire Application.
EDIT:
Currently doing the following for modal dialogs:
((Stage)getDialogPane().getScene().getWindow()).setAlwaysOnTop(true);
This makes the dialog always appear on top, however the dialog also remains on top of other applications even if our main application is minimized. It also does not block input to any Swing components in the frame.
You can use the following work-around which creates an invisible JDialog when the Alert is shown and disposes the JDialog when the Alert is closed. This approach extends the modality to the whole application, including the Swing part.
// create Alert
Alert alert = new Alert(AlertType.INFORMATION, "Hello");
// create invisible JDialog and "show" it
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setUndecorated(true);
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
SwingUtilities.invokeLater(() -> dialog.setVisible(true));
// show Alert
alert.showAndWait();
// close JDialog after Alert is closed
dialog.dispose();
I don't think i understand your question completely. But here is my guess - You are trying to make an alert window from some JFXPanel that will be modal (i.e. user will not be able to click in your application until she closes that alert window) to your entire application which is written partially using swing components.
If your application would be written in purely JavaFX then you would do something like (Assuming you have created a button somewhere in your JFXPanel)
button.setOnAction(evt -> {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.initModality(Modality.APPLICATION_MODAL);
// This will not work in your code
alert.initOwner(button.getScene().getWindow());
alert.show();
});
but since initOwner requires a javafx.stage.window object passing a swing component won't work in your code. As of Java 8u40 i don't think there is a right way(i.e. not hacks) to set ownership of Alert objects to swing component. Not surprisingly such questions has already been asked here and not answered as of writing this.
For your requirements you can use JOptionPane.showMessageDialog method and its look alike as workaround.
button.setOnAction(evt -> {
JOptionPane.showMessageDialog(desktopPane,"My message");
});
These dialog boxes are modal by default so no work is necessary. You can call these from any event handler methods of JavaFX components.
I've done a little workaround with a small interface which is implemented in my JavaFXFrame:
public interface DialogParent {
void setOnFocusGained(EventHandler<FocusEvent> focusHandler);
void setOnCloseRequest(EventHandler<WindowEvent> closeHandler);
}
And my JavaFXFrame implementation
public class JavaFXFrame implements DialogParent {
private JFrame frame;
private EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler;
private EventHandler<javafx.stage.WindowEvent> windowClosingHandler;
public void JavaFXFrame() {
final JFXPanel fxPanel = new JFXPanel();
frame = new JFrame();
frame.add(fxPanel);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
tryClosing(this);
}
});
frame.addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent e) {
if (focusGainedHandler != null) {
focusGainedHandler.handle(new FocusEvent());
}
}
});
}
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
private void tryClosing(WindowListener listener) {
javafx.stage.WindowEvent windowEvent = new javafx.stage.WindowEvent(null, javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST);
if (windowClosingHandler != null) {
windowClosingHandler.handle(windowEvent);
}
if (!windowEvent.isConsumed()) {
frame.setVisible(false);
}
}
#Override
public void setOnFocusGained(EventHandler<ch.irix.sumadmin.util.FocusEvent> focusGainedHandler) {
this.focusGainedHandler = focusGainedHandler;
}
#Override
public void setOnCloseRequest(EventHandler<javafx.stage.WindowEvent> windowClosingHandler) {
this.windowClosingHandler = windowClosingHandler;
}
}
And showing an Alert:
public static void showAlert(Alert alert) {
DialogPane dialogPane = alert.getDialogPane();
final Stage stage = new Stage();
stage.setScene(dialogPane.getScene());
List<ButtonType> buttonTypes = dialogPane.getButtonTypes();
for (ButtonType buttonType : buttonTypes) {
ButtonBase button = (ButtonBase) dialogPane.lookupButton(buttonType);
button.setOnAction(evt -> {
dialogPane.setUserData(buttonType);
stage.close();
});
}
dialogParent.setOnFocusGained(event -> {
stage.toFront();
});
dialogParent.setOnCloseRequest(Event::consume);
stage.setOnCloseRequest(event -> {
dialogParent.setOnFocusGained(null);
dialogParent.setOnCloseRequest(null);
});
stage.show();
}
Hope this will help you

How to specify javascript method on menu item click in managed bean?

Primefaces :4
I need to create a Programmatic Menu & specify a javascript method which would be called on click of the menu item.
I am unable to understand how to specify the javascript method to be called on menu item click in the managed bean.
Only the client side method needs to be called. Server side method is not required to be called.
#ManagedBean
public class MenuView {
private MenuModel model;
#PostConstruct
public void init() {
model = new DefaultMenuModel();
//First submenu
DefaultSubMenu firstSubmenu = new DefaultSubMenu("Dynamic Submenu");
DefaultMenuItem item = new DefaultMenuItem("ABC");
item.setIcon("ui-icon-home");
firstSubmenu.addElement(item);
...
model.addElement(firstSubmenu);
}
public MenuModel getModel() {
return model;
}
}
You can use : item.setOnclick(String click)
Check out the API : http://www.primefaces.org/docs/api/4.0/org/primefaces/model/menu/DefaultMenuItem.html#setOnclick(java.lang.String)

Javafx 2.0 - Get ContextMenu Parent Node in EventHandler

I am writing a javafx UI and would like to get the owner Node of a contextMenu from a eventHandler for the MenuItem that was clicked on.
My Code:
TabPane tabPane = new TabPane();
Tab tab1 = new Tab();
Tab tab2 = new Tab();
tabPane.getTabs().addAll(tab1,tab2);
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
#override
public void handle(ActionEvent e){
// Get the tab which was clicked on and do stuffs with it
}
});
contextMenu.getItems().add(menuItem);
for(Tab tab: tabPane.getTabs()){
tab.setContextMenu(contextMenu);
}
What I would like to do is get a reference to the tab that had it's contextMenu selected.
I was able to get a reference to what appears to be the ContextMenu of the MenuItem with the following code inside of the handle(ActionEvent e) method for the menuItem eventHandler:
ContextMenu menu = ((ContextMenu)((MenuItem)e.getSource()).getParentPopup());
My idea from there was to use ContextMenu's .getOwnerNode() method on menu and then have a reference to the tab, but when running that I get a reference to an item that I can't make sense of.
The toString() method for the object returned by .getOwnerNode() returns "TabPaneSkin$TabHeaderSkin$3#14f59cef" which I can't figure out the meaning of.
Is my approach of trying to work my way up the chain until I get to the node correct or is there an entirely different approach that will work better?
All I need to have is the functionality of a ContextMenu, and when the MenuItem is clicked on, I need to have a reference to the tab for which the ContextMenu was selected so I can do cool stuffs with it.
Create a ContextMenu for each tab.
Make each tab final.
Directly reference the final tab in the menu item event handler for the context menu.
Here is a code snippet:
final Tab tab = new Tab("xyzzy");
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
tab.setText("Activated by User");
}
});
Every time the user right clicks on a tab header and selects the "Count Click" menu, the content of the related tab is updated with a count of the number of licks counted so far for that tab.
Here is an executable sample:
import javafx.application.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class TabContext extends Application {
#Override public void start(Stage stage) {
TabPane tabPane = new TabPane();
tabPane.getTabs().addAll(
createTab("xyzzy", "aliceblue"),
createTab("frobozz", "blanchedalmond")
);
stage.setScene(new Scene(tabPane));
stage.show();
}
private Tab createTab(String tabName, String webColor) {
final Label content = new Label("0");
content.setAlignment(Pos.CENTER);
content.setPrefSize(200, 100);
content.setStyle("-fx-font-size: 30px; -fx-background-color: " + webColor + ";");
final Tab tab = new Tab(tabName);
tab.setContent(content);
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Count Click");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
#Override public void handle(ActionEvent e){
content.setText(
"" + (Integer.parseInt(content.getText()) + 1)
);
}
});
contextMenu.getItems().add(menuItem);
tab.setContextMenu(contextMenu);
return tab;
}
public static void main(String[] args) { Application.launch(args); }
}
Alternately to using an anonymous inner class this way, you could create an EventHandler subclass with a constructor that includes the Tab for which the EventHandler is attached.
class TabContextMenuHandler implements EventHandler<ActionEvent> {
private final Tab tab;
TabContextMenuHandler(Tab tab) {
this.tab = tab;
}
#Override public void handle(ActionEvent event) {
tab.setText("Activated by User");
}
}

Adding an ActionListener to a JList

I have a JList with an array of strings. Basically it displays a restaurant menu.
right next to the JList i have another JList which is empty. Whenever a user double clicks on a string in the first JList (where the menu is displayed) I want it to show up on the next JList which is right next to it.
how do i do that?
You can try
final JList list = new JList(dataModel);
MouseListener mouseListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
String selectedItem = (String) list.getSelectedValue();
// add selectedItem to your second list.
DefaultListModel model = (DefaultListModel) list2.getModel();
if(model == null)
{
model = new DefaultListModel();
list2.setModel(model);
}
model.addElement(selectedItem);
}
}
};
list.addMouseListener(mouseListener);
You may also want to do it with the Enter key pressed by adding a KeyListener:
jlist.addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_ENTER){
//do what you want to do
}
}
});
I know that this is not for a double click but some people want to do it with the Enter button instead as I wanted to do.
I have done it already in your code in the other question?
[link] I want to add an action listener from one JList to another JList and how can a JList appear with out any text inside?
The only think you must do there is to put it into the #Bala R's if statement doing the check of number of clicks:
if (e.getClickCount() == 2) {
//your code
}
Actually you would be better to use addElement(selectedItem); method, as in the #Bala R's code instead of
add(orderList.getModel().getSize(), selectedItem); in my code. Both add the item to the end but addElement looks nicer and you do not need to retrieve the model's size.
Oi, Boro.
public void addActionListener(final ActionListener al) {
jList.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
al.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "ENTER"));
}
}
});
jList().addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
al.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "ENTER"));
}
}
});
}

Java Swing - Display table in sub menu

I have a menu that displays say
Item1
Item2
Item3
etc. Clicking on Item1 should display me a Table with 2 columns.
I tried something below with displaying just a label. But the label gets displayed somewhere in the screen where as I am expecting it to be a submenu under menuitem1.
JMenu mainMenu = new JMenu("MainMenuHeader");
JMenu menuItem1 = new JMenu(new SomeClassExtendingAbstractAction("menuItem1"));
public class SomeClassExtendingAbstractAction extends AbstractAction {
public SomeClassExtendingAbstractAction(String displayText) {
super(displayText);
}
public void actionPerformed(ActionEvent event) {
try {
SubMenuDialog.showDialog(parent);
} catch (Throwable e) {
}
}
}
public class SubMenuDialog extends JDialog {
public SubMenuDialog(JFrame parent) {
super();
initialize();
}
private void initialize() {
JLabel label = new JLabel();
label.setText("This is test submenu");
getContentPane().add(label);
}
public static void showDialog(JFrame parent) {
SubMenuDialog subMenuDialog = new SubMenuDialog(parent);
subMenuDialog.pack();
subMenuDialog.setVisible(true);
}
}
If I understand correctly, what you want to do is to show arbitrary component in a submenu popup. You obviously cannot use JDialog as it would give you a, you know, JDialog.
Your SubMenuDialog#showDialog can create a JPopupMenu, add any component to it (for example JScrollPane containing a table, or JPanel with labels), and show it where a normal submenu would be.
However it's not a good idea in general to show complicated things in a popup, since it's too easy to lose the popup, plus you may get focus problems with components inside the popup.
I'd suggest you consult a UI designer for the best UI representation of the functionality you want to implement.