2016-05-19 3 views
1

JavaFX TabPaneは、すべてのタブを表示するのに十分なスペースがないときにタブを並べ替えると非常に奇妙な動作をします。JavaFX TabPane並べ替えタブで盛り上がりが発生する

さらに正確には、すべてのタブのドロップダウンリストを表示するタブ選択ボタン(タブペインのヘッダーの右側にある下向き矢印の丸いボタン)は、を何も表示しません。

私は問題を再現するための小さなテストを作成しました。 「Add new tab & sort」(または「新しいタブの追加」と「タブの並べ替え」を複数回実行)を数回クリックするだけで(すべてのタブに十分なスペースがなくなるまで)、タブ選択ボタンをクリックするだけです右上隅に...それは全く何も表示されていないことを見て!

enter image description here

すべてのタブがフィット感にするために、ウィンドウのサイズを変更して、タブの選択ボタンが再び表示されるように戻ってそれをリサイズすることを注記は、問題を解決します。

ここにコードを再現します。私はjdk1.8.0_92を使用しています。 JDKのバグのようですか?

public class TabPaneTest extends Application { 

public static void main(String[] args) { 
    TabPaneTest.launch(); 
} 

int i = 1; 

@Override 
public void start(Stage primaryStage) throws Exception { 
    TabPane tabPane = new TabPane(); 

    tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++)))); 

    Button add = new Button("Add new tab"); 
    add.setOnAction(event -> { 
     tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++)))); 
    }); 

    Button addSort = new Button("Add new tab & sort"); 
    addSort.setOnAction(event -> { 
     tabPane.getTabs().add(new Tab("My beautiful tab " + i, new TextArea("pane " + (i++)))); 
     tabPane.getTabs().sort((o1, o2) -> o2.getText().compareTo(o1.getText())); 
    }); 
    Button sort = new Button("Sort tabs"); 
    sort.setOnAction(event -> { 
     tabPane.getTabs().sort((o1, o2) -> o2.getText().compareTo(o1.getText())); 
    }); 


    VBox vbox = new VBox(tabPane, new HBox(add, addSort, sort)); 

    primaryStage.setScene(new Scene(vbox)); 
    primaryStage.setWidth(400); 
    primaryStage.setHeight(300); 
    primaryStage.show(); 
} 
} 
+0

これを再現するには別のJDKバージョンを使いましたか? – Supahupe

+1

私はチェックしました。 'TabPaneSkin'の' removeTabs'(以下の私の答えを参照してください)に関係するコードは、今日のJava 9ブランチにはまだ存在しているので、まだバグが残っている可能性があります。私は以前のバージョンをチェックしなかったが、明らかに最近まで、このバグ(2015年に修正された)のためにタブのソートがまったく機能しなかった:http://bugs.java.com/bugdatabase/view_bug.do?bug_id= 8118423 – Denis

+0

情報ありがとうございます。これは非常に興味深いです – Supahupe

答えて

2

TabリストについてTabPaneSkinListChangeListenerがあり、何とかそれはあなたがすでに述べたように、リストを並べ替えに取り組んでいません。

List<Tab> tabs = new ArrayList(tabPane.getTabs()); 
tabs.sort((o1, o2) -> o2.getText().compareTo(o1.getText())); 
tabPane.getTabs().clear(); 
tabPane.getTabs().setAll(tabs); 
+0

ありがとう@jns、これは、バグが修正されるまで有効な回避策だと思います。ところで、そこに 'ObservableList'の必要はありません、通常のArrayListで十分です! – Denis

+0

実際、これは機能していません。効果はありません(タブの順序は変更されません)。回避策を動作させるには、すべてのタブを削除してから再追加する必要があります: 'tabPane.getTabs()。clear();'の前に 'tabPane.getTabs()。setAll(tabs);' – Denis

+0

右。ドロップダウンリストのみが更新されます。 – jns

2

は私がTabPaneSkinクラスのメソッドremoveTabsで問題を見つけたと思う:あなたは、新しいリストにタブを入れて、ソートされた後TabPaneに適用することができます回避策として

それが削除されますtabHeaderArea.controlButtons.popupからエントリ:

   // remove the menu item from the popup menu 
      ContextMenu popupMenu = tabHeaderArea.controlButtons.popup; 
      TabMenuItem tabItem = null; 
      if (popupMenu != null) { 
       for (MenuItem item : popupMenu.getItems()) { 
        tabItem = (TabMenuItem) item; 
        if (tab == tabItem.getTab()) { 
         break; 
        } 
        tabItem = null; 
       } 
      } 
      if (tabItem != null) { 
       tabItem.dispose(); 
       popupMenu.getItems().remove(tabItem); 
      } 
      // end of removing menu item 

これは問題です:

  1. 反対をしませんaddTabs反対の方法(すなわち、ポップアップメニューに項目を追加していない、と
  2. tabHeaderArea.controlButtons.popuptabPane.getTabs()の変化に加入することによって、それ自体でそのエントリを管理します。

    tabPane.getTabs().addListener((ListChangeListener<Tab>) c -> setupPopupMenu()); 
    

そこで彼らは、ポップアップメニューから項目を削除しますが、setupPopupMenuremoveTabs前に呼び出されるため、エントリはタブaddTabsで再追加したときにバックに再追加されません両方。

私は上記の行をremoveTabsメソッドから削除しましたが、うまく動作します。

JDKのバグを提出する...

はUPDATE:

http://Bugs.java.com(レビューID JI-9038050)で、バグレポートを提出、それが固定されることはほとんど希望を持っている(私の最後の提出2015年9月のバグレポートはまだ「保留中」です)。

その間に醜い回避策(@jnsのおかげで)、すべてのタブを削除し、それらを並べ替え、再び追加することです:

 List<Tab> tabs = Lists.newArrayList(tabPane.getTabs()); 
     tabs.sort((o1, o2) -> o2.getText().compareTo(o1.getText())); 
     tabPane.getTabs().clear(); 
     tabPane.getTabs().setAll(tabs); 

あなたが実際にタブが起こって見ることができるので、それは醜いです離れて戻ってくる。

UPDATE 2:

よりよい回避策(おかげで再び@jns)を挿入する前に、新しいタブの正しい位置を決定することです:

Comparator<Tab> comparator = (o1, o2) -> o2.getText().compareTo(o1.getText()); 
    Button addSort = new Button("Add new tab, sorted"); 
    addSort.setOnAction(event -> { 
     Tab newTab = new Tab("My beautiful tab " + i, new TextArea("pane " + (i++))); 

     // THIS IS WRONG! See UPDATE 3 below: 
     // int pos = Math.max(0, Collections.binarySearch(tabPane.getTabs(), newTab, comparator)); 
     tabPane.getTabs().add(pos, newTab); 
    }); 

ソート順がない場合にのみ、明らかに動作します新しいタブが挿入されるたびに変更されません。別のソート順で既存のタブをソートする必要がある場合は、すべてのタブを削除してソートしてから、再度追加する必要があります(回避策1を参照)。

UPDATE 3:

それはJavaのbinarySearchだけ正確一致を探して、私として下限を返していないことが判明(味付けC++開発者が;)...期待だから、配置する必要があります挿入ポイントを見つけるために次の残虐行為をしてください:

<...> 
    int pos = 0; 
    while(pos < tabPane.getTabs().size() && tabPane.getTabs().get(pos).getText().compareTo(newTab.getText()) < 0) { 
     pos++; 
    } 
    tabPane.getTabs().add(pos, newTab); 
    <...> 
+1

'Tab'を追加するときにソートを適用できますか?その場合は、新しいタブのインデックスを決定し、その位置のタブリストに追加することができます。 – jns

+0

これは良いアイデアです.2番目の回避策として追加しました。 – Denis

関連する問題