当ScrollBar
被调整(缩小)时,TableView
的水平TableView
(具有受限的调整大小策略)保持闪烁。我相信这是一个长期存在的问题,因为我可以找到JDK-8089009和其他参考问题JDK-8115476 & JDK-8089280的公开发行票。
我现在问这个问题的目的,是看看是否有人有办法或解决办法来解决这个现存的问题。
下面是在JDK-8089009中提供的演示代码,其中问题可以与JavaFX的最新版本(18+)重复。
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class HorizontalConstrainedTableScrolling extends Application {
@Override
public void start(final Stage primaryStage) throws Exception {
final TableView<Object> left = new TableView<>();
final TableColumn<Object, String> leftColumn = new TableColumn<>();
left.getColumns().add(leftColumn);
left.getItems().add(new Object());
left.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
final TableView<Object> right = new TableView<>();
final TableColumn<Object, String> rightColumn = new TableColumn<>();
right.getColumns().add(rightColumn);
right.getItems().add(new Object());
final SplitPane splitPane = new SplitPane();
splitPane.setOrientation(Orientation.HORIZONTAL);
splitPane.getItems().addAll(left, right);
Label osLabel = new Label(System.getProperty("os.name"));
Label jvmLabel = new Label(
System.getProperty("java.version") +
"-" + System.getProperty("java.vm.version") +
" (" + System.getProperty("os.arch") + ")"
);
primaryStage.setScene(new Scene(new BorderPane(splitPane, null, null, new VBox(osLabel, jvmLabel), null)));
primaryStage.setWidth(600);
primaryStage.setHeight(400);
primaryStage.setTitle("TableView in SplitPane");
primaryStage.show();
}
}
更新
下面是我通常遇到的使用受限调整大小策略的用法。
要求是,通常一个列是可维护的,而其他所有列都有一些最小/最大宽度,因此它们不能超出这些大小。如果所有列都有足够的空间,那么所有列都应该安装在tableView中,如果空间小于它们所能容纳的空间,那么滚动条就会出现。
下面是演示该示例的演示(使用滚动条问题):
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class ConstrainedResizePolicyDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TableColumn<Person, String> fnCol = new TableColumn<>("First Name");
fnCol.setMinWidth(100);
fnCol.setCellValueFactory(param -> param.getValue().firstNameProperty());
TableColumn<Person, String> act1Col = new TableColumn<>("Act1");
act1Col.setMinWidth(50);
act1Col.setMaxWidth(50);
act1Col.setResizable(false);
act1Col.setCellValueFactory(param -> param.getValue().act1Property());
TableColumn<Person, String> priceCol = new TableColumn<>("Price");
priceCol.setMinWidth(100);
priceCol.setMaxWidth(150);
priceCol.setCellValueFactory(param -> param.getValue().priceProperty());
TableColumn<Person, String> act2Col = new TableColumn<>("Act2");
act2Col.setMinWidth(50);
act2Col.setMaxWidth(50);
act2Col.setResizable(false);
act2Col.setCellValueFactory(param -> param.getValue().act2Property());
TableColumn<Person, String> totalCol = new TableColumn<>("Total");
totalCol.setMinWidth(100);
totalCol.setMaxWidth(150);
totalCol.setCellValueFactory(param -> param.getValue().totalProperty());
TableColumn<Person, String> act3Col = new TableColumn<>("Act3");
act3Col.setMinWidth(50);
act3Col.setMaxWidth(50);
act3Col.setResizable(false);
act3Col.setCellValueFactory(param -> param.getValue().act3Property());
TableColumn<Person, String> bidCol = new TableColumn<>("Bid");
bidCol.setMinWidth(100);
bidCol.setMaxWidth(150);
bidCol.setCellValueFactory(param -> param.getValue().bidProperty());
ObservableList<Person> persons = FXCollections.observableArrayList();
persons.add(new Person("Harry", "A", "200.00", "B", "210.00", "C", "300.00"));
persons.add(new Person("Kingston", "D", "260.00", "E", "610.00", "F", "700.00"));
TableView<Person> tableView = new TableView<>();
tableView.getColumns().addAll(fnCol, act1Col, priceCol, act2Col, totalCol, act3Col, bidCol);
tableView.setItems(persons);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Scene scene = new Scene(tableView, 600, 150);
primaryStage.setScene(scene);
primaryStage.setTitle("Constrained Resize Policy TableView");
primaryStage.show();
}
class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty act1 = new SimpleStringProperty();
private StringProperty price = new SimpleStringProperty();
private StringProperty act2 = new SimpleStringProperty();
private StringProperty total = new SimpleStringProperty();
private StringProperty act3 = new SimpleStringProperty();
private StringProperty bid = new SimpleStringProperty();
public Person(String fn, String act1, String price, String act2, String total, String act3, String bid) {
setFirstName(fn);
setAct1(act1);
setPrice(price);
setAct2(act2);
setTotal(total);
setAct3(act3);
setBid(bid);
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public StringProperty act1Property() {
return act1;
}
public void setAct1(String act1) {
this.act1.set(act1);
}
public StringProperty priceProperty() {
return price;
}
public void setPrice(String price) {
this.price.set(price);
}
public StringProperty act2Property() {
return act2;
}
public void setAct2(String act2) {
this.act2.set(act2);
}
public StringProperty totalProperty() {
return total;
}
public void setTotal(String total) {
this.total.set(total);
}
public StringProperty act3Property() {
return act3;
}
public void setAct3(String act3) {
this.act3.set(act3);
}
public StringProperty bidProperty() {
return bid;
}
public void setBid(String bid) {
this.bid.set(bid);
}
}
}
发布于 2022-07-21 10:10:54
和以往一样,对于长期存在的错误,唯一的出路就是黑客攻击。其基本思想是根据调整大小策略将滚动条的大小约束设置为0:对于约束策略,固定为0,对于无约束策略,则设置通常的useComputed。下面是实现hack的实用程序方法。
备注
守则:
public static void updateScrollBar(final TableView<Object> table) {
// lookup the horizontal scroll bar
ScrollBar hbar = null;
Set<Node> scrollBars = table.lookupAll(".scroll-bar");
for (Node node : scrollBars) {
ScrollBar bar = (ScrollBar) node;
if (bar.getOrientation() == Orientation.HORIZONTAL) {
hbar = bar;
break;
}
}
// choose sizing constraint as either 0 or useComputed, depending on policy
Callback<?, ?> policy = table.getColumnResizePolicy();
double pref = policy == CONSTRAINED_RESIZE_POLICY ? 0 : USE_COMPUTED_SIZE;
// set all sizing constraints
hbar.setPrefSize(pref, pref);
hbar.setMaxSize(pref, pref);
hbar.setMinSize(pref, pref);
}
发布于 2022-11-15 08:28:13
我使用的是从JavaFX 8开始对我有效的解决方案,在JavaFX 19中仍然是这样,但是使用这个解决方案意味着您必须遵守一些规则。为了使其发挥作用:
下面的代码适用于您的第一个示例代码。不需要侦听器,因为只有一个列:
leftColumn.prefWidthProperty().bind(left.widthProperty().subtract(1));
下面的代码适用于第二个示例代码,包括可重排序和可调整大小的更改。绑定和侦听器可以应用于您选择的TableColumns,条件是所选列是可调整大小的,并且没有设置maxWidth:
@Override
public void start(Stage primaryStage) throws Exception {
TableColumn<Person, String> fnCol = new TableColumn<>("First Name");
fnCol.setMinWidth(100);
fnCol.setReorderable(false);
fnCol.setCellValueFactory(param -> param.getValue().firstNameProperty());
TableColumn<Person, String> priceCol = new TableColumn<>("Price");
priceCol.setMinWidth(100);
priceCol.setReorderable(false);
priceCol.setCellValueFactory(param -> param.getValue().priceProperty());
TableColumn<Person, String> totalCol = new TableColumn<>("Total");
totalCol.setMinWidth(100);
totalCol.setReorderable(false);
totalCol.setCellValueFactory(param -> param.getValue().totalProperty());
TableColumn<Person, String> bidCol = new TableColumn<>("Bid");
bidCol.setMinWidth(100);
bidCol.setReorderable(false);
bidCol.setCellValueFactory(param -> param.getValue().bidProperty());
TableColumn<Person, String> act1Col = new TableColumn<>("Act1");
act1Col.setMinWidth(50);
act1Col.setMaxWidth(50);
act1Col.setResizable(false);
act1Col.setReorderable(false);
act1Col.setCellValueFactory(param -> param.getValue().act1Property());
TableColumn<Person, String> act2Col = new TableColumn<>("Act2");
act2Col.setMinWidth(50);
act2Col.setMaxWidth(50);
act2Col.setResizable(false);
act2Col.setReorderable(false);
act2Col.setCellValueFactory(param -> param.getValue().act2Property());
TableColumn<Person, String> act3Col = new TableColumn<>("Act3");
act3Col.setMinWidth(50);
act3Col.setMaxWidth(50);
act3Col.setResizable(false);
act3Col.setReorderable(false);
act3Col.setCellValueFactory(param -> param.getValue().act3Property());
ObservableList<Person> persons = FXCollections.observableArrayList();
persons.add(new Person("Harry", "A", "200.00", "B", "210.00", "C", "300.00"));
persons.add(new Person("Kingston", "D", "260.00", "E", "610.00", "F", "700.00"));
TableView<Person> tableView = new TableView<>();
tableView.setPadding(Insets.EMPTY);
tableView.getColumns().addAll(fnCol, priceCol, totalCol, bidCol, act1Col, act2Col, act3Col);
tableView.setItems(persons);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
fnCol.widthProperty().addListener((obs, ov, nv)->{
if (nv != null && !ov.equals(nv) && (double)nv > 0) {
if ((double)nv > (double)ov) {
fnCol.prefWidthProperty().unbind();
fnCol.setPrefWidth(tableView.getWidth() - act1Col.getWidth() - priceCol.getWidth() - act2Col.getWidth() - totalCol.getWidth() - act3Col.getWidth() - bidCol.getWidth());
fnCol.prefWidthProperty().bind(
tableView.widthProperty()
.subtract(act1Col.widthProperty())
.subtract(priceCol.widthProperty())
.subtract(act2Col.widthProperty())
.subtract(totalCol.widthProperty())
.subtract(act3Col.widthProperty())
.subtract(bidCol.widthProperty())
);
}
}
});
fnCol.prefWidthProperty().bind(
tableView.widthProperty()
.subtract(act1Col.widthProperty())
.subtract(priceCol.widthProperty())
.subtract(act2Col.widthProperty())
.subtract(totalCol.widthProperty())
.subtract(act3Col.widthProperty())
.subtract(bidCol.widthProperty())
);
Scene scene = new Scene(tableView, 600, 150);
primaryStage.setScene(scene);
primaryStage.setTitle("Constrained Resize Policy TableView");
primaryStage.show();
}
我假设这样做的原因很简单,因为何时精确计算列宽,何时触发水平滚动条可见性,以及所有这些事情发生的顺序。
https://stackoverflow.com/questions/73060277
复制相似问题