2013-09-26 98 views
2

我需要切換標籤Ctrl-TabCtrl-Shift-Tab。但它只適用於TabPane焦點。我有帶有setContent(textArea)的Tabs。 當textarea的是焦點,我按Ctrl-Tab組合,重點去某處菜單:JavaFX TabPane切換選項卡只在聚焦

[email protected][styleClass=text-input text-area] 
    [email protected][styleClass=text-input text-area] 
    TabPane[id=null, styleClass=tab-pane] 
    TextArea[id=null, styleClass=text-input text-area] 
    MenuButtonSkinBase$MenuLabeledImpl[id=null, styleClass=label] 
    TextArea[id=null, styleClass=text-input text-area] 
    MenuButtonSkinBase$MenuLabeledImpl[id=null, styleClass=label] 
    TextArea[id=null, styleClass=text-input text-area] 
    TabPane[id=null, styleClass=tab-pane] 
    TextArea[id=null, styleClass=text-input text-area] 
    MenuButtonSkinBase$MenuLabeledImpl[id=null, styleClass=label] 
    TextArea[id=null, styleClass=text-input text-area] 

我跟蹤對焦的變化是這樣的:

scene.focusOwnerProperty().addListener(new ChangeListener<Node>() { 

     @Override 
     public void changed(ObservableValue<? extends Node> ov, Node t, Node t1) { 
      System.out.println(t1); 
     } 
    }); 

setFocusTraversablefalse幾乎在每個組件上(包括菜單,工具欄,textArea和窗格)

我創建了Tabs並使用setContent(textArea)

另外我想requestFocus textArea每次用戶打開/關閉選項卡並在選項卡之間切換(使用鼠標和鍵盤熱鍵)。

tabPane.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() { 

     @Override 
     public void changed(ObservableValue<? extends Number> ov, Number t, Number t1) { 
      Platform.runLater(new Runnable() { 

       @Override 
       public void run() { 
        if (tabPane.getTabs().size() > 0) { 
         FileTab tab = (FileTab)tabPane.getTabs().get(tabPane.getSelectionModel().getSelectedIndex()); 
         tab.getTextArea().requestFocus(); 
        } 
       } 
      }); 

     } 
    }); 

這是行不通的。 我試過tab.getContent()。requestFocus() - 不起作用。

關於在TabPane子項關注時更改選項卡: 看起來TabPane獲取KeyEvent,但由於焦點沒有處於焦點(textArea焦點),它只是跳過此事件。 也許我可以複製默認功能通過發射KeyEventTabPane或者甚至可能重新實施它我自己。

tabPane.addEventFilter(KeyEvent.KEY_PRESSED,新的事件處理程序(){

 @Override 
     public void handle(KeyEvent t) { 
      if (t.getCode().equals(KeyCode.TAB) && t.isControlDown()) { 
        //Event.fireEvent(tabPane, event); //I'm not sure how to do it like this 
        //Maybe it's better to just call default actions on TabPane. 
        t.consume(); 
      } 
     } 
    }); 

http://s23.postimg.org/poeujzwbf/screenshot_185.png

但我仍然不知道:也許我可以從這個監聽器調用nextTab/previousTab默認操作如何標籤開關後設置文本區焦點。 也許我應該嘗試一些延遲之後調用Platform.runLater()

+0

你可以[過濾事件在現場](http://docs.oracle.com/javafx/2/api/javafx/scene/Scene.html#addEventFilter(javafx.event.EventType,%20javafx.event .EventHandler))而不是TabPane? – jewelsea

+0

看起來像個好主意。我認爲JavaFX有更優雅的解決方案。無論如何,我得到它的工作,但仍然不知道在Tab鍵切換後,在Tab內的TextArea的焦點,有時它的工作原理,有時它不工作(requestFocus())。 – AS3Boyan

+0

@ AS3Boyan,你可以嘗試在Platform.runLater中只放入'tab.getTextArea()。requestFocus();',即將if語句放在它之外。或者使用時間線在100ms後請求焦點。 –

回答

3

解TABS SWITCH:

scene.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() { 

     @Override 
     public void handle(KeyEvent t) { 
      if (t.getCode().equals(KeyCode.TAB) && t.isControlDown()) { 
       int size = tabPane.getTabs().size(); 

       if (size > 0) { 
        SkinBase skin = (SkinBase) tabPane.getSkin(); 
        TabPaneBehavior tabPaneBehavior = (TabPaneBehavior) skin.getBehavior(); 

        int selectedIndex = tabPane.getSelectionModel().getSelectedIndex(); 

        if (!t.isShiftDown()) { 
         if (selectedIndex < size -1) { 
          tabPaneBehavior.selectNextTab(); 
         } else { 
          tabPaneBehavior.selectTab(tabPane.getTabs().get(0)); 
         } 
        } else { 
         if (selectedIndex > 0) { 
          tabPaneBehavior.selectPreviousTab(); 
         } else { 
          tabPaneBehavior.selectTab(tabPane.getTabs().get(size - 1)); 
         } 
        } 

        t.consume(); 
       } 

      } 
     } 
    }); 

解焦點設置上選擇TAB:

 tabPane.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() { 

     @Override 
     public void changed(ObservableValue<? extends Number> ov, Number t, final Number t1) { 
      Platform.runLater(new Runnable() { 

       @Override 
       public void run() { 
        if (tabPane.getTabs().size() > 0) { 
         final FileTab tab = (FileTab) tabPane.getTabs().get(t1.intValue()); 

         final Timer timer = new Timer(); 
         timer.schedule(new TimerTask() { 

          @Override 
          public void run() { 
           Platform.runLater(new Runnable() { 

            @Override 
            public void run() { 
             tab.getContent().requestFocus(); 
             timer.cancel(); 
             timer.purge(); 
            } 
           }); 
          } 
         }, 25); 
        } 
       } 
      }); 

     } 
    }); 

替代解決方案FOR SETTING FOCUS ON SELECTED TAB(基於https://stackoverflow.com/a/16920898由@Uluk BIY ):

 tabPane.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() { 

     @Override 
     public void changed(ObservableValue<? extends Number> ov, Number t, final Number t1) { 
      Platform.runLater(new Runnable() { 

       @Override 
       public void run() { 
        if (tabPane.getTabs().size() > 0) { 
         final FileTab tab = (FileTab) tabPane.getTabs().get(t1.intValue()); 

         final Timeline animation = new Timeline(
           new KeyFrame(Duration.millis(25), 
           new EventHandler<ActionEvent>() { 
            @Override 
            public void handle(ActionEvent actionEvent) { 
             Platform.runLater(new Runnable() { 

              @Override 
              public void run() { 
               tab.getContent().requestFocus(); 
              } 
             }); 
            } 
           })); 
         animation.setCycleCount(1); 
         animation.play(); 
        } 
       } 
      }); 

     } 
    }); 

這應該是比只使用計時器更好的解決方案。

+0

我很感興趣該代碼如何改進使用計時器。你能告訴我們代碼示例嗎? –

+0

沒有必要在'Platform.runlater(...)'中的'KeyFrame'處理程序中包裝代碼, – user11153