We have a Java application that used Swing, but we are migrating it to JavaFX. Therefore, we wrap the old Swing code into SwingNodes and replace them step-by-step.
Before migrating, the Swing application used com.sun.java.swing.plaf.gtk.GTKLookAndFeel as look-and-feel (default on Ubuntu). We used following code to set it (if available):
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getClassName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) {
UIManager.setLookAndFeel(info.getClassName());
}
}
This worked fine. Yet, after switching to JavaFX, the call to UIManager.setLookAndFeel() freezes the application, and nothing happens. The manual setting of the look-and-feel is needed since we want to still style the Swing components that have not been migrated to JavaFX based on the GTKLookAndFeel.
Further info: This only does not work with com.sun.java.swing.plaf.gtk.GTKLookAndFeel, since it works when using javax.swing.plaf.metal.MetalLookAndFeel, javax.swing.plaf.nimbus.NimbusLookAndFeel or com.sun.java.swing.plaf.motif.MotifLookAndFeel.
What can we do to make it work with GTKLookAndFeel to style our Swing components in the SwingNodes?
Gui components need to be updated into gui threads.
Try one of the following:
SwingUtilities.invokeLater(() -> {
//commands
});
javafx.application.Platform.runLater(() -> {
//commands
});
Related
I have a JavaFX application that i have ported to Mac. When the application in foreground Command+H suppose to hide the application but for my ported application it is showing version details in a new popup windows.
I wanted to check if my program is suppose to handle Command+H and then hide the application or should it be handled by OS.
On macOS, it was solved by the following.
//
// Disable default popup window.
//
Desktop.getDesktop().setAboutHandler(null);
//
// Hides the stage when Command + H is pressed.
//
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.H, KeyCombination.META_DOWN), () -> {
primaryStage.setIconified(true);
}
);
I'm coding a game in java, and I decided to add music to it. I tried with this code:
URL resource = getClass().getResource("music.mp3");
MediaPlayer a = new MediaPlayer(new Media(resource.toString()));
a.setOnEndOfMedia(new Runnable() {
public void run() {
a.seek(Duration.ZERO);
}
});
a.play();
But for some reason, I get this error:
https://pastebin.com/UPkTbWHh
The file music.mp3 is in the same folder as the class I'm running it from, and the code is running in the tick() method. Do anybody have an idea about how I can fix this?
Thanks, Lukas
You're attempting to execute the above code from outside the context of a JavaFX app. MediaPlayer is a JavaFX component, so relies on the Toolkit being initialised, you can't (by default) just spin up a JFX component as you please.
The "proper" way is to subclass a JFX Application and then launch your application from there, which will initialise the JFX platform properly.
The "hack" way is to run the following line of code in the Swing EDT:
new JFXPanel();
...which will also have the side effect of initialising the JFX toolkit and allow you to create other JFX components.
As pointed out in the comments, since Java 9 you can use the less hacky method of:
Platform.startup(() -> {
//Code to run on JFX thread
});
Am designing a Notepad application in java, using AWT. Now, i have created the MenuBar as well as the MenuItems, but the thing i can't get is how do i deactivate specific MenuItem, like if we haven't wrote anything in the TextArea, in the Edit Section the cut and copy option, as well as Undo option remains Deactivate. Is there any method in java to do that stuff? Am doing this Using AWT and not Swing.
Got the answer, after trials and errors and surfing. While in the constructor while initializing them we will keep their initial values as "false". Hence when the texteditor opens there is nothing on the screen. So they will appear disabled and then registering TextArea object with KeyListener will do the job of enabling that menuItems. ;)
constructor()
{
undo=new MenuItem("Undo",new MenuShortcut(90));
edit.add(undo);
un.setEnabled(false);
cut=new MenuItem("Cut",new MenuShortcut(88));
edit.add(cut);
cut.setEnabled(false);
copy=new MenuItem("Copy",new MenuShortcut(67));
edit.add(copy);
copy.setEnabled(false);
paste=new MenuItem("Paste",new MenuShortcut(86));
ed.add(paste);
selectAll=new MenuItem("Select All",new MenuShortcut(65));
ed.add(selectAll);
selectAll.setEnabled(false);
textArea.addKeyListener();
}
public void keyTyped(KeyEvent arg0)
{
if(textArea.getText()!=null)
{
cut.setEnabled(true);
copy.setEnabled(true);
undo.setEnabled(true);
selectAll.setEnabled(true);
find.setEnabled(true);
}
}
In a Java Swing application that uses several own UI's (e.g. for JTabbedPane) sometimes right after startup, the Look and Feel (L&F) of the entire application changes back to the default. It quickly shows everything correct and then after a second or less the entire application changes to the ugly default.
Unfortunately, this is difficult to reproduce. It happens very rarely and so far only under Ubuntu when I start it directly from within Eclipse using java-1.6.0-openjdk-amd64. I have a newer java version installed too, but I use 1.6 to test compatibility.
Since it happens either for all or for no component, it looks like it does not matter how I I derive the UI. It even changes back this little change where no custom UI is used:
JTextField textField = new JTextField();
textField.setBorder(null);
So if it happens, then the border will show up.
Since this is difficult to reproduce, I can not give a code example where it always happens. Actually, the one above is already an example, but it does not happen always. But I hope to find someone who run into a similar issue where the L&F or any changes to it suddenly and unwanted changed back to the default. If so, I would appreciate if you could share your experience and hopefully a solution.
---------------- Edit:
I found two workaraounds:
For the border problem, I simply use textField.setBorder(new EmptyBorder()); instead of setting it to null.
For the reset of the UI, which was indeed caused by unwanted calls to updateUI, I created for my customized swing objects subclasses that override updateUI(), e.g.:
public class JTabbedPaneNoHeads extends JTabbedPane {
public JTabbedPaneNoHeads() {
setUI(new GUITabbedPaneNoHeadsUI());
}
#Override
public GUITabbedPaneNoHeadsUI getUI() {
return (GUITabbedPaneNoHeadsUI) ui;
}
#Override
public void updateUI() {
/* This was to find out who is calling updateUI:
StackTraceElement[] _stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement element : _stackTrace ){
System.out.print(element + " -- ");
}
System.out.println();
*/
setUI(new GUITabbedPaneNoHeadsUI());
}
}
Now everything works fine.
btw: the calls to updateUI had the following stack trace (generated by the commented block in the code above):
livedocket.GUI.design.JTabbedPaneNoHeads.updateUI(JTabbedPaneNoHeads.java:22)
javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1230)
.... many more of these updateComponentTreeUI0 ...
javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1245)
javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1221)
javax.swing.plaf.metal.MetalLookAndFeel$AATextListener.updateWindowUI(MetalLookAndFeel.java:2329)
javax.swing.plaf.metal.MetalLookAndFeel$AATextListener.updateAllUIs(MetalLookAndFeel.java:2342)
javax.swing.plaf.metal.MetalLookAndFeel$AATextListener.access$200(MetalLookAndFeel.java:2295)
javax.swing.plaf.metal.MetalLookAndFeel$AATextListener$1.run(MetalLookAndFeel.java:2370)
java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
java.awt.EventQueue.dispatchEventImpl(EventQueue.java:673)
java.awt.EventQueue.access$300(EventQueue.java:96)
java.awt.EventQueue$2.run(EventQueue.java:634)
java.awt.EventQueue$2.run(EventQueue.java:632)
java.security.AccessController.doPrivileged(Native Method)
java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:108)
java.awt.EventQueue.dispatchEvent(EventQueue.java:643)
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
As I mentioned before, these calls happen only very rarely and only on Java 1.6.
I have seen similar symptoms in an application with threading problems - if I were you I would double-check if all of the GUI is constructed on the Event Dispatch Thread.
I am working on a project where there is a Java client that needs to run on both Windows and Mac. At the top is a search box, which appears correctly on Windows but incorrectly on Macintosh. You can also see how the cursor does not appear right.
Any help would be much appreciated in trying to work out why this is happening.
I would suggest either to reduce the font-size or make the box higher to accommodate the text inside the box.
Also, if its not required that the GUI looks native, you might want to enable the NIMBUS look and feel (from Java 6u14 I think). I've made applications where its more important that the app looks the same between OSes, than it is that the app looks more like a native app on that OS. Your requirements might differ from app to app :)
You can enable Numbus by calling (usually in public static void main(...):
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look and feel.
}