JavaFXの(コンボボックス、リストビュー)のバグを修正レンダリングする方法

user27772:

非常に複雑JavaFXアプリケーションでは、私は可能なレンダリングのバグに直面しました。最後の2日間、私は次のような単純なアプリケーションにそれを追跡することができます。次SSCCEは、特定の状況では、いくつかのJavaFXコンポーネントが正しくレンダリングされていないことを示しています。その結果、コンボボックスとリストビューは、変更されたコンテンツは表示されません。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ComboManagedBug extends Application {
  public static void main(String[] args) {
    launch(args);
  }

  public void start(Stage primaryStage) {
    // add combo box
    ComboBox<String> combo = new ComboBox<>();
    combo.setPromptText("Choose a value...");
    combo.getItems().setAll("1", "2", "3");

    // add list view
    ListView<Label> list = new ListView<>();

    // add "add" button
    Button add = new Button("Add");
    add.setOnAction(e -> list.getItems().add(
      new Label(combo.getSelectionModel().getSelectedItem())));

    // add tab pane
    Tab tab1 = new Tab("First", new VBox(combo, add, list));
    Tab tab2 = new Tab("Second");
    TabPane tabs = new TabPane(tab1, tab2);
    tabs.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); // important!

    // add "next" and "cancel" buttons at bottom
    Button next = new Button("Next");
    Button cancel = new Button("Cancel (Triggers refresh)");
    HBox buttons = new HBox(next, cancel);

    // install tab listener
    tabs.getSelectionModel().selectedItemProperty().addListener((a, b, c) -> {
      // intention is to show next button only on first tab
      boolean firstTab = c == tab1;
      next.setVisible(firstTab);
      next.setManaged(firstTab); // important!
    });

    // show
    VBox root = new VBox(new VBox(tabs, buttons)); // important!
    Scene scene = new Scene(root, 400, 400);
    primaryStage.setTitle("ComboBox/ListView Rendering Bug Demo");
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

再現する手順:

  1. 起動プログラム
  2. コンボ値を選択してください - >コンボボックスが示す選択された値 - > OK
  3. 「追加」をクリック - >の値は、リストビューに追加されますと示されている - > OK
  4. アクティブに2番目のタブ
  5. アクティブに最初のタブ
  6. 以前のものとは異なるもののコンボ値を選択してください- > コンボボックスの値が変更されない- > BUG
  7. 「追加」をクリック- > リストビューの内容は変更されません- > BUG
  8. 一番下にある「キャンセル」をクリックします - >このボタンに添加していないリスナーがありませんでしたが、コンボボックスとリストビューの両方が正しい値を示しています。だから、両方の容器は、正しい値が含まれているように見えるが、いくつかのUIのリフレッシュがトリガされるまで、彼らは正しくレンダリングされません。

(「重要」でマークされた)、このバグを再現するには、3つの重要なreqiurementsがあることに注意してください:

  1. このボタンを非表示にするタブを切り替えるときにトグル「次へ」ボタンの状態を管理(ノードの可視状態と一緒にノードを非表示にする通常の方法を参照のJavaFXを-のsetVisibleがない「非表示」要素ありません
  2. TabClos​​ingPolicy.UNAVAILABLE(非常に一般的なケース)
  3. VBoxののVBox(異なるJavaFXのコンポーネントノードをネストするとき、容易に実際の生活の中で起こることができます)。

すでに知られているこのバグがある、と誰もがこのための回避策を知っているのですか?私が試したPlatform.runLater(cancel.fire())と同様のものを、成功せず。

、任意のヒントをピーター、ありがとうございました。

ところで、これとは別に、当社の用途は現在、いくつかの年のためのJavaFX。我々の経験では、それは非常に信頼性が高いとプログラミングJavaFXのは楽しいです。私は、私たちの問題の簡単な解決策があると願っています:)

user27772:

元の記事のコメントで述べたように、バグがJavaFXの8(オラクル)ではなく、それ以降のバージョン(OpenJFX)は発生しません。私は次の回避策を見つけました:

public static void fixTabRendering(TabPane tabs) {
    if (tabs.getTabClosingPolicy() != TabClosingPolicy.UNAVAILABLE) return;
    tabs.setTabClosingPolicy(TabClosingPolicy.SELECTED_TAB);
    for (Node node : tabs.lookupAll(".tab-close-button")) {
        // hide "close" button to imitate TabClosingPolicy.UNAVAILABLE
        node.setStyle("-fx-background-color:transparent;-fx-shape:null;-fx-pref-width:0.001");
    }
}

このコードは、ステージ(そうでなければ表示した後に実行されるべきであるlookupAll()戻り値ヌルならびにタブペインにタブを追加した後に)。後者は、タブリスナーを経由して実現することができます。

tabs.getTabs().addListener((Change<?> change) ->
    Platform.runLater(() -> fixTabRendering(tabs)));

Platform.runLater()はそうでないので、必要とされるlookupAll()は、追加のタブのノードを返さなくてもよいです。

たぶん、この解決策は、誰かを助けることができます:)

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=336121&siteId=1