删除impl_isTreeVisible()的替代方法

时间:2017-05-10 08:38:50

标签: javafx java-9

我们依赖于Node.impl_isTreeVisible(),因为isVisible不能正常工作(或者至少我们想要的方式)。

/**
 * @treatAsPrivate implementation detail
 * @deprecated This is an internal API that is not intended for use and will be removed in the next version
 */
@Deprecated
public final boolean impl_isTreeVisible() {
    return impl_treeVisibleProperty().get();
}

我们有一个自定义节点,其中包含一个Plot。这会得到连续的数据。如果不可见(仍然是托管/渲染,但隐藏),我们希望避免更新绘图。 如果节点放在未选中的选项卡上,因此在窗口中不可见,则使用isVisible仍然返回true。这会导致每次更新绘图时,所选选项卡上的节点都会重新生成。

即使节点在应用程序窗口中不可见,也会评估为真。

if (isVisible()) {
    updatePlot()
}

所以我们一直在使用以下工作方式。

if (impl_isTreeVisible()) {
    updatePlot()
}

然而,这将不再适用于Java 9,因为此类方法已被删除。 Java 9中是否有新的方法?

更新: 查看javafx.scene.Node的Java 9源代码我发现方法isTreeVisible(),它看起来像是impl_isTreeVisible的替代品。但是看着Javadoc我找不到这个isTreeVisible()。 http://download.java.net/java/jdk9/docs/api/javafx/scene/Node.html

尝试使用isTreeVisible()的示例将无法使用Java 9进行编译

Java9AppTest.java:50: error: cannot find symbol
                    if (text1.isTreeVisible()) {
                         ^
  symbol:   method isTreeVisible()
  location: variable text1 of type Text

Update2 :最初看不到isTreeVisible()是包私有。

Update3 :再看一下Node源代码,我开始查看NodeHelper是否可以使用它获取isTreeVisible(),但是NodeHelper包不可见。虽然使用com.sun.javafx.scene的--add-exports来访问NodeHelper可以正常工作。

--add-exports javafx.graphics/com.sun.javafx.scene=ALL-UNNAMED

然后我可以读取Node的isTreeVisible()的状态。

final boolean isTreeVisible = NodeHelper.isTreeVisible(node);

代码示例

包含两个Tab,每个Tab都有自己的Text。 有一个更新每个文本的任务。 使用isVisible()将更新两个选项卡上的每个文本。 使用impl_isTreeVisible()只会更新真正可见的文本。 有意义的是,Text应该更新,即使它不可见。这只是为了说明问题。将文本替换为后台进程,这会使CPU工作量增加。

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Java9AppTest extends Application {

    private Text text1, text2;

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

    public void start(Stage stage) throws Exception {
        TabPane root = new TabPane();

        VBox box1 = new VBox();
        text1 = new Text();
        text1.setText("Hello World!");
        text1.textProperty().addListener((observable, oldValue,     newValue) -> {
            System.out.println("text1 changed from " + oldValue + " to " + newValue);
        });
        box1.getChildren().addAll(text1);

        Tab tab1 = new Tab("Tab 1");
        tab1.setContent(box1);

        VBox box2 = new VBox();
        text2 = new Text();
        text2.setText("Another Hello World!");
        text2.textProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println("text2 changed from " + oldValue + " to " + newValue);
        });
        box2.getChildren().add(text2);

        Tab tab2 = new Tab("Tab 2");
        tab2.setContent(box2);

        root.getTabs().addAll(tab1, tab2);

        Task<Void> task = new Task<Void>() {
            /* (non-Javadoc)
             * @see javafx.concurrent.Task#call()
             */
            @Override
            protected Void call() throws Exception {
                final String oldText = "Hello World!";
                final String newText = "New Hello World!";
                while (true) {
                    if (text1.isVisible()) {
                        if (text1.getText().equals(oldText)) {
                            text1.setText(newText);
                        } else {
                            text1.setText(oldText);
                        }
                    }

                    if (text2.isVisible()) {
                        if (text2.getText().equals(oldText)) {
                            text2.setText(newText);
                        } else {
                            text2.setText(oldText);
                        }
                    }

                    Thread.sleep(2000);
                }
            }

        };

        stage.setScene(new Scene(root));
        stage.setWidth(200);
        stage.setHeight(200);
        stage.setTitle("JavaFX 9 Application");
        stage.show();

        Thread thread = new Thread(task, "Task");
        thread.start();
    }

}

2 个答案:

答案 0 :(得分:2)

我建议在节点中添加一个属性,控制是否要更新绘图。因此,而不是if (impl_isTreeVisible()) {只有if (shouldUpdate) {。选项卡选择更改后,只需切换属性即可。所以从本质上讲,你的TabPane会控制情节是否更新。

或者,您可以将TabPane传递到您的节点并查询所选标签:tabPane.getSelectionModel().getSelectedIndex()。但是,这意味着您的节点必须知道它所在的选项卡。

答案 1 :(得分:-1)

  • Tab有一个属性selected,将该属性绑定到您的绘图的update属性,这决定了您是否重绘了您的绘图。
  • 在你的控件(或它的皮肤)中添加一个监听器到情节的update属性,你可以暂停或继续监听输入源,或暂停或恢复获取数据的计时器。

此解决方案不会向对象图添加额外的依赖项,它应该包含的容器类型,并允许您在必要时创建更复杂的绑定(如暂停按钮),并简化测试,因为此属性可在独立的方式。

根据数据源实现,如果确定没有侦听器主动处理您的数据,此解决方案也可以暂停您的数据源。