JavaFx:TitledPane 折叠后滚动重置

标签 java javafx scroll tableview javafx-8

我正在使用 TitledPanes ScrollPanes 和 TableViews,并且我遇到了问题,当我折叠 titledPane 时,水平 TableView 的 >ScrollBar 重置。

这是一个代码示例,您可以在其中验证它:

import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TableView;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.AnchorPane;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {

    @FXML
    private AnchorPane content;
    @FXML
    private TitledPane titledPane;
    @FXML
    private TableView<Object> tableView;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        titledPane.prefHeightProperty().bind(content.heightProperty());
        tableView.prefWidthProperty().bind(content.widthProperty());

        tableView.getColumns().forEach(col -> col.setPrefWidth(300)); // to have enough "space" to scroll

        tableView.setItems(FXCollections.observableArrayList(new Object()));
    }

}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="stackoverflow.testscroll.Controller"
            fx:id="content">
            <TitledPane fx:id="titledPane">
                <TableView fx:id="tableView">
                    <columns>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                        <TableColumn/>
                    </columns>
                </TableView>
           </TitledPane>
</AnchorPane>

知道如何防止每次折叠 Pane 时重置桌面 View 的滚动吗?

最佳答案

经过一番挖掘,看起来 VirtualFlow 中的一些布局优化可能是原因(如果滚动的内容不是 TableView,那么一切似乎都很好 - 但没有彻底分析)

发生的情况是:

  • 折叠期间,TitledPane 的内容垂直调整为 0
  • 在 VirtualFlow 的 layoutChildren 中,零高度/宽度是一种特殊情况,除了隐藏所有内容(包括滚动条)之外什么也不做
  • 滚动条可见性的内部监听器将其值重置为 0

一个尝试性的(读:肮脏并且可能有不需要的副作用,除了这个快速概述之外完全没有经过测试!)破解是一个自定义的 TableViewSkin,它尝试“记住”最后一个非零值并在再次可见时重置它.

一个例子:

public class TitledPaneTableScroll extends Application {

    public static class TableViewScrollSkin<T> extends TableViewSkin<T> {

        DoubleProperty hvalue = new SimpleDoubleProperty();

         public TableViewScrollSkin(TableView<T> control) {
            super(control);
            installHBarTweak();
        }

        private void installHBarTweak() {
            // Note: flow and bar could be legally retrieved via lookup 
            // protected api pre-fx9 and post-fx9
            VirtualFlow<?> flow = getVirtualFlow();
            // access scrollBar via reflection 
            // this is my personal reflective access utility method - use your own :)
            ScrollBar bar = (ScrollBar) FXUtils
                    .invokeGetFieldValue(VirtualFlow.class, flow, "hbar");
            bar.valueProperty().addListener((s, o, n) -> {
                if (n.intValue() != 0) {
                    hvalue.set(n.doubleValue());
                    // debugging
                    //  new RuntimeException("who is calling? \n").printStackTrace();
                } 
                //LOG.info("hbar value: " + n + "visible? " + bar.isVisible());
            });

            bar.visibleProperty().addListener((s, o, n) -> {
                if (n) {
                    bar.setValue(hvalue.get());
                } 
            });
        }
    }

    int counter;
    private Parent createContent() {

        TableView<Object> table = new TableView<>(FXCollections.observableArrayList(new Object()) ) {

            @Override
            protected Skin<?> createDefaultSkin() {
                return new TableViewScrollSkin<>(this);
            }

        };
        table.getColumns().addAll(Stream
                .generate(TableColumn::new)
                .limit(10)
                .map(col -> {
                    col.setPrefWidth(50);
                    col.setText("" + counter++);
                    return col;
                })
                .collect(Collectors.toList())); 


        TitledPane titled = new TitledPane("title", table);
        titled.setAnimated(true);

        BorderPane content = new BorderPane(titled);
        return content;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent(), 400, 400));
       // stage.setTitle(FXUtils.version());
        stage.show();
    }

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

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger
            .getLogger(TitledPaneTableScroll.class.getName());

}

关于JavaFx:TitledPane 折叠后滚动重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52145683/

相关文章:

java - 在 Antlr 3 中生成自定义 JavaDoc

JavaFX 视频在反复播放同一视频几个小时后出现卡顿

java - 如何在 javafx 中更改 slider 的填充颜色

html - 滚动条在不同浏览器中的宽度是否始终相同?

java - 如何使用子查询而不是连接查询来通过 hibernate 获得正确的计数

java - 如何创建接受值数组的类构造函数?

java - 为什么这个 if 语句不起作用?

java - 创建元素包装器时的空指针

html - 左列滚动,其他选项然后滚动条?

安卓索引滚动