2017-03-24 3 views
2

タブを使用するJavaFXでアプリケーションを作成しています。ユーザーは、一度に1つのタブではなく、同時にタブを開くことができます。これは、タブを画面の一側にドラッグすると理想的です。JavaFXで適切なタブ付きインターフェイスを作成していますか?

元は、グリッドパネルを1つのグリッドで作成し、ユーザーがタブをドラッグするときにグリッドを追加することをお勧めします。それはうまくいくとは思わない。これを行う良い方法はありますか? JavaFXのレイアウトとペインコントロールは本当にこれが欠けていますか?私が意図した動作のために、このようなものを使用した可能性がありますC#では

は私がしたい:http://avalondock.codeplex.com/

質問:私は、ユーザーが持っているタブをドラッグすることができ、JavaFXの中のタブとの適切なUXを実現することができる方法を "分割されたレイアウト?

EDIT:現時点で私は上記のアイデアを複製しようとしているのですが、HBoxを複製しようと考えています。私はHBoxの別の象限にタブドラッグを実装する方法を知っていますか?

+0

事前に定義されたものは何もありません。このようなものを実装しているサードパーティのライブラリがいくつかあります(たとえば、[Drombler](http://www.drombler.org/drombler-fx/)にドッキング機能があると思います)。それ以外の場合は、適切なマウスハンドラなどで自分で実装しなければなりません。 –

+0

マウス操作がどのタブで行われるかわからないので、TabPaneではこれが可能ではないと思います。私はおそらくToggleButtonsを使って "偽の"タブを作成し、コンテンツエリアにStackPaneを使用し、各タブコンテンツノードの可視性を特定のToggleButtonの選択状態にバインドします。 – VGR

+1

@VGR別の回避策は、(タブのテキストを設定する代わりに) 'Tab'のグラフィックとして' Label'を使い、ラベルにマウスハンドラを登録することです。 (もしあなたが本当に野心的であると感じたら、新しい 'TabPaneSkin'を書いてください。) –

答えて

3

あなたの質問は多少曖昧で、私は正直言って答えてはいけません。本当に「適切なタブ付きインターフェース」が本当に何を意味するのか分かりません。

ここでは、タブをお互いに開くことができるシステムです。タブを右クリックすると、縦または横に分割するコンテキストメニューが表示されます。タブの内容は、SplitPane内の新しいTabPane内で目的の方向に複製されます。

これは間違いなく完全なドッキングソリューションではなく、おそらくあなたが望むものに近いものではないかもしれませんが、おそらく有用であるかもしれません。このソリューションでは分割だけが行われますが、分割領域間でタブをドラッグ&ドロップすることはできません(おそらく自分で把握できない場合は、ドラッグアンドドロップの情報としてget in contact with Tom Schindl)。

以下の解決策は、分割タブの内容を新しい分割ゾーンの新しいタブにコピーするだけです。さらに強化された機能は、共通の同期されたドキュメントモデルのようなもので、異なるタブに複製されたファイルを並べて編集することができます(Intellij Ideaのエディタの実装と同様です)。

sample

import javafx.application.Application; 
import javafx.geometry.Orientation; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

import java.util.HashMap; 
import java.util.Optional; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 

public class SplitTabs extends Application { 
    final Lorem lorem = new Lorem(); 

    final HashMap<Node, SplitPane> splitPanes = new HashMap<>(); 

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

    @Override 
    public void start(Stage stage) { 
     TabPane tabPane = new TabPane(); 
     //noinspection ResultOfMethodCallIgnored 
     IntStream.range(0, 5) 
       .mapToObj(i -> createTab(lorem.nextString(1), lorem.nextString(200))) 
       .collect(Collectors.toCollection(tabPane::getTabs)); 

     stage.setScene(new Scene(new StackPane(tabPane))); 
     stage.show(); 
    } 

    private Tab createTab(String title, String text) { 
     TextArea textArea = new TextArea(text); 
     textArea.setWrapText(true); 

     Tab tab = new Tab(title); 
     tab.setContent(textArea); 
     tab.setOnCloseRequest(event -> { 
      TabPane tabPane = tab.getTabPane(); 
      if (tabPane.getTabs().size() <= 1) { 
       SplitPane splitPane = splitPanes.get(tabPane); 
       if (splitPane == null) { 
        // don't allow the last tab to be closed. 
        event.consume(); 
        return; 
       } 

       int siblingIdx = (splitPane.getItems().indexOf(tabPane) + 1) % 2; 
       Node siblingItem = splitPane.getItems().get(siblingIdx); 


       Optional<SplitPane> optionalParentSplitPane = 
         splitPanes.values().stream() 
           .filter(searchPane -> searchPane.getItems().contains(splitPane)) 
           .findFirst(); 

       // make the last TabPane the root. 
       if (!optionalParentSplitPane.isPresent()) { 
        StackPane stackPane = (StackPane) splitPane.getParent() ; 
        stackPane.getChildren().setAll(siblingItem); 
        splitPanes.clear(); 
        return; 
       } 

       // graft sibling under parent. 
       SplitPane parentSplitPane = optionalParentSplitPane.get(); 

       int idx = parentSplitPane.getItems().indexOf(splitPane); 
       parentSplitPane.getItems().set(idx, siblingItem); 
       splitPane.getItems().forEach(splitPanes::remove); 
       splitPanes.put(siblingItem, parentSplitPane); 
      } 
     }); 

     MenuItem splitVertically = new MenuItem("Split Vertically"); 
     splitVertically.setOnAction(event -> split(title, text, tab, Orientation.HORIZONTAL)); 
     MenuItem splitHorizontally = new MenuItem("Split Horizontally"); 
     splitHorizontally.setOnAction(event -> { 
      split(title, text, tab, Orientation.VERTICAL); 
     }); 

     tab.setContextMenu(new ContextMenu(
       splitVertically, 
       splitHorizontally 
     )); 

     return tab; 
    } 

    private void split(String title, String text, Tab tab, Orientation orientation) { 
     TabPane tabPane = tab.getTabPane(); 
     Tab tabCopy = createTab(title, text); 
     TabPane newTabPane = new TabPane(tabCopy); 
     SplitPane splitPane = new SplitPane(tabPane, newTabPane); 
     splitPane.setOrientation(orientation); 

     if (splitPanes.isEmpty()) { 
      StackPane stackPane = (StackPane) tabPane.getParent(); 
      stackPane.getChildren().setAll(splitPane); 
      splitPanes.put(tabPane, splitPane); 
      splitPanes.put(newTabPane, splitPane); 
     } else { 
      SplitPane parentSplit = splitPanes.get(tabPane); 
      int idx = parentSplit.getItems().indexOf(tabPane); 
      parentSplit.getItems().set(idx, splitPane); 
      splitPanes.remove(tabPane); 
      splitPanes.put(splitPane, parentSplit); 
      splitPanes.put(tabPane, splitPane); 
      splitPanes.put(newTabPane, splitPane); 
     } 
    } 
} 

class Lorem { 
    private static final String[] IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque hendrerit imperdiet mi quis convallis. Pellentesque fringilla imperdiet libero, quis hendrerit lacus mollis et. Maecenas porttitor id urna id mollis. Suspendisse potenti. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras lacus tellus, semper hendrerit arcu quis, auctor suscipit ipsum. Vestibulum venenatis ante et nulla commodo, ac ultricies purus fringilla. Aliquam lectus urna, commodo eu quam a, dapibus bibendum nisl. Aliquam blandit a nibh tincidunt aliquam. In tellus lorem, rhoncus eu magna id, ullamcorper dictum tellus. Curabitur luctus, justo a sodales gravida, purus sem iaculis est, eu ornare turpis urna vitae dolor. Nulla facilisi. Proin mattis dignissim diam, id pellentesque sem bibendum sed. Donec venenatis dolor neque, ut luctus odio elementum eget. Nunc sed orci ligula. Aliquam erat volutpat.".split(" "); 
    private int idx = 0; 

    public String nextString(int nWords) { 
     int end = Math.min(idx + nWords, IPSUM.length); 

     StringBuilder result = new StringBuilder(); 
     for (int i = idx; i < end; i++) { 
      result.append(IPSUM[i]).append(" "); 
     } 

     idx += nWords; 
     idx = idx % IPSUM.length; 

     return result.toString(); 
    } 
} 
+0

ありがとう!これは私が得たものより優れているので、これを答えとして設定します。私はもっ​​と良い解決策がないとうんざりしています。私は誰もタブ付き文書をお互いに並べることを望んでいないだろうか? – KingDan

+0

まあ、他のコメントにリンクされている解決策を参照してください)、私はちょうどそれらのいずれかがあなたが探しているか分からない。 – jewelsea

+0

私は本格的なデスクトップドッキングインターフェイスとアプリケーションフレームワークのために、SwingとSWTはしばらくの間行われており、人々はそれについてたくさんのものを作り出しています(例えばhttps://netbeans.org/features/platform/、https:// projects.eclipse.org/projects/eclipse.platform、http://www.jetbrains.org/pages/viewpage.action?pageId=983889)。 JavaFXをJavaFXで使用することはできますが、JavaFXでその程度の新しいプラットフォームを作成するのではなく、JavaFXプログラムをそれらのプラットフォームに組み込む方が簡単かもしれません。 – jewelsea

関連する問題