当前位置: 首页 > 知识库问答 >
问题:

如何修复javafx (ComboBox,ListView)中的渲染错误

益和雅
2023-03-14

在一个相当复杂的javafx应用程序中,我遇到了一个可能的渲染错误。在过去的两天里,我可以追踪到以下简单的应用程序。以下SSCCE演示了在某些情况下,某些javafx组件无法正确呈现。因此,ComboBox和ListView不显示更改的内容:

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. 选择组合值-

请注意,重现此 Bug 有三个重要的要求(标有“重要”):

  1. 切换选项卡以隐藏此按钮时切换“Next”按钮的托管状态(隐藏节点以及节点可见状态的常用方法,请参阅JavaFX-setViable不“隐藏”元素)
  2. TabClosingPolicy.UNAVAILABLE(一种很常见的情况)
  3. VBox中的VBox(在现实生活中嵌套不同的javafx组件节点时很容易发生)。

这个错误是已知的吗?有人知道解决方法吗?我尝试了Platform.runLater(cancel.fire())和类似的方法,但没有成功。

谢谢你的提示,彼得。

顺便说一句。除此之外,我们公司使用javafx已经有几年了。根据我们的经验,它非常可靠,编程javafx很有趣。我希望我们的问题有一个简单的解决方案:)

共有1个答案

涂煌
2023-03-14

正如最初帖子的评论中所讨论的那样,该错误不是在JavaFX 8 (Oracle)中出现的,而是在更高版本(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()返回null)以及将选项卡添加到选项卡窗格后运行。后者可以通过选项卡侦听器实现:

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

站台runLater()是必需的,因为否则lookupAll()可能不会返回添加选项卡的节点。

也许这个解决方案可以帮助某人:)

 类似资料:
  • 我无法呈现一个selectOneMenu,但只能禁用该项目 例如,这是可行的: 而这个不是: 有什么建议吗 谢谢

  • 我写了一些代码来呈现ReactJS中的重复元素,但我讨厌它有多丑。 有没有更好的方法来实现这一点? (我想在模板代码或类似的方法中嵌入循环。)

  • 问题内容: 我已经写了一些代码来渲染ReactJS中的重复元素,但是我讨厌它是如此丑陋。 有没有更好的方法来实现这一目标? (我想在模板代码或类似方法中嵌入循环。) 问题答案: 您可以将表达式放在大括号内。请注意,在已编译的JavaScript中,为什么在JSX语法中永远不可能发生循环;JSX相当于函数调用和加糖的函数参数。仅允许使用表达式。 (此外:请记住将属性添加到在循环内渲染的组件。) JS

  • 我已经开始在JavaFX中开发一个应用程序,我运行了一个问题,我可以找到很少有用的信息:Linux中字符之间的间距非常不均匀。我说的不是不同字符的宽度,而是字符之间的空格。 它在普通文本中可见,但下面的示例说明了比普通文本更好的效果。看看第一排。前两个字符之间的空格小于第二个和第三个字符之间的空格。这也发生在第六和第七个字符和其他几个字符之间: Swing没有这个问题,JavaFX在Windows

  • 我有一个,其中有和属性(以适当的JavaFX方式),我想创建一个,它将显示人员的名称,并反映列表和列表中单个对象的属性中的更改。这件事怎么做最好?有两个问题: 所以,最后,我确实有一种方法来做我想做的事情:在1中编写我自己的包装器,在2中使用一个自定义的单元工厂。我只是觉得这需要更多的工作,我认为这是一个比较普遍的情况。有没有更简单的方法让我错过了?

  • 问题内容: 实际上我不知道问题出在哪里。我认为这必须在创建TableLayout时进行。我不知道如何解决错误并使该应用程序正常工作。该程序显示错误“ java.lang.ArithmeticException:被零除”错误该程序具有EditText(edText),要求用户输入。它的类型是NUMBER。(这里r是edText的值)在EditText下方有一个Button(bt),它显示edText