Substance L&F not working - java

I want to use the Substance L&F library in my Java application, so I downloaded the .jar files and added them to the project classpath. Then I want to set the L&F in the application's main() function like this:
SwingUtilities.invokeAndWait(new Runnable()
{
#Override
public void run()
{
try
{
// Substance
String skin = "org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel";
SubstanceLookAndFeel.setSkin(skin);
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
}
catch(Exception e)
{
System.err.println("Can't initialize specified look&feel");
e.printStackTrace();
}
}
});
That is done before the JFrame is being created. However, even though no exception is thrown, nothing happens, the GUI is rendered in default Swing L&F.
Any ideas what I am missing here?
EDIT
Instead of the SubstanceLookAndFeel.setSkin(skin); call I tried it with UIManager.setLookAndFeel(skin); instead. This still doesn't work, but at least I get an exception now:
org.pushingpixels.substance.api.UiThreadingViolationException:
State tracking must be done on Event Dispatch Thread
Isn't that solved by calling this via invokeAndWait()?
EDIT-2
Ok, so the problem was something different. The exception was thrown while creating a JTable, not when setting the L&F. I was able to solve the issue - the L&F is now correctly rendered - by calling the JFrame constructor (which then basically runs the whole application) via EventQueue.invokeLater(). But I never did that before, is it "save" (valid in Java terms) to do it that way?

There is a small trick when setting Substance LaF. You have to call UIManager.setLookAndFeel(new SubstanceGraphiteAquaLookAndFeel()); before you call UIManager.setLookAndFeel("org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel");. So, set it like this:
public class App {
public static void main(String [] args) {
try {
UIManager.setLookAndFeel(new SubstanceGraphiteAquaLookAndFeel());
UIManager.setLookAndFeel("org.pushingpixels.substance.api.skin.SubstanceGraphiteAquaLookAndFeel");
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable(){
public void run() {
//Your GUI code goes here..
}
});
}
}

Related

JavaFX and and getDesktop().open() crashes the program

When I try to call Desktop.getDesktop().open(), my program crashes.
I'm on Ubuntu GNOME 16.10, running Gnome 3.20.4. I haven't had a chance to test this code on another platform, but on this platform it is definitely crashing the program.
browseMenuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Platform.runLater( new Runnable() {
public void run() {
try {
System.out.println ( Desktop.isDesktopSupported() );
Desktop.getDesktop().open( albumTable.getSelectionModel().getSelectedItem().getPath().toFile() );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
});
Any thoughts on how to fix or troubleshoot this?
You're mixing JavaFX and AWT, which is likely causing the problem. Instead of
Desktop.getDesktop().open(file);
try using the JavaFX API:
getHostServices().showDocument(file.toURI().toString());
getHostServices() is defined in Application (so you may need to retrieve it in your start method and pass it to whichever object - perhaps a controller - is registering the listener with the menu item).
It looks like #James_D's answer is the better way to do things, but currently (as of 2017/05/03) it doesn't work on the OpenJDK / OpenJFK.
Thankfully, his comment about mixing JFX and Swing helped me find a solution which will work on OpenJDK / OpenJFX:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
Desktop.getDesktop().open( albumTable.getSelectionModel().getSelectedItem().getPath().toFile() );
} catch (IOException e) {
e.printStackTrace();
}
}
});
The trick was using SwingUtilities.invokeLater() rather than Platform.runLater(), since the code inside is swing.

Regarding the Look and Feel in Java

In Java, I want to set the Look and Feel of the program (specifically to the 'get system look and feel').
Is it necessary to set the look and feel inside each component (aka, each JPanel, each JFrame)?
Or is setting the look and feel once, enough to affect the whole application?
If once is enough, then where should I place the code to do so (in what class?)
You define it in the main method and it will be used everywhere.
This is the main screen's main method:
Example:
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainScreen mainWindow = new MainScreen();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
mainWindow.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Or is setting the look and feel once, enough to affect the whole application?
Correct
If once is enough, then where should I place the code to do so (in what class?)
Usually, in a class which creates the application frame (before it is created):
UIManager.setLookAndFeel(lookAndFeelName);
...
JFrame frame = new JFrame(...);
Also, you can change LnF on the fly for the whole application, if you need:
UIManager.setLookAndFeel(lookAndFeelName);
SwingUtilities.updateComponentTreeUI(frame);
frame.pack();

When is Applet.stop() called?

I experiment with my applet using Eclipse and its Applet Viewer. The Applet Viewer appears on the top of Eclipse and during Applet execution I click on Eclipse icon to maximize it from task bar. Then Applet Viewer loses the focus and Applet.stop() gets called.
When I minimize Eclipse, Applet Viewer goes to front again, gains focus and Applet.start() gets called. This ends up in a complete mess.
Is it normal behavior for a browser to call Applet.stop once user changes to another Tab or minimizes the browser Can I disable that, I want stop never been called.
Maybe I am missing something in threads.
My code is something like this:
public class AppletApp extends JApplet {
public void init() {
super.init();
System.out.println("AppletApp.init()");
}
public void start() {
System.out.println("AppletApp.start()");
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
getContentPane().add(new JLabel("Test Label"));
}
});
} catch (InterruptedException e) {
} catch (InvocationTargetException e) {}
Runnable runnable = new Runnable() {
#Override
public void run() {
//For DJ Browser Component
NativeSwing.initialize();
NativeInterface.open();
//connect to server and start message exchange
Client.init(userInterface);
userInterface.authenticate();
NativeInterface.runEventPump();
}
};
Thread t = new Thread(runnable);
t.start();
}
public void stop() {
System.out.println("AppletApp.stop()");
}
public void destroy() {
System.out.println("AppletApp.destroy()");
}
}
Is it normal behavior for a browser to call Applet.stop once user
changes to another Tab or minimizes the browser?
Yes it is normal. From the javadoc:
Called by the browser or applet viewer to inform this applet that it
should stop its execution. It is called when the Web page that
contains this applet has been replaced by another page, and also just
before the applet is to be destroyed.
When you switch tab, I consider that the containing web page has been replaced hence it is logical that stop() is invoked.
Can I disable that, I want stop never been called.
No you can't, you don't have control on that. However, you could rely on the init() and the destroy() methods instead of start() and stop(). start() and stop() are meant for resuming/pausing anything that consumes resources which are not necessary if not visible (for example an animation is pointless if not visible).

about override run() method of GUI in main method

The issue is when I close my GUI windows I wanna run a last method ( for example printList() ) but I couldn't manage to do it. This is my main method
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
patientTest2 screen = new patientTest2();
screen.setVisible(true);
screen.setResizable(false);
} catch (FileNotFoundException ex) {
Logger.getLogger(patientTest2.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
patientTest2 is my JFrame class. I assume that if I put printList() before } catch (FileNotFoundException ex) { it should work and finally print my list to a file but it doesn't. I will be glad if you can help me and explain why of course_?
You should add a listener that extends WindowAdapter to your frame, and override the method windowClosing(WindowEvent e). In this method, you will be able to call any methods you want to call before the window is closed.
You need to
change the default close operation to JFrame.DO_NOTHING_ON_CLOSE (if the window is a JFrame)
add a WindowListener to your top-level window
listen for window closing events, calling your method
and then finally exit the JVM with the appropriate exit code (usually 0 if no errors).
If you want to have something that runs when you Java VM gets shut down, then you should have a look at
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
//The stuff you want to do at shutdown.
}
}));
Please read the here for further information.
You also should set the DefaultCloseOperation of your Window if you want to close your Programm (and shutdown your Java VM) when the JFrame is closed.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This is I think what you were asking for. Hope this helps.

Catch exceptions in javax.swing application

I'm working with javax.swing to make an aplication which generates forms from XML Schema (using JAXFront library) and stores the data filled by the user them into XML documents.
I have put try-catch-finally blocks when I need it, but I have a little problem catching exceptions when the main thread ends (The AWT threads are still running).
I have two classes which do the main work and other classes which aren't important for the question:
Main class: It has the following structure. Initializes the application and runs the main frame
public class Main {
public static void main(String[] args) {
readArgs(); // An INI file with the app config
Model model = initializeElements(args); // My model class
try {
MyFrame mfr = new MyFrame(title,model);
mfr.visualize(); // Assembling view and setting visible
} catch( Excepion e ) {
doCleanUp();
System.exit(-1);
}
}
}
Frame Class: Generates the view and listen events
public class MyFrame extends JFrame implements ActionListener,MenuListener {
// Some attributes
// Other mthods without importance
/**
* Compose the elements, add listeners and set visible the frame
*/
public void visualize() {
generateFormPanel();
setListeners();
validate();
setVisible(true);
}
public MyFrame(String title, Modele model) {
super(title);
createElementsUsing(model);
}
public void actionPerformed(ActionEvent e) {
// Code to manage events
}
}
Well, the problem is the following:
When the visualize function is exectuted from the main method, the view is generated and showed. At that moment is when I lose the control of the exceptions catching. Then my question is if there are some way to catch the possible RuntimeExceptions throwed after this point.
I hope you understand my English and can answer the question.
Thanks in advance.
Simplest version is to set the default uncaught exception handler:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
// do something
}
});
But that catches uncaught exceptions thrown in other parts of the program aswell.
You could however catch only runtime exceptions thrown off the swing event dispatching thread using a proxy (See this page for more information, copied code from there):
class EventQueueProxy extends EventQueue {
protected void dispatchEvent(AWTEvent newEvent) {
try {
super.dispatchEvent(newEvent);
} catch (Throwable t) {
// do something more useful than: t.printStackTrace();
}
}
}
Now installing it like this:
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new EventQueueProxy());
After you have called visualize() the only thread running is the Swing/AWT event dispatch thread. If you want to catch any exceptions you will need to do so in any of your listener methods that are called on this thread e.g.
public void actionPerformed(ActionEvent e) {
try {
// Some code here
} catch(RuntimeException e) {
// Handling code here
}
}
To prevent boilerplate you can have this code in a super class.
Note that you can also set a default uncaught exception handler if you want to catch anything not already dealt with by the Swing/AWT thread.
Note also that in general it is best practice to not catch subclasses of RuntimeException if you can avoid it.
Try adding:
setDefaultCloseOperation(EXIT_ON_CLOSE);
to MyFrame constructor. Not sure though, but worth trying.

Categories

Resources