Swing/PersistenceService の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/PersistenceService へ行く。
- Swing/PersistenceService の差分を削除
--- category: swing folder: PersistenceService title: PersistenceServiceを使ってJFrameの位置・サイズを記憶 tags: [ServiceManager, PersistenceService, JFrame, SwingWorker, XMLEncoder, XMLDecoder, Preferences] author: aterai pubdate: 2012-03-26T15:45:39+09:00 description: ServiceManagerからPersistenceServiceを取得し、JFrameなどの位置・サイズの保存、呼び出しを行います。 image: https://lh6.googleusercontent.com/-PyOW5DW5kHU/T3APD_Cq_bI/AAAAAAAABKk/i9eivMuQZ0Y/s800/PersistenceService.png --- * 概要 [#summary] `ServiceManager`から`PersistenceService`を取得し、`JFrame`などの位置・サイズの保存、呼び出しを行います。 #download(https://lh6.googleusercontent.com/-PyOW5DW5kHU/T3APD_Cq_bI/AAAAAAAABKk/i9eivMuQZ0Y/s800/PersistenceService.png) * サンプルコード [#sourcecode] #code(link){{ class LoadSaveTask extends SwingWorker<WindowAdapter, Void> { private final WindowState windowState; public LoadSaveTask(WindowState windowState) { super(); this.windowState = windowState; } @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) { ps = null; bs = null; } if (ps == null || bs == null) { return null; } else { final PersistenceService persistenceService = ps; final URL codebase = bs.getCodeBase(); loadWindowState(persistenceService, codebase, windowState); return new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { JFrame f = (JFrame) e.getComponent(); if (f.getExtendedState() == Frame.NORMAL) { windowState.setSize(f.getSize()); windowState.setLocation(f.getLocationOnScreen()); } saveWindowState(persistenceService, codebase, windowState); } }; } } 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(); } } } 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(); } } } }} * 解説 [#explanation] - `JFrame`の位置とサイズを`PersistenceService`で確保したファイルに`XMLEncoder`で保存、`XMLDecoder`でそのファイルから値を復元 - `Windows`環境では`C:\Users\(user)\AppData\LocalLow\Sun\Java\Deployment\cache\6.0\muffin`以下に次のような`muf`ファイルが作成される #code{{ <?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`を設定し、警告を捨ててしまう #code{{ import java.awt.*; import java.awt.event.*; import java.beans.*; import java.io.*; import java.nio.charset.StandardCharsets; 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), StandardCharsets.UTF_8)) { textArea.read(fr, "File"); } catch (Exception ex) { ex.printStackTrace(); } add(new JScrollPane(textArea)); } public static void main(String... args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } public static void createAndShowGUI() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } JFrame frame = loadFrame(); frame.setVisible(true); } private static JFrame loadFrame() { JFrame frame = null; try (XMLDecoder d = new XMLDecoder(new BufferedInputStream( new FileInputStream(PROPERTIES_XML)))) { 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(); frame.removeWindowListener(this); File file = new File(PROPERTIES_XML); try (XMLEncoder xe = new XMLEncoder(new BufferedOutputStream( new FileOutputStream(file)))) { xe.setExceptionListener(new ExceptionListener() { @Override public void exceptionThrown(Exception exception) { // XXX: exception.printStackTrace(); } }); xe.writeObject(frame); // xe.flush(); xe.close(); } catch (Exception ex) { ex.printStackTrace(); } } }); return frame; } } }} * 参考リンク [#reference] - [http://pscode.org/jws/api.html JWS javax.jnlp.* API demos] - [https://docs.oracle.com/javase/jp/8/docs/technotes/guides/javaws/developersguide/examples.html#PersistenceService PersistenceServiceサービスの使用] // - [http://www.finnw.me.uk/persistencetest.html PersistenceService Demo] - [[JFrameの位置・サイズを記憶する>Swing/Preferences]] - [[JTableのモデルをXMLファイルで保存、復元する>Swing/PersistenceDelegate]] * コメント [#comment] #comment - `JScrollPane` + `JTable` + `DefaultTableModel`を`XMLEncoder`で`XML`書出しする場合のエラーなどについて: [http://wiki.byte-welt.net/wiki/JTable_speichern JTable speichern – Byte-Welt Wiki] -- &user(aterai); &new{2013-11-14 (木) 19:06:49}; java.lang.InstantiationException: javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler Continuing ... java.lang.Exception: XMLEncoder: discarding statement JTableHeader.removeMouseMotionListener(BasicTableHeaderUI$MouseInputHandler); Continuing ... java.lang.InstantiationException: javax.swing.plaf.basic.BasicTableUI$Handler Continuing ... java.lang.Exception: XMLEncoder: discarding statement JTable.removeMouseMotionListener(BasicTableUI$Handler); Continuing ... #comment