ããã®è¨äºã¯ãJavaFX Advent Calendar 2015 ã®äºæ¥ç®ã®è¨äºã§ããä¸æ¥ç®ã®JavaFXで流れるHello world - Qiitaãå®ã¯ç§ãæ¸ãã¦ãã¾ããä¸æ¥ç®ã¯@btnrougeããã®MSI/EXE インストーラ版 Scene Builder を HiDPI 対応させるには - notepadã§ãã
ãä»å¹´ã®æ¥ãJJUG CCC 2015 Springã«ããã¦ãJavaFXã°ã©ãã£ãã¯ã¹ã¨ã¢ãã¡ã¼ã·ã§ã³å
¥é ãã¹ã¯ãããã«ã¢ããã°æè¨ãåºãã¦ã¿ãããã®çºè¡¨ãè¡ãã¾ããã
http://d.hatena.ne.jp/torutk/20150412/p1
ãã¢ããã°æè¨ã®æ§æã¯ãå·¦ã®å³ã®ããã«ãªãã¾ãããããä½æããã¦ã£ã³ãã¦æ ãèæ¯ãéæåãã¦ããã¹ã¯ãããã«è¡¨ç¤ºããæè¨ãä½ããã¨ãããã®ã§ããããã®ã¨ãã¯ãæè¨ã®è¡¨ç¤ºï¼æç»ï¼ãå®è£ ããã®ã«ä¸æ¯ã§ãã¿ããããã«å¯¾å¿ã¾ã§ã¯æãåã£ã¦ãã¾ããã§ããã
ããã®å¾ãã¡ãã£ã¨ãã¤ã¿ããããã«æä½ã追å ããããããªæåãããã¹ã¦ã¿ããã¨ãã¦ããããä¸éãã®å¯¾å¿ãã§ããããã«ãªãã¾ãããæ¬æ¥ã¯ã¿ããããã«å¯¾å¿ã®å 容ãç°¡åã«ç´¹ä»ãã¾ãã
ã¿ããããã«ã®æä½ç¨èª
ãæåã«ãã¿ããããã«ã®æä½ç¨èªãæ´çãã¾ããã¿ããããã«ã®æä½ã«ã¯ãä¼¼ããããªè¨èã¨æä½ãå¤æ°è¦ããã¾ããä¾ãã°ã¿ããããã«ä¸ãä¸ç®æ触ãæä½ã«å¯¾ãã¦ã¯ãã¿ãããã¿ããã§ããã¨ããä¸ç®æãé·æ¼ãããæä½ã«å¯¾ãã¦ã¯ããã³ã°ã¿ãããã¿ããã»ã¢ã³ãã»ãã¼ã«ãã§ããã¨ããã¿ããããã«ä¸ã§æã触ã£ãã¾ã¾ãããæä½ã«å¯¾ãã¦ã¯ããã©ãã°ãããªãã¯ãã¹ã¯ã¤ãã§ããã¨ãã§ãã
æä½å 容 | Appleç¨èª | Androidç¨èª | Microsoftç¨èª | JavaFXç¨èª |
---|---|---|---|---|
1æ¬æã§è§¦ãããã«é¢ã | ã¿ãã | ã¿ãã | ã¿ãã | ã¿ãã |
1æ¬æã§è§¦ãããã«é¢ãã2åé£ç¶ | ããã«ã¿ãã | ããã«ã¿ãã | ||
1æ¬æã§è§¦ã£ãã¾ã¾ããã | ãã©ãã° | ãã©ãã°ãã¹ã¯ã¤ã | ã¹ã©ã¤ã | ã¹ã¯ãã¼ã« |
1æ¬æã§è§¦ã£ã¦ã¯ãã | ããªã㯠| ããªã³ã° | ã¹ã¯ã¤ã | ã¹ã¯ã¤ã |
2æ¬æã§è§¦ã£ãã¾ã¾éãåºãã | ãã³ããªã¼ãã³(ãã³ãã¢ã¦ã) | ãã³ããªã¼ãã³ | ã¹ãã¬ãã | ãºã¼ã |
2æ¬æã§è§¦ã£ãã¾ã¾éãçãã | ãã³ãã¯ãã¼ãº(ãã³ãã¤ã³) | ãã³ãã¯ãã¼ãº | ãã³ã | ãºã¼ã |
1æ¬æã§è§¦ããã°ãããã¦é¢ã | ã¿ããã»ã¢ã³ãã»ãã¼ã«ã | ãã³ã°ãã¬ã¹ | é·æ¼ã | |
2æ¬æã§è§¦ã£ãã¾ã¾å転ããã | å転 | ãã¼ãã¼ã | å転 | å転 |
ä¸è¿°ã®è¡¨ã®ä½æã«ã¯ã次ã®æç®ãåç §ãã¾ããã
- Mac で Multi-Touch ジェスチャを使う - Apple サポート
- フリック、ピンチイン……アップルが新しい操作の呼称を提案- Design - Material Design
- 5 タッチ対応デバイスからのイベントの使用(リリース8)
Androidç¨èªã§ã¯ãä»ã«ããã¼ãã£ã³ã¬ã¼ãã³ã°ãã¬ã¹ãã©ãã°ãªã©2æ¬æã®æä½ãå¤æ°å®ç¾©ããã¦ãã¾ããããã§ã¯å²æãã¾ããã
Microsoftç¨èªã§ãæç®ã«ãã£ã¦ã¯å¥ãªç¨èªã使ã£ã¦ãããã¨å®ã¾ã£ã¦ããªãé¨åãããããã§ãã
JavaFXããã°ã©ã ã§ã®å ¥åã¤ãã³ãã®ç¢ºèª
JavaFXã®ããã°ã©ã ã§ãçºçããå ¥åã¤ãã³ããå ¨ã¦åå¾ããã°è¡¨ç¤ºãããå ´åã¯ãStage#addEventFilterã¡ã½ããã«ã¤ãã³ã種é¡ã¨ãã³ãã©ã¼ãæå®ãã¾ãã
Applicationã¯ã©ã¹ãç¶æ¿ããã¯ã©ã¹ã®startã¡ã½ããå ã§ãå¼æ°ã«æ¸¡ãããStageã¤ã³ã¹ã¿ã³ã¹ã«å¯¾ãã¦ãã¨ããããã¤ãã³ãããã¹ã¦printlnåºåããããã«ããã³ã¼ãã次ã«ç¤ºãã¾ãã
public class AnalogClock extends Application { @Override public void start(Stage primaryStage) { : primaryStage.addEventFilter(EventType.ROOT, System.out::println); } : }
ã¢ããã°æè¨ã«å®è£ ãããã¿ããããã«æä½
ä»åãã¢ããã°æè¨ã«å®è£ ãããã¿ããããã«æä½ã¯æ¬¡ã®3ã¤ã§ãã
- ãã©ãã°ã§ãã¹ã¯ãããä¸ã®è¡¨ç¤ºä½ç½®ã移åããã
- ãã³ãï¼ãºã¼ã ï¼ã§æè¨ã®å¤§ãããå¢æ¸ããã
- é·æ¼ãã§ãããã¢ããã¡ãã¥ã¼ã表示ãããã¡ãã¥ã¼ä¸ã®é ç®ãé¸æããã
ãã©ãã°ã§ãã¹ã¯ãããä¸ã®è¡¨ç¤ºä½ç½®ã移å
ã¿ããããã«ä¸ã§ãã©ãã°æä½ãå®æ½ããã¨ãJavaFXã§ã¯TouchEventãScrollEventãMouseEventãçºçãã¾ããMouseEventã§ã¯ãMOUSE_DRAGGEDãçºçãã¾ããã
JavaFXのガイド文書「JavaFX: イベントの処理」5章 タッチ対応デバイスからのイベントの使用 ã«èª¬æãããã¾ãããå¼ç¨ãã¾ãã
ã¸ã§ã¹ãã£ããã³ã¿ãããå®è¡ãããã¨ãã«ã¯ã対å¿ããã¸ã§ã¹ãã£ã»ã¤ãã³ãã¾ãã¯ã¿ããã»ã¤ãã³ãã ãã§ãªãããã®ä»ã®ã¿ã¤ãã®ã¤ãã³ããçæã§ãã¾ããã¹ã¯ã¤ãã»ã¸ã§ã¹ãã£ã§ã¯ãã¹ã¯ã¤ãã»ã¤ãã³ãã ãã§ãªããã¹ã¯ãã¼ã«ã»ã¤ãã³ããçæããã¾ãã
ã¿ããç»é¢ã¸ã®ã¿ããã§ã¯ã対å¿ãããã¦ã¹ã»ã¤ãã³ããçæããã¾ãããã¨ãã°ãç»é¢ä¸ã®ãã¤ã³ãã«ã¿ããããã¨ãTOUCH_PRESSEDã¤ãã³ãã¨MOUSE_PRESSEDã¤ãã³ããçæããã¾ããç»é¢ä¸ã®åä¸ãã¤ã³ãã移åããã¨ãã¹ã¯ãã¼ã«ã»ã¤ãã³ãã¨ãã©ãã°ã»ã¤ãã³ããçæããã¾ããã¿ããã»ã¤ãã³ãã¾ãã¯ã¸ã§ã¹ãã£ã»ã¤ãã³ããã¢ããªã±ã¼ã·ã§ã³ã§ç´æ¥å¦çã§ããªãå ´åã§ããã¿ããã®å®è¡æã«çæããããã¦ã¹ã»ã¤ãã³ãã«å¯¾ããã¬ã¹ãã³ã¹ãçæããããã«å¤æ´ããã ãã§ãã¿ãã対å¿ããã¤ã¹ã§ã¢ããªã±ã¼ã·ã§ã³ãå®è¡ã§ããããã«ãªãã¾ãã
ã¨ãããã¨ã§ãå¾æ¥ã®ãã¦ã¹ã§ã®ãã©ãã°ã¤ãã³ãã«å¯¾å¿ãã¦ããã°ããã®ã¾ã¾ã®ã³ã¼ãã§ã¿ããããã«ä¸ã§ã®ãã©ãã°æä½ã«ã対å¿ãããã¨ãã§ãã¾ãã
ã¤ã¾ããã¿ããããã«æä½ã«å¯¾å¿ããããã¨ãã£ã¦ã¿ããããã«å°ç¨ã®ã³ã¼ããå¿
ãããæ¸ãå¿
è¦ã¯ãªãã¨ãããã¨ã§ããã
ä¸å¿ããã¦ã¹ã®ãã©ãã°æä½ã§ã¦ã£ã³ãã¦ã移åãããã³ã¼ãã次ã«ç¤ºãã¾ãã
public class AnalogClock extends Application { private double dragStartX; private double dragStartY; : @Override public void start(Stage primaryStage) { Scene scene = ... : // ãã¦ã¹ã®ãã©ãã°æä½ã§ã¦ã£ã³ãã¦ã移å scene.setOnMousePressed(e -> { dragStartX = e.getSceneX(); dragStartY = e.getSceneY(); }); scene.setOnMouseDragged(e -> { primaryStage.setX(e.getScreenX() - dragStartX); primaryStage.setY(e.getScreenY() - dragStartY); }); : }
ãã³ãï¼ãºã¼ã ï¼ã§æè¨ã®å¤§ãããå¢æ¸
ã¿ããããã«ä¸ã§ãã³ãæä½ãå®æ½ããã¨ãJavaFXã§ã¯TouchEventãScrollEventãRotateEventãZoomEventãMouseEventãçºçãã¾ããã
ä»åã¯ç´çã§ZoomEventãåå¾ããã¦ã£ã³ãã¦ãµã¤ãºã®å¤æ´ãè¡ãã¾ãã
public void start(Stage primaryStage) throws Exception { : // ã¿ããããã«ã®ãã³ãæä½ã§ã¦ã£ã³ãã¦ãµã¤ãºãå¤æ´ scene.setOnZoom(e -> { zoom(e.getZoomFactor()); }); : } private void zoom(double factor) { double scale = root.getScaleX() * factor; scale = Math.max(Math.min(scale, MAX_SCALE), MIN_SCALE); root.setScaleX(scale); root.setScaleY(scale); stage.setWidth(INITIAL_WINDOW_SIZE * scale); stage.setHeight(INITIAL_WINDOW_SIZE * scale); }
ãã¦ã¹ãã¤ã¼ã«ã§è¡¨ç¤ºãµã¤ãºå¤æ´ãå®è£ ãã¦ããå ´åã®æ³¨æç¹
ããããã¦ã¹ãã¤ã¼ã«ã§æ¡å¤§ã»ç¸®å°è¡¨ç¤ºããUIãè¦ããã¾ããå²ã¨ä½¿ãåæãããã®ã§ããã®UIã¯éå®ãã¾ããããããJavaFXã§ã¯ãã¦ã¹ãã¤ã¼ã«ãç´æ¥ã¤ãã³ãã¨ãã¦åããã¨ãã§ããªãã®ã§ããã¦ã¹ãã¤ã¼ã«ãåãããã¨ãã«çæãããScrollEventãæãã¦è¡¨ç¤ºãµã¤ãºå¤æ´ãè¡ãã¾ãã
// æè¨ã®ãµã¤ãºãå¤æ´ãã // ãã¦ã¹ã®ãã¤ã¼ã«æä½ã«ããScrollEventãé¸å¥ãã¦ã¦ã£ã³ãã¦ãµã¤ãºãå¤æ´ scene.setOnScroll(e -> { double zoomFactor = e.getDeltaY() > 0 ? 1.1 : 0.9; zoom(zoomFactor); });
ãããããã®ã³ã¼ããã¿ããããã«ä¸ã§å®è¡ããã¨ãããããªæ¯ãèãããã¦ãã¾ãã¾ããã¿ããããã«ä¸ã®ãã©ãã°ãã¹ã©ã¤ãï¼ã¹ã¯ã¤ãï¼æä½ãããã¨ãã«ãScrollEventãçºçããã®ã§ãããããã¤ã¼ã«ã¨èª¤èªãã¦ã¦ã£ã³ãã¦ãµã¤ãºãå¤æ´ãã¦ãã¾ãããã§ãã
ãã¦ã¹ã®ãã¤ã¼ã«æä½ã§çºçããScrollEventã¨ããã以å¤ï¼ã¿ããããã«ä¸ã®ãã©ãã°æä½ãªã©ï¼ã®æä½ã§çºçããScrollEventãåºå¥ãã¾ããåºå¥ããæ¹æ³ãæ¢ãã¦ã¿ãã¨ãããJavaFXのガイド文書「JavaFX: イベントの処理」5章 タッチ対応デバイスからのイベントの使用 ã«è¨è¿°ãããã¾ããå¼ç¨ãã¾ãã
ã¹ã¯ãã¼ã«ã»ã¸ã§ã¹ãã£ãå®è¡ãããã¨ãSCROLL_STARTEDãSCROLLããã³SCROLL_FINISHEDã¤ãã³ããçæããã¾ãããã¦ã¹ã»ãã¤ã¼ã«ã®ç§»åã§ã¯ãSCROLLã¤ãã³ãã®ã¿ãçæããã¾ãã
ã¾ããä½ã¨ãªãå®è£
ãã§ãã¾ãããã¤ãã³ãã®ç¶æ
ã管çããªãã¦ã¯ãªããé¢åããã§ãã
ã¨æã£ã¦ããããä»ã«ããã¡ãã£ã¨æ¥½ãªæ¹æ³ãããã¾ããããã®æ¹æ³ã¯ãã£ã¡æ°ã®ããã°ï¼æ¬¡ã®URLï¼ã«æ¸ããã¦ãã¾ããã
http://yucchi.jp/blog/?p=1750
ã¿ããã«ã¦ã³ãã¨æ £æ§ã¹ã¯ãã¼ã«ã¤ãã³ãã§æ¡å¤§ç¸®å°å¦çãè¡ããã©ããå¤æããã¦ãã¾ãã
ã¤ã¾ããScrollEventã®å±æ§ã§ã¿ããæ°ãè¦ã¦ãããã0åã§ããã°ã¿ããã§ã¯ãªããã¦ã¹ãã¤ã¼ã«æä½ã«ããã¤ãã³ãã¨å¤å®ããã ããã¹ã¯ã¤ãæä½ã§çºçããæ £æ§ã«åºã¥ãScrollEventãå«ã¾ãã¦ãã¾ãã®ã§ããããé¤å¤ãããã¨ããå¦çã«ãªãã¾ããè¨èã§ã¯è¤éã§ããã³ã¼ãã¯ifæ1ã¤ã追å ã§æ¸ã¿ã¾ãã
// æè¨ã®ãµã¤ãºãå¤æ´ãã // ãã¦ã¹ã®ãã¤ã¼ã«æä½ã«ããScrollEventãé¸å¥ãã¦ã¦ã£ã³ãã¦ãµã¤ãºãå¤æ´ scene.setOnScroll(e -> { if (e.getTouchCount() != 0 || e.isInertia()) return; // 追å è¡ double zoomFactor = e.getDeltaY() > 0 ? 1.1 : 0.9; zoom(zoomFactor); });
ï¼è¿½è¨ï¼TOUCHã¤ãã³ãã使ã£ãå¤å¥æ¹æ³
id:skrbãããWheel or Touch - JavaFX in the Boxã§ãã¿ããæä½ã«ããScrollã¤ãã³ããå¦ããå¤å¥ããæ±ç¨çãªæ¹æ³ãç´¹ä»ãã¦ãã¾ãããã®æ¹æ³ã¯ãScrollã¤ãã³ã以å¤ã§ãã¿ããæä½ãå¦ããå¤æãããã¨ãã§ããã®ã§ãã¿ããããã«UIãæ±ããªãã°ç¥ã£ã¦ããã¹ãæ¹æ³ã§ãã
é·æ¼ãã§ãããã¢ããã¡ãã¥ã¼ã表示ãããã¡ãã¥ã¼ä¸ã®é ç®ãé¸æ
ããã¯å®ç¾æ¹æ³ãåããããã°ããæ©ã¿ã¾ãããã¸ã§ã¹ãã£ã«ã¯é·æ¼ãã¯è¦å½ããããä½ã¬ãã«ãªTouchEventãè¦ãã¨ãTOUCH_STATIONARYã¨ããã¿ããã»ãã¤ã³ããæ¼ãããã¾ã¾åæ¢ãã¦ããã¨ãã«çºçããã¤ãã³ããããã¾ããã
æåãããå®è£ ãã¦ã¿ã¾ããããã¿ããããã«ä¸ã§é·æ¼ãæä½ã ãã§ãªãããã©ãã°ããã³ãã¨ãã£ãæä½ããã¦ããã¨ããæã®ç§»åãé ããªãã¨çºçãã¦ãã¾ãã¾ãã
ããããæ¢ãã¦ã¿ãã¨ãããWindows OSã®ã¿ããæ©è½ã«ãé·æ¼ããæ¤åºããã¨å³ã¯ãªãã¯ã®ã¤ãã³ããçºè¡ããããã§ãã
ããã§ãã³ã³ããã¹ãã¡ãã¥ã¼ã¨ãã¦ãããã¢ããã¡ãã¥ã¼ãç»é²ãããã¨ã§å®ç¾ãã§ãã¾ããã
ContextMenu popup = new ContextMenu(); : // ã³ã³ããã¹ãã¡ãã¥ã¼æä½ï¼OSä¾åï¼ãããã¨ãã«ããããã¢ããã¡ãã¥ã¼è¡¨ç¤º // Windows OSã§ã¯ããã¦ã¹ã®å³ã¯ãªãã¯ãtouchããã«ã®é·æ¼ãã§çºç root.setOnContextMenuRequested(e -> { popup.show(primaryStage, e.getScreenX(), e.getScreenY()); });
ãããçµå±ã¿ããããã«æä½å¯¾å¿ã¯ç´æ¥ãã¦ãã¾ããã
ã¾ã¨ãçãªãã®
JavaFXã®ã¿ããããã«æä½å¯¾å¿ã¯ãã¾ãç¨èªï¼æ©è½ãä¸ã®ä¸ä¸è¬çã«åºã¾ã£ã¦ããã¿ããããã«ã®æä½ã¨ç´æ¥å¯¾å¿ãã¦ããªããã®ãããã¾ãã
次ã«ã¿ããããã«æä½ã«ãã£ã¦ãã¿ããããã«åºæã®ã¤ãã³ãã ãã§ã¯ãªãããã¦ã¹ã¤ãã³ããçºçãã¾ãããã®ããããææ¡ãã¦ãããªãã¨ãã¿ããããã«æä½ã«å¯¾å¿ã§ããªãã£ãããããããªæåãããç ´ç®ã«ä¼ããã¨ãããã¾ãã
ã¢ããã°æè¨ã®URL
JJUG CCC以éã®ã¢ããã°æè¨ã¯Githubãªãã¸ããªã«ä¸ãã¦ã¿ããããã«æä½ã»ãã®å¯¾å¿ãå
¥ãã¦ãã¾ãã
https://github.com/torutk/analogclock
ã³ã¼ãã®èª¬æã¯Wikiã«è¨è¼ãã¦ãã¾ãã
JavaFXとアナログ時計 - ソフトウェアエンジニアリング - Torutk