我为TableView编写了一个自定义大小调整策略,该策略与TableView.CONSTRAINED_RESIZE_POLICY相似,因为可见列的总宽度始终等于表本身的宽度.
每当调整列的大小时(通过调整表的大小或用户拖动列),都会调用调整大小策略,并适当地调整列的大小.
但是,当双击表头中的分隔线之一(以“收缩包装”列的内容)时,不会触发自定义大小调整策略.
结果,列的总宽度可能大于或小于表的宽度,这不好.
如何检测到这些双击并导致CustomResizePolicy之后触发呼叫?
这是一个工作示例,显示双击不会导致调用CustomResizePolicy:
import java.util.Locale;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class CustomResizeExample extends Application {
@SuppressWarnings("unchecked")
private Parent getContent () {
TableView <Locale> table = new TableView <>( FXCollections.observableArrayList( Locale.getAvailableLocales() ) );
TableColumn <Locale, String> countryCode = new TableColumn <>( "CountryCode" );
countryCode.setCellValueFactory( new PropertyValueFactory <>( "country" ) );
TableColumn <Locale, String> language = new TableColumn <>( "Language" );
language.setCellValueFactory( new PropertyValueFactory <>( "language" ) );
table.getColumns().addAll( countryCode, language );
TableColumn <Locale, Locale> local = new TableColumn <>( "Locale" );
local.setCellValueFactory( c -> new SimpleObjectProperty <>( c.getValue() ) );
table.getColumns().addAll( local );
table.setColumnResizePolicy( new CustomResizePolicy() );
BorderPane pane = new BorderPane( table );
return pane;
}
@Override
public void start ( Stage stage ) throws Exception {
stage.setScene( new Scene( getContent(), 800, 400 ) );
stage.show();
}
public static void main ( String[] args ) {
launch ( args );
}
}
@SuppressWarnings ( "rawtypes" )
class CustomResizePolicy implements Callback <TableView.ResizeFeatures, Boolean> {
@Override
public Boolean call ( TableView.ResizeFeatures feature ) {
System.out.println ( "Called" ); //This does not print when the divider is double-clicked.
return TableView.CONSTRAINED_RESIZE_POLICY.call( feature );
}
}
解决方法:
这是TableViewSkin中的错误.
在Java 8中,通过双击列分隔符调用的resizeColumnToFitContent方法不会在TableView中调用resizeColumn.结果是布局未正确更新.您尝试调整适合宽度的列的大小来观察这一点就足够了.实际上,反复拟合宽度将使宽度越来越接近其实际宽度.尝试拟合然后在同一列中连续几次调整大小(对其他列执行此操作将重置行为).
我没有时间找到一个好的解决方法.通过将TableViewSkin子类化并覆盖resizeColumnToFitContent,有一些类似的改进:
class CustomTableSkin<T> extends TableViewSkin<T> {
public CustomTableSkin(TableView<T> tableView) {
super(tableView);
i = tableView.getColumns().size() + 1;
}
private int i;
@Override
protected void resizeColumnToFitContent(TableColumn<T, ?> tc, int maxRows) {
double before = tc.getWidth();
super.resizeColumnToFitContent(tc, maxRows);
double now = tc.getWidth();
double diff = before - now;
i--;
if (i >= 0)
resizeColumn(tc, -diff);
}
}
在某些情况下,增加对resizeColumn的调用可能会有所帮助,但是需要更多的研究才能找出正确的修复方法.
Java 9更改了外观实现,但是我认为问题仍然存在.