Javatterβでショートカットキー
別にJavatterβじゃなくてもいいです。
メソッド
public void addShortCut(int keyCode, int modifies, ActionListener... listeners) { JFrame frame = getMainView().getMainFrame(); JMenuBar menuBar; if ((menuBar = frame.getJMenuBar()) == null) { menuBar = new JMenuBar(); menuBar.setPreferredSize(new Dimension(0, 0)); frame.setJMenuBar(menuBar); } JMenu menu; if (menuBar.getMenuCount() < 1) { menu = new JMenu(); menuBar.add(menu); } else { menu = menuBar.getMenu(0); } JMenuItem item = new JMenuItem(); item.setAccelerator(KeyStroke.getKeyStroke(keyCode, modifies)); for (ActionListener listener : listeners) item.addActionListener(listener); menu.add(item); }
使用
// Ctrl+Enter addShortCut(KeyEvent.VK_Enter, KeyEvent.KeyEvent.CTRL_DOWN_MASK, listener0); // A (non-modifies key) addShortCut(KeyEvent.VK_A, 0, listener1);
InputBoxプラグインでこだわったこと
制作秘話的なアレ。
続きを読むSwingでショートカットキー
ソースコードを見て察してください。
JMenuBar menuBar = new JMenuBar(); menuBar.setPreferredSize(new Dimension(0, 0)); JMenu menu1 = new JMenu("File"); JMenuItem item1 = new JMenuItem("Open"); item1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK)); item1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("ok"); } }); menu1.add(item1); menuBar.add(menu1); dialog.setJMenuBar(menuBar);
JMenuが必要なら項目のサイズでも変更しとけばいいんじゃないですかね(適当)
pandocがすごい
様々なフォーマットのテキストから様々な形式のドキュメントに変換してくれるpandocが今アツい。
私の中で。
Java switchの各caseのスコープ
条件分岐に使うswitch文。
Java7で文字列にも対応してより一層使い所が増えました。
が、こんな落とし穴が。
間違った例
switch (value) { case "yes": int val = 0; resultModel.setValue(val); logger.info("val" + val); break; case "no": int val = 1; resultModel.setValue(val); logger.info("val" + val); break; case "cancel": logger.info("cancelled"); break; default: logger.info("invalid value" + value); break; }
実はこれ、エラーが出ます。
case "yes": int val = 0; // これ
と
case "no": int val = 1; // これ
が競合してる、というのです。
ぱっと見では違うスコープなので競合は起こらないように見えます。
しかも競合してるくせしてno側ではyes側のvalは使えないのです。なんじゃそりゃ。
解決策
switch (value) { case "yes": { int val = 0; resultModel.setValue(val); logger.info("val" + val); break; } case "no": { int val = 1; resultModel.setValue(val); logger.info("val" + val); break; } case "cancel": { logger.info("cancelled"); break; } default: { logger.info("invalid value" + value); break; } }
( ^ω^)こうじゃ
これで別のスコープと判断され、競合は起こらなくなります。
非常に面倒です。
スコープは波括弧内、というのは基本中の基本なのですが忘れがちです。気をつけましょう。
やめてそんなこともわからないのかハゲって言いながら石を投げないで
参考:java - Variable's scope in a switch case - Stack Overflow
JavatterFXでウィンドウ閉じてもVMが終了しない問題あれこれ
JavatterFXの終了処理はウィンドウを閉じた時にJavaFXのスレッドを終了させるだけのものなので、Swingとかでウィンドウを表示させてるとスレッドが残り続けて、VMが終了しません。
ウィンドウが一回限りの表示なら
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
でOKなのですが、再利用する場合はそうもいきません。
なのでメインウィンドウの終了イベントにハンドラをぶち込んでMainWindowCloseEventを発火させました。
このイベントは自作です。発火時のDateのみを持ちます。
メインクラス
EventHandler<WindowEvent> handler = new EventHandler<WindowEvent>() { @Override public void handle(WindowEvent windowEvent) { Platform.exit(); windowEvent.consume(); EventManager.INSTANCE.eventFire(new MainWindowCloseEvent()); } }; Main.getStage().addEventHandler(WindowEvent.WINDOW_CLOSE_REQUEST, handler);
Windowを継承したクラス
@EventHandler public void onWindowClose(MainWindowCloseEvent event) { this.dispose(); }
JavaFX Image to Swing Image
というおはなし。
ちょっとググったらすぐ見つかったので備忘録として。
変換するメソッドを置いとくのでご自由にどうぞどうぞ。
/** * JavaFXのImageをSwingのImageIconに変換します. * @param fximage JavaFXのImage * @return SwingのImageIcon */ public static ImageIcon fromFXImage(javafx.scene.image.Image fximage) { BufferedImage icon = SwingFXUtils.fromFXImage(fximage, null); return new ImageIcon(icon); }