I am trying to serialize a JFrame containing a JDesktopPane with several JInternalFrames.
I encountered a problem with the LookAndFeel because for any reason it is not possible to serialize a Swing component with a to the CrossPlatform LnF different one.
So I wrote this test program in order to figure out my possibilites:
public static void main(String[] args) {
try {
JFrame f = new JFrame();
f.setBounds(200,200,200,200);
JTree tree = new JTree();
f.add(tree);
f.setVisible(true);
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(f);
ObjectOutputStream oop = new ObjectOutputStream(
new FileOutputStream(new File("test.serialized")));
oop.writeObject(f);
} catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This didn't work for two reasons:
I am not able to serialize the frame and the contained tree. Just the tree is fine but just when
I set the LookAndFeel to cross platform in the first place and create my tree afterwards.
Any idea how to fix this?
EDIT:
Sorry for making this not clear:
I am NOT trying to serialize the LnF or something like that.
The LnF doesnt want me to serialize the Frame.
java.io.NotSerializableException: com.apple.laf.AquaTreeUI
And on top of that i am not able to serialize a Frame that contains a Tree.
Exception in thread "AWT-EventQueue-0" java.lang.InternalError: incorrect component
What you are trying is not possible. When you serialize the JFrame object, the LnF is not serialized in any way. That is because the JFrame keeps no memory of this. What LnF is used is stored elsewhere...
What I would do is wrap the JFrame in another object, let's say MyGUI. Inside that, I would store the LnF (as a String for example) in a private field. In the end, serialize MyGUI and, at deserialization, you have the LnF nice and intact and you can set it again.
Check this. Is the implementation proposed by #SoboLAN.
Related
What is the purpose of catching a FileNotFound and IOException when the FileNotFoundException is covered by IOException?
Examples:
try {
pref.load(new FileInputStream(file.getAbsolutePath()));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
as opposed to:
try {
pref.load(new FileInputStream(file.getAbsolutePath()));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Is it simply to enable different code to be executed if a FileNotFoundException is thrown? Or is there a different reason?
EDIT: What are a few examples of what an IOException could be thrown for? (Besides a FileNotFoundException)
It allows you to specifically handle that case. Perhaps your application needs to do something specific when a file is not found. Such as notify the user that a file was not found, rather then just a generic error.
So basically, yes, it allows different code to be executed specifically when a FileNotFoundException is thrown.
It has to, because you assigning the task for the particular FileNotFound Exception error.
If you do as IOException, user may not get the right information what went wrong in there. so doing in separate way, user come to know exactly what happening in the code.
I am trying to revise a java code to write something into a txt file. The original code is:
try {
out = new PrintStream(system.out, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I use FileOutputStream to do this, and revise the code to:
try {
FileOutputStream os = new FileOutputStream("wiki.txt", true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But it doesn't work, the error is:
Wikipedia2Txt.java:56: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
FileOutputStream os = new FileOutputStream("wiki.txt");
^
1 error
I try two ways: 1, I make a wiki.txt file manually on disk; 2, no wiki.txt exist before run the code.
But either doesn't work. It just stopped when compiled.
So what is going on?
Thanks.
Java is not telling you that the file is not found, just that it may not be found at runtime, and your program is not ready to handle it.
Here is one way to address this:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException fnf) {
// TODO Auto-generated catch block
fnf.printStackTrace();
}
Here is another way:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (IOException e) {
// TODO Auto-generated catch block
fnf.printStackTrace();
}
The first way ensures the compiler that your code is prepared to handle both exceptions separately; the second way ensures the compiler that your code is prepared to handle a superclass of both exceptions. The two ways are not the same, because the second one covers more exceptions that the first one.
Finally, there is an alternative to silence the compiler by declaring your function with a throws block (either a common superclass or the two individual classes would do). This is a way to tell the compiler that your function has no idea of how to handle these exceptions, and that they should be handled by a caller. The consequence of this approach is that every caller of your function must put a try/catch around the call, or declare the exceptions using throws.
The signature of the FileOutputStream constructor that you're using is public FileOutputStream(File file) throws FileNotFoundException. This means it is a checked exception which you have to handle. Therefore make sure that your method in which you have written this code either handles this exception (i.e. specify this exception as part of the catch block) or you specifically throw this exception.
So either of the following would work for you:
Specify in catch block
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Or make your method throw this exception - so your method signature would be something like return_type method_name (params_list) throws FileNotFoundException
You need to handle the situation when the file is not found.
Try this:
try {
File file = (..your code..)
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// Handling a situation when file is not found.
e.printStackTrace();
}
Your IDE (for instance Eclipse, IDEA, NetBeans) should provide additional help in such situations. As you have generated stubs, you are probably already using IDE. Isn't your code red-underlined?
You are just trampling upon one of the sore spots of Java: checked exceptions. There's a myriad of exceptions that may happen when your code is running, but only some of them must be declared in advance. My preferred way to handle your piece of code would be to wrap any and all checked exceptions into a RuntimeException that you can handle somewhere else up the stack trace:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
In most cases handling exceptions right at the spot where they happen is wrong and leads to swallowed exceptions and generally unreliable, hard-to-debug code.
In a well-engineered application all exceptions that represent a failure—rather than an expected alternative situation—must be propagated up the stack frame towards the so-called exception barrier, where all failures are uniformly handled.
I had a problem that I posted before but got no clear solution
How to prevent JFrame from closing.
So I am posting a SSCCE may be this might help in better understanding the problem being faced
package myApp;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JFrame;
import App2.Applic2;
public class MYApp {
#SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String arg[]){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Application frame 1");
f.setSize(200,200);
f.setVisible(true);
Class cls = Applic2.class;
Object[] actuals = { new String[] { "" } };
Method m = null;
try {
m=cls.getMethod("main", new Class[] { String[].class } );
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
m.invoke(null,actuals);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
second package
package App2;
import javax.swing.JFrame;
public class Applic2 {
#SuppressWarnings("unused")
public static void main(String args[]){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(200,200);
f.setVisible(true);
f.setTitle("This needs not to be changed");
NewFrame3 Frame3 = new NewFrame3();
}
}
Second class of App2 package.
package App2;
import javax.swing.JFrame;
public class NewFrame3 {
public NewFrame3(){
JFrame f = new JFrame();
f.setTitle("f3");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(200,200);
f.setLocation(200, 200);
f.setVisible(true);
}
}
MYAPP invokes instance of Applic2 which further invokes instance of NewFrame3. Like we can see if I close instance of 'NewFrame3' or instance of Applic2 the entire program closes (due to EXIT_ON_CLOSE) statement.
I want a solution in which MYAPP should not close on closing Applic2 or NewFrame3.
I cannot make any changes to APPlic2 or NewFrame3. via reflection If we try to turn EXIT_ON_CLOSE to DISPOSE_ON_CLOSE How do we access these frames and their setDefaultCloseOperation() when we do not have our classes extended JFrames ?
In another solution as mentioned a new JVM instance should be created and Applic2 should be executed in a new process on this new JVM instance. but then I encountered that runtime.exec takes Java commands as input and not Java statements like method.invoke().
I have access to the Applic2 via loader that loaded Applic2 I can only access the class files of Applic2 in memory so no way I can use jar to run in runtime.exec(). Now how do I solve it?
Adding these statements to MYApp classensures that on clicking close button of a frame nothing happens but this does not seem the be the case
Frame[] f2 = JFrame.getFrames();
for(Frame fx: f2){
System.out.println(fx.getTitle());
fx.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we){
}
});
and this code needs to be added to the last frame that was instantiated else it does returns all frames. i.e, if this frame is added to JFrame3 class all instantiated frames are returned if added to MyApp JFrame in MyApp is returned and if added Applic2 then frames instantiated in MYApp and Applic2 are returned. Why this behaviour ??
You could use JFrame.getFrames() which returns an array of Frame (you could also getWindows() for a much lower level list of those windows created within the current application context).
Then, you need to walk through, checking each frame to see if it meets your requirements. After, that, you don't need reflection, you gain direct access to the frames
The only only way to communicate with other JVM's is via socket comms (such as RMI).
UPDATE WITH EXAMPLE
Frame[] listOfFrames = JFrame.getFrames();
for (Frame : listOfFrames) {
if (frame instanceof JFrame) {
JFrame aFrame = (JFrame)frame;
}
}
Cross Process Communications is not a simple thing. Basically, each process you want to talk to needs to have a ServerSocket with which it can accept incoming requests. If you want to perform two way communication, each process would need to have it's own ServerSocket, this will allow ANY process to start the communications.
This raises issues with port numbers and the like, but you could actually do a muticast to over come that (basically, "hay everybody, I'm here, come talk to me") which could be used to determine who's available or not - take a look at Broadcasting to Multiple Recipients for an example.
So. When you're ready, you would open a socket connection to the process in question (localhost/127.0.0.1) on it's port and start chatting.
Now. The problem I see with what you've described, is the fact that in order to get this to run, you're going to need some kind of launcher that can create the server socket and then execute the existing program (as you've already described), which raises the question of why? If you're only goal is to get these frames to stop closing your application, simply launching the program in a new JVM achieves that goal. Obviously, if you still need more information from them, then that's a reasonable excuse for all the hard work.
Now, the good news, you can serialize objects across sockets (that is, you can send Java objects via the socket connection), check Discover the secrets of the Java Serialization API for more info.
Now, if that hasn't scared you off, check out All About Sockets for more information.
And finally, the big question of "how" to execute a new JVM, check out Java ProcessBuilder, it actually describes a means by which you can execute a new JVM!!
So have completed the solution with the help provided by MadProgrammer amd mKorbel and here is the updated MYApp class
package myApp;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JFrame;
import App2.Applic2;
public class MYApp {
#SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String arg[]){
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Application frame 1");
f.setSize(200,200);
f.setVisible(true);
Class cls = Applic2.class;
Object[] actuals = { new String[] { "" } };
Method m = null;
try {
m=cls.getMethod("main", new Class[] { String[].class } );
Method[] m1 =Frame.class.getDeclaredMethods();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
m.invoke(null,actuals);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Frame[] f2 = JFrame.getFrames();
// Window[] f23= JFrame.getFrames();
for(Frame fx: f2){
System.out.println(fx.getTitle());
// fx.setVisible(false);
if (fx instanceof JFrame) {
JFrame aFrame = (JFrame)fx;
aFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}
}
}
I know this site isn't made for questions like this but I've been searching for the answer to this I haven't found anything and I need a confirmations.
I have a singleton class which is the centre of my program, in some situations I try to save its state, however it seems it doesn't save properly, and I don't see why because It's not the first time I do this, however It is the first time I try to save a singleton, so is it possible to save a singleton object?
Here are my loading and saving codes of this object
public void Loading(String name) {
ObjectInputStream is = null;
//ignore this variable
game_loaded = 1;
try {
is = new ObjectInputStream(new FileInputStream(name + ".dat"));
//Logica is the singleton class,
//logi is the name of the variable where it is
logi = (Logica) is.readObject();
} catch (FileNotFoundException e1) {
JOptionPane.showOptionDialog(frame, "Game Invalid", "Load",
JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE,
null, new String[] { "Ok" }, "Ok");
return;
} catch (IOException e1) {
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
}
JOptionPane.showOptionDialog(frame, "Game Loaded Sucessfully", "Load",
JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE,
null, new String[] { "Ok" }, "Ok");
}
Save:
public void saving(String nome){
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream(new FileOutputStream(nome+".dat"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
return;
} catch (IOException e) {
// TODO Auto-generated catch block
return;
}
try {
os.writeObject(Logica.getLogica(null));
} catch (IOException e) {
// TODO Auto-generated catch block
return;
}
JOptionPane.showOptionDialog(frame, "Game Saved sucessfully", "Load",
JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE,
null, new String[] { "Ok" }, "Ok");
if (os != null)
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
EDIT
Ok I may have explained corretcly, it doesn't give me any error loading, however it doesn't load the state I saved, it loads an new "Logica" as if I had created a new one
There's nothing about Singleton per se that says it can't be serialized; you can write incorrect serialization code for any class. It's not clear what's wrong, and I'm not willing to pore over your code to figure it out, but it should be possible to do.
You have an empty catch block for IOException. That's always a bad idea. You've swallowed the exception that might explain everything. Print the stack trace.
The situation you have described is not possible. Ergo you haven't described it correctly. Probably there is something wrong with your observations.
I strongly suspect an IOException or FileNotFoundException, despite your comment in another answer. You have posted code that ignores exceptions in at least four separate places. The presumption is overwhelming.
In fact your exception handling needs a lot of work. You aren't closing the file in case of exceptions for example. There are no finally blocks. You have multiple try/catch blocks where you should have one try and several catches.
Further questions along other lines of enquiry. Is the file being created? With non-zero length? Or else maybe the singleton class only has transient fields?
How can I make a hyperlink in a JFace Dialog that when clicked opens the link in the default web browser. A full example would be useful. I know there is a org.eclipse.jface.text.hyperlink package but I can't find a suitable example.
Are you running an RCP application?
If so, then the following code will open your link in the default OS browser:
// 'parent' is assumed to be an SWT composite
Link link = new Link(parent, SWT.NONE);
String message = "This is a link to Google";
link.setText(message);
link.setSize(400, 100);
link.addSelectionListener(new SelectionAdapter(){
#Override
public void widgetSelected(SelectionEvent e) {
System.out.println("You have selected: "+e.text);
try {
// Open default external browser
PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(new URL(e.text));
}
catch (PartInitException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
catch (MalformedURLException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
});
The above assumes that you do not want to scan existing text for hyperlinks but simply wish to create one programmatically. If the former is required then you'll need to use the API from JFace text packages or suchlike.