I'm trying to add proper support for OS X in my Java 8 Swing application. To do this I'm using the com.apple:AppleJavaExtensions:1.4 package from maven.
I initialise the menu bar using the following code:
Application application = Application.getApplication();
JMenu fileMenu = new JMenu("File");
JMenuItem openMenuItem = new JMenuItem("Open...");
openMenuItem.addActionListener(action -> openFileDialog());
openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_MASK));
fileMenu.add(openMenuItem);
JMenuBar mainMenuBar = new JMenuBar();
mainMenuBar.add(fileMenu);
application.setDefaultMenuBar(mainMenuBar);
This works just fine the first time, without any Swing windows opened. However, when one file is opened (and a Swing window is created), the shortcut stops working. Pressing CMD+O still highlights the menu item, but the action isn't executed. Using the mouse to select the 'Open...' menu item does work. I'm guessing the Swing window is somehow stealing the event (but the menu is still highlighted when the key combo is pressed.. weird).
When the file open dialog (that openFileDialog() shows) is cancelled, the menu accelerator will keep working. So it is definitely related to the Swing window being opened when a file is opened.
Another problem with opening files with OS X is that the following code never shows 'foo':
application.setOpenFileHandler(e -> System.out.println("foo"));
This code is executed in main() (which returns almost instantly, after creating the menu bar I mentioned earlier). The file handler isn't ever called; not when dropping a file onto the dock icon, nor when double clicking a file and opening it with my application.
What am I doing wrong?
If your app doesn't have many Frames then this could be a workaround.
setJMenuBar(menuBar);
final Dimension invisible = new Dimension(0, 0);
menuBar.setSize(invisible);
menuBar.setMaximumSize(invisible);
menuBar.setPreferredSize(invisible);
menuBar.setMinimumSize(invisible);
Apparently the OpenFileHandler does nothing unless your Java application is running from an application bundle with an Info.plist that specifies appropriate CFBundleDocumentTypes. Here's an example of what it should look like:
http://www.qtcentre.org/wiki/index.php?title=Opening_documents_in_the_Mac_OS_X_Finder
I worked around the menu accelerator not working by simply registering a KeyEventDispatcher to the KeyboardFocusManager on each of the Swing windows, and manually invoking the appropriate ActionListeners when the correct KeyEvent is caught. Very very ugly, but it works. I'm still wondering why this is necessary.
Related
I followed this tutorial to create an app with tray icon. When I closed the app window, there is an icon left on the task bar. The question is how can I hide the icon on task bar when I close the window? If it is not possible, then if there is a way to bring back the window when I click the task bar icon? A cross-platform solution will be much appreciated.
The gist you linked to has everything you're looking for.
A way to reopen the JavaFX window (involves two parts):
Lines 39-40:
// instructs the javafx system not to exit implicitly when the last application window is shut.
Platform.setImplicitExit(false);
Lines 106-112:
// if the user double-clicks on the tray icon, show the main app stage.
trayIcon.addActionListener(event -> Platform.runLater(this::showStage));
// if the user selects the default menu item (which includes the app name),
// show the main app stage.
java.awt.MenuItem openItem = new java.awt.MenuItem("hello, world");
openItem.addActionListener(event -> Platform.runLater(this::showStage));
A way to exit the application completely:
Lines 120-128:
// to really exit the application, the user must go to the system tray icon
// and select the exit option, this will shutdown JavaFX and remove the
// tray icon (removing the tray icon will also shut down AWT).
java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit");
exitItem.addActionListener(event -> {
notificationTimer.cancel();
Platform.exit();
tray.remove(trayIcon);
});
I've been running into a problem lately where I try to se a JMenuItems icon which when I define and point to the icon the application it self don't start/show.
I started looking for errors, but there where none; started looking for write occurencies, which typically pretty much does appear when I add the icon and after that as pointed above the application doesn't start/show.
When the icon is set but commented:
Code
mntmMaximize = new JMenuItem();
mntmMaximize.setText("Maximize Window");
mntmMaximize.setActionCommand("maximize");
mntmMaximize.addActionListener(this);
mntmMaximize.setMnemonic(KeyEvent.VK_PLUS);
mntmMaximize.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, ActionEvent.CTRL_MASK));
// mntmMaximize.setIcon(new ImageIcon(Vision.class.getResource("xray/fullscreen16x.png")));
mnWindow.add(mntmMaximize);<br>
Picture:
Screen Shot Of Visible Application
After the icon is set and trying to execute application:
Code:
mntmMaximize = new JMenuItem();
mntmMaximize.setText("Maximize Window");
mntmMaximize.setActionCommand("maximize");
mntmMaximize.addActionListener(this);
mntmMaximize.setMnemonic(KeyEvent.VK_PLUS);
mntmMaximize.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, ActionEvent.CTRL_MASK));
mntmMaximize.setIcon(new ImageIcon(Vision.class.getResource("xray/fullscreen16x.png")));
mnWindow.add(mntmMaximize);<br>
Picture:
The window not created and application terminated
Note that when the window is not created in this picture the application is therefor terminated.
Please try to answer nice, and if you need the whole source file it is possible.
Edit:
Also if needed i can make a video where i show when i start the application when the icon is set but not commented.
getResource uses the relative path with respect to the package (folder), like in
Vision.class.getResource("fullscreen16x.png")
or absolute like in:
Vision.class.getResource("/xray/fullscreen16x.png")
Here is my specific scenario:
I have my application running in the background and I want to open a new window from my applications toolbar icon right click menu. For simplicity I am using a MessageDialog, and using the method open() on the dialog, the window should display and make itself the active window.
For some reason I've run into the problem that if I had some other application open and I try to open this new dialog, it opens, but behind the active application. The new dialog will open in front of the other windows of the same application, but not the other(active) application.
Is there a simple way to do this that I'm missing?
I was able to find a solution. Essentially you need to find your active workbench shell(the application shell) and use the following methods on that shell, followed by pushing the actual desired window to the front.
You could easily modify this to make your window appear maximized as well by adding the method shell.setMaximized(true) before the redraw.
private static void bringupDialog(WindowState state) {
final Shell workbenchShell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
//bring up the application to front
workbenchShell.setVisible( true );
workbenchShell.setMinimized( false );
workbenchShell.redraw();
//focus on dialog
workbenchShell.setActive();
workbenchShell.forceActive();
workbenchShell.setFocus();
workbenchShell.forceFocus();
workbenchShell.moveAbove( null );
workbenchShell.redraw();
Shell shell = instance.getShell(); // desired window shell
shell.setActive();
shell.forceActive();
shell.setFocus();
shell.forceFocus();
shell.moveAbove( null );
shell.redraw();
}
In my current RCP-project i use a MultipageEditorPart. It has various pages, with simple SWT composites on it. The composites contain some Text and Combo elements. When the user right clicks onto the editor page, I want a context menu to open. This menu holds a command for creating a new editor page, with a composite on it.
The command is already working, but I'm quite clueless about how to implement the context menu for the editor. Can someone help with this?
This should be based on Action contributions: see Contributing Actions to the Eclipse Workbench
As an RCP-based example, You could check out "Designing a Workflow Editor Eclipse XML", where a contextual menu is added to an EditorPart, included in a MultipageEditorPart.
protected void createContextMenuFor(StructuredViewer viewer) {
MenuManager contextMenu = new MenuManager("#PopUp");
contextMenu.add(new Separator("additions"));
contextMenu.setRemoveAllWhenShown(true);
contextMenu.addMenuListener(this);
Menu menu= contextMenu.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(contextMenu, new UnwrappingSelectionProvider(viewer));
}
See also Step 18 for extending that context menu (section "Delete - Contextual Menu, requiring using GEF).
I'm developing a SWT/JFace application using the libraries from Eclipse 3.4.1.
I encounter the following problem on Windows (Vista 32bit) and Ubuntu 8.10 32bit:
I create a menu bar in the createMenuManager method of the JFace ApplicationWindow. I add MenuManagers for file, edit and help.
I then add an ExitAction to the file MenuManager like so:
filemenu.add(new ExitAction(this));
The ExitAction is defined this way:
public class ExitAction extends Action {
final ApplicationWindow window;
public ExitAction(ApplicationWindow w) {
this.window = w;
setText("E&xit");
setToolTipText("Exit the application");
setAccelerator(SWT.MOD1 + 'Q');
}
}
Now when my application starts I want be able to press "CTRL+Q" to quit the application. This does however not work. Only AFTER I click on "File" in the menu bar and THEN clicking "CTRL+Q" the application will quit.
I've tried this with different accelerators- same behavior.
It does work however if I create a "MenuItem" instead of an "Action" to contribute to the menu bar.
Is this a SWT bug or do I miss something?
Torsten.
Update: There is a duplicate bug of mine which also contains a workaround.
The bug url is: https://bugs.eclipse.org/bugs/show_bug.cgi?id=243758
Basically the workaround is to call create() on the ApplicationWindow and then getMenuBarManager().updateAll(true); which will force all menu items to get initialized.
Of course you have to call the above methods after you created the menu items.
AFAIK setAccelerator(.) does nothing else than adding the appropriate text to your MenuItem. You are responsible to register for an KeyUp event and react on it.
You can use Display.addFilter(SWT.KeyUp, myListener) to register your Listener independently of your widgets.
Turns out that this is a bug in Eclipse 3.4.
I have submitted a bug report: https://bugs.eclipse.org/bugs/show_bug.cgi?id=253078