Swing/PersistenceService のバックアップの現在との差分(No.14)
- category: swing folder: PersistenceService title: PersistenceServiceを使ってJFrameの位置・サイズを記憶 tags: [ServiceManager, PersistenceService, JFrame, SwingWorker, XMLEncoder, XMLDecoder] tags: [ServiceManager, PersistenceService, JFrame, SwingWorker, XMLEncoder, XMLDecoder, Preferences] author: aterai pubdate: 2012-03-26T15:45:39+09:00 description: ServiceManagerからPersistenceServiceを取得し、JFrameなどの位置・サイズの保存、呼び出しを行います。 image:
概要
概要
ServiceManager
からPersistenceService
を取得し、JFrame
などの位置・サイズの保存、呼び出しを行います。
Screenshot
Advertisement
サンプルコード
サンプルコード
#spandel
final WindowState ws = new WindowState();
#spanend
#spandel
SwingWorker<WindowAdapter,Void> worker = new SwingWorker<WindowAdapter,Void>() {
#spanend
#spanadd
class LoadSaveTask extends SwingWorker<WindowAdapter, Void> {
#spanend
private final WindowState windowState;
#spanadd
#spanend
public LoadSaveTask(WindowState windowState) {
super();
this.windowState = windowState;
}
#spanadd
#spanend
@Override public WindowAdapter doInBackground() {
PersistenceService ps;
BasicService bs;
try{
bs = (BasicService)ServiceManager.lookup("javax.jnlp.BasicService");
ps = (PersistenceService)ServiceManager.lookup("javax.jnlp.PersistenceService");
}catch(UnavailableServiceException use) {
use.printStackTrace();
try {
bs = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");
ps = (PersistenceService) ServiceManager.lookup("javax.jnlp.PersistenceService");
} catch (UnavailableServiceException use) {
ps = null;
bs = null;
}
if(ps != null && bs != null) {
if (ps == null || bs == null) {
return null;
} else {
final PersistenceService persistenceService = ps;
final URL codebase = bs.getCodeBase();
loadWindowState(persistenceService, codebase, ws);
loadWindowState(persistenceService, codebase, windowState);
return new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
JFrame f = (JFrame)e.getComponent();
if(f.getExtendedState()==JFrame.NORMAL) {
ws.setSize(f.getSize());
ws.setLocation(f.getLocationOnScreen());
JFrame f = (JFrame) e.getComponent();
if (f.getExtendedState() == Frame.NORMAL) {
windowState.setSize(f.getSize());
windowState.setLocation(f.getLocationOnScreen());
}
saveWindowState(persistenceService, codebase, ws);
saveWindowState(persistenceService, codebase, windowState);
}
};
}else{
return null;
}
}
@Override public void done() {
WindowAdapter wa = null;
try{
wa = get();
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e) {
e.printStackTrace();
#spanadd
#spanend
private static void loadWindowState(
PersistenceService ps, URL codebase, WindowState windowState) {
try {
FileContents fc = ps.get(codebase);
try (XMLDecoder d = new XMLDecoder(
new BufferedInputStream(fc.getInputStream()))) {
@SuppressWarnings("unchecked")
Map<String, Serializable> map = (Map<String, Serializable>) d.readObject();
windowState.setSize((Dimension) map.get("size"));
windowState.setLocation((Point) map.get("location"));
}
} catch (IOException ex) {
try {
long size = ps.create(codebase, 64000);
System.out.println("Cache created - size: " + size);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
JFrame frame = new JFrame();
if(wa!=null) frame.addWindowListener(wa);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainPanel());
frame.setSize(ws.getSize());
frame.setLocation(ws.getLocation());
frame.setVisible(true);
}
#spandel
};
#spanend
#spandel
worker.execute();
#spanend
#spanadd
#spanend
private static void saveWindowState(
PersistenceService ps, URL codebase, WindowState windowState) {
try {
FileContents fc = ps.get(codebase);
try (XMLEncoder e = new XMLEncoder(
new BufferedOutputStream(fc.getOutputStream(true)))) {
HashMap<String, Serializable> map = new HashMap<>();
map.put("size", (Serializable) windowState.getSize());
map.put("location", (Serializable) windowState.getLocation());
e.writeObject(map);
e.flush();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#spanadd
}
#spanend
View in GitHub: Java, Kotlin解説
上記のサンプルでは、PersistenceService
で確保したファイルに、HashMap<String, Serializable>
に格納したJFrame
の位置、サイズをXMLEncoder
、XMLDecoder
を使って読み書きしています。
解説
-
JFrame
の位置とサイズをPersistenceService
で確保したファイルにXMLEncoder
で保存、XMLDecoder
でそのファイルから値を復元 -
Windows
環境ではC:\Users\(user)\AppData\LocalLow\Sun\Java\Deployment\cache\6.0\muffin
以下に次のようなmuf
ファイルが作成される
- -
-
Windows 7
、JDK 1.7.0_03
では、C:\Users\(user)\AppData\LocalLow\Sun\Java\Deployment\cache\6.0\muffin
以下にmuf
ファイルなどが作成されるようです。
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_03" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>location</string>
<object idref="Point0"/>
</void>
<void method="put">
<string>size</string>
<object idref="Dimension0"/>
</void>
</object>
</java>
- -
XMLEncoder
で直接上記のJFrame
を書きだす場合、以下のようなIllegalAccessException
が発生する
java.lang.IllegalAccessException: Class sun.reflect.misc.Trampoline can not access a member of class MainPanel$2 with modifiers "" Continuing ...
- 回避方法
WindowListener
を実装する匿名内部クラスをpublic class
(Java Beans
)に変更する- または、
removeWindowListener
で取り除く - または、
XMLEncoder#setExceptionListener(...)
で、何もしないExceptionListener
を設定し、警告を捨ててしまう
#spandel
//package example;
#spanend
#spandel
//-*- mode:java; encoding:utf-8 -*-
#spanend
#spandel
// vim:set fileencoding=utf-8:
#spanend
#spandel
//@homepage@
#spanend
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
#spanadd
import java.nio.charset.StandardCharsets;
#spanend
import javax.swing.*;
public class MainPanel extends JPanel {
private static final String PROPERTIES_XML = "properties.xml";
public MainPanel() {
super(new BorderLayout());
JTextArea textArea = new JTextArea();
try(Reader fr = new InputStreamReader(
new FileInputStream(PROPERTIES_XML), "UTF-8")) {
try (Reader fr = new InputStreamReader(
new FileInputStream(PROPERTIES_XML), StandardCharsets.UTF_8)) {
textArea.read(fr, "File");
} catch (Exception ex) {
ex.printStackTrace();
}
add(new JScrollPane(textArea));
}
public static void main(String[] args) {
#spanadd
#spanend
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
#spanadd
#spanend
public static void createAndShowGUI() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
JFrame frame = loadFrame();
frame.setVisible(true);
}
#spanadd
#spanend
private static JFrame loadFrame() {
JFrame frame = null;
try(XMLDecoder d = new XMLDecoder(new BufferedInputStream(
//MainPanel.class.getResourceAsStream(PROPERTIES_XML)))) {
try (XMLDecoder d = new XMLDecoder(new BufferedInputStream(
new FileInputStream(PROPERTIES_XML)))) {
#spandel
#spanend
frame = (JFrame)d.readObject();
//d.close();
frame = (JFrame) d.readObject();
// d.close();
} catch (Exception ex) {
ex.printStackTrace();
}
if (frame == null) {
frame = new JFrame("title");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainPanel());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
}
frame.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
JFrame frame = (JFrame)e.getComponent();
JFrame frame = (JFrame) e.getComponent();
frame.removeWindowListener(this);
File file = new File(PROPERTIES_XML);
try(XMLEncoder xe = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream(file)))) {
try (XMLEncoder xe = new XMLEncoder(new BufferedOutputStream(
new FileOutputStream(file)))) {
xe.setExceptionListener(new ExceptionListener() {
@Override public void exceptionThrown(Exception exception) {
//XXX:
// XXX:
exception.printStackTrace();
}
});
xe.writeObject(frame);
xe.flush();
// xe.flush(); xe.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
return frame;
}
}
参考リンク
参考リンク
- JWS javax.jnlp.* API demos
- PersistenceService
- PersistenceService Demo
- PersistenceServiceサービスの使用
- JFrameの位置・サイズを記憶する
- JTableのモデルをXMLファイルで保存、復元する