JavaFx:标题窗格折叠后滚动重置
我正在使用JavaFx:标题窗格折叠后滚动重置,java,javafx,scroll,tableview,javafx-8,Java,Javafx,Scroll,Tableview,Javafx 8,我正在使用标题窗格s滚动窗格s和表格视图s,我遇到了一个问题,当我折叠标题窗格时,表格视图的水平滚动条会重置 下面是一个代码示例,您可以在其中进行验证: import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.ScrollPane; import javafx.scene.control.Table
标题窗格
s滚动窗格
s和表格视图
s,我遇到了一个问题,当我折叠标题窗格时,表格视图
的水平滚动条
会重置
下面是一个代码示例,您可以在其中进行验证:
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()));
}
}
导入javafx.collections.FXCollections;
导入javafx.fxml.fxml;
导入javafx.fxml.Initializable;
导入javafx.scene.control.ScrollPane;
导入javafx.scene.control.TableView;
导入javafx.scene.control.TitledPane;
导入javafx.scene.layout.ancorpane;
导入java.net.URL;
导入java.util.ResourceBundle;
公共类控制器实现可初始化{
@FXML
私人锚烷含量;
@FXML
私有标题窗格标题窗格;
@FXML
私有TableView TableView;
@凌驾
公共void初始化(URL位置、ResourceBundle资源){
titledPane.prefHeightProperty().bind(content.heightProperty());
tableView.prefWidthProperty().bind(content.widthProperty());
tableView.getColumns().forEach(col->col.setPrefWidth(300));//有足够的“空间”滚动
setItems(FXCollections.observearraylist(newobject());
}
}
FXML:
知道如何防止每次折叠窗格时tableview的滚动复位吗 经过一番挖掘,看起来VirtualFlow中的一些布局优化可能是原因所在(如果滚动的内容不是TableView,那么一切似乎都很好,尽管没有进行彻底的分析) 发生的情况是:
- 折叠期间,标题窗格的内容垂直调整为0
- 在VirtualFlow的布局中,零高度/宽度是一种特殊情况,除了隐藏所有内容外,什么也不做,包括滚动条
- 滚动条的visiblilty的内部侦听器将其值重置为0
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());
}
public类TitledPaneTableScroll扩展应用程序{
公共静态类TableViewScrollSkin扩展了TableViewSkin{
DoubleProperty hvalue=新的SimpleDoubleProperty();
公共TableViewScrollSkin(TableView控件){
超级(控制);
installHBarTweak();
}
私有void installHBart虚弱(){
//注意:可以通过查找合法检索流和条
//fx9之前和fx9之后受保护的api
VirtualFlow流=getVirtualFlow();
//通过反射访问滚动条
//这是我的个人反射访问实用程序方法-使用您自己的:)
滚动条=(滚动条)FXUtils
.invokeGetFieldValue(VirtualFlow.class,流,“hbar”);
bar.valueProperty().addListener((s,o,n)->{
如果(n.intValue()!=0){
hvalue.set(n.doubleValue());
//调试
//新的RuntimeException(“谁在调用?\n”)。printStackTrace();
}
//LOG.info(“hbar值:+n+“可见?”+bar.isVisible());
});
bar.visibleProperty().addListener((s,o,n)->{
如果(n){
setValue(hvalue.get());
}
});
}
}
整数计数器;
私有父createContent(){
TableView table=newtableview(FXCollections.observearraylist(new Object())){
@凌驾
受保护的皮肤createDefaultSkin(){
返回新的TableViewScrollSkin(此);
}
};
table.getColumns().addAll(流
.generate(TableColumn::新建)
.限额(10)
.map(列->{
列设置宽度(50);
col.setText(“+计数器++);
返回列;
})
.collect(Collectors.toList());
标题窗格标题=新标题窗格(“标题”,表格);
标题为.setAnimated(true);
边框窗格内容=新边框窗格(标题);
返回内容;
}
@凌驾
public void start(Stage)引发异常{
stage.setScene(新场景(createContent(),400400));
//stage.setTitle(FXUtils.version());
stage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
@抑制警告(“未使用”)
专用静态最终记录器日志=记录器
.getLogger(TitledPaneTableScroll.class.getName());
}
hmm。。。不太明白为什么标题窗格周围有滚动窗格?为什么表的隐式滚动窗格不够好?可以忽略这一点,我只是将代码复制到一个虚拟项目中。在原始版本中,我在滚动窗格
中有许多标题窗格
s,这就是它存在的原因,但为了更简单,我删除了它。只是注意到这并不重要-隐式滚动窗格也重置为0。。。可能是一个bug:您希望标题窗格恢复到崩溃前的确切状态,您使用的是哪个版本的Java(Fx)?例如,我没有FXUtils。这只是一个用于反射访问的实用程序类-只需使用您自己的或使用node.lookup:)啊,好的,它使用queryAA
工作。考虑到它或多或少是一种黑客行为,我必须对它进行测试,以确保它不会导致任何意外的错误,但无论如何,它是一种解决方案,谢谢;)酷-请随意编辑我的
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());
}