2017-12-11 26 views
3

내 응용 프로그램에서 TreeTableView를 표시하고 들여 쓰기를 늘리고 싶습니다. 완벽하게 잘 작동하는 각각의 CSS 속성 -fx-indent을 찾았습니다. 그러나 지금은 선호 너비 계산에 어려움을 겪고 있습니다. 내가 완벽하게 내용을 포장하는 열을 좋아하고이 사용하여 반사를 achived JavaFx TreeTableCell 너비 계산

Auto resize column to fit content

이 기본 들여 쓰기를 사용하여 작동

에 설명 된대로, 그러나 계산에 나의 변화를 포함하지 않는 것 것입니다. 소스를 파고 나는 TreeTableCellSkin 클래스에 다음 snippent을 발견 :

if (isDeferToParentForPrefWidth) { 
     // RT-27167: we must take into account the disclosure node and the 
     // indentation (which is not taken into account by the LabeledSkinBase. 
     return super.computePrefWidth(height, topInset, rightInset, bottomInset, leftInset); 
    } 
    return columnWidthProperty().get(); 

편집 : 나는 일부 내 앞의 질문에 대한 답변과 코드가 leftLabelPadding() 방법으로 이동되면서이 댓글이 잘못이 있음을 발견 같은 클래스 :

// RT-27167: we must take into account the disclosure node and the 
    // indentation (which is not taken into account by the LabeledSkinBase. 
... 
double indentPerLevel = 10; 
if (treeTableRow.getSkin() instanceof TreeTableRowSkin) { 
    indentPerLevel = ((TreeTableRowSkin<?>)treeTableRow.getSkin()).getIndentationPerLevel(); 
} 
leftPadding += nodeLevel * indentPerLevel; 
... 

디버거 프로그램, 코드 조각 작품과 패딩으로 증가 들여 쓰기를 추가는, 셀의 그러나 prefWidth이 동일하게 유지하고 내 텍스트가 오버런되는 것을 ...

수정 방법 및 해결 방법에 대한 의견이 있으십니까? 어느 방향 으로든 어떤 힌트를 주시면 감사하겠습니다.

미리 감사드립니다.

답변

1

편집

문제가 FX9 수정되었습니다처럼 보이는, 그래서 다음과 같은 솔루션은 FX8와 필요 (가능)입니다

/EDIT

좋아, 내가 그랬어 좀 더 파고와 (잘하면 오른쪽) 설명과 문제에 대한 더러운 솔루션을 발견. 설명에 관심있는 사람은이 게시물 아래로 더 읽을 수 있습니다. 여기 다른 모든 사람들은 내 더러운 퀵 픽스입니다.

더러운하지만 작업 솔루션 : 설명의

Method fitColumn = TreeTableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TreeTableColumn.class, int.class); 
    fitColumn.setAccessible(true); 
    List<TreeTableColumn<S, ?>> tableColumns = aTreeTableView.getColumns(); 
    for (TreeTableColumn<S, ?> treeTableColumn : aTreeTableView.getColumns()) { 
    fitColumn.invoke(aTreeTableView.getSkin(), treeTableColumn, -1); 

    /* 
    * FX does not include the altered indentation in the calculation for the prefWidth. 
    * Instead it uses a fixed constant of 10 (TreeTableCellSkin.leftLabelPadding()). 
    * To ensure the column can still display all its contents the remaining indentation must be added manually. 
    * To achieve this the maximum depth of the displayed tree is calculated and multiplied with the remaining indentation per level. 
    */ 
    TreeItem<S> rootItem = aTreeTableView.getRoot(); 
    Stack<TreeItem<S>> items = new Stack<>(); 
    if (aTreeTableView.isShowRoot() && rootItem != null) { 
     items.push(rootItem); 
    } else if (rootItem != null) { 
     rootItem.getChildren().forEach(items::push); 
    } 

    int maxLevel = -1; 
    while (!items.isEmpty()) { 
     TreeItem<S> curItem = items.pop(); 
     int curLevel = aTreeTableView.getTreeItemLevel(curItem); 
     maxLevel = Math.max(curLevel, maxLevel); 
     if (curItem.isExpanded()) { 
     curItem.getChildren().forEach(items::push); 
     } 
    } 
    if (maxLevel >= 0) { 
     double indentation = 20; // the indentation used in the css stylesheet 
     double additionalIndentPerLevel = indentation - 10; // constant from TreeTableCellSkin 
     treeTableColumn.setPrefWidth(treeTableColumn.getWidth() + maxLevel * additionalIndentPerLevel); 
    } 

시도 : 나는 그들의 콘텐츠에 열 너비에 맞게 반사를 사용하고 언급 한 바와 같이

:

Method fitColumn = TreeTableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TreeTableColumn.class, int.class); 
fitColumn.setAccessible(true); 
List<TreeTableColumn<S, ?>> tableColumns = aTreeTableView.getColumns(); 
for (TreeTableColumn<S, ?> treeTableColumn : aTreeTableView.getColumns()) { 
    fitColumn.invoke(aTreeTableView.getSkin(), treeTableColumn, -1); 
} 

그래서이 프로세스가 어떻게 작동하는지 이해하려고했습니다. FX가 TreeTableViewSkin FX에있는 resizeColumnToFitContent의 코드가 표시된 값을 반복하고 각 값에 대해 새로운 셀과 새 행을 구성하는 것으로 보입니다. 그런 다음 셀을 행에 넣고 현재보기에 행을 추가 한 다음 계산 된 prefWidth를 읽습니다. 그런 다음 새 행과 셀을 제거합니다.지금까지 모두 기능 작동

// RT-27167: we must take into account the disclosure node and the 
    // indentation (which is not taken into account by the LabeledSkinBase. 
... 
double indentPerLevel = 10; 
if (treeTableRow.getSkin() instanceof TreeTableRowSkin) { 
    indentPerLevel = ((TreeTableRowSkin<?>)treeTableRow.getSkin()).getIndentationPerLevel(); 
} 
leftPadding += nodeLevel * indentPerLevel; 
... 

을 바르고 정확한 폭을 계산한다

TreeTableCell<S,?> cell = (TreeTableCell) cellFactory.call(col); 
... 
TreeTableRow<S> treeTableRow = new TreeTableRow<>(); 
treeTableRow.updateTreeTableView(treeTableView); 
... 
getChildren().add(cell); 
cell.applyCss(); 

double w = cell.prefWidth(-1); 

maxWidth = Math.max(maxWidth, w); 
getChildren().remove(cell); 
... 

는 동시에 TreeTableCellSkin 클래스 압입을 결정하는 셀과 연관된 TableRowSkin을 이용한다. 그러나 나는 그들이 조합에서 작동하지 않는다고 가정합니다. TreeTableCellSkin은 셀과 연결된 행이 표시되는 모든 행의 경우 인 것처럼 보이는 TreeTableRowSkin의 인스턴스인지 확인합니다. 그러나 TreeTableViewSkin은 연관된 행을 TreeTableRow 유형으로 설정합니다. 결과로 instanceof 검사가 실패하고 사용자 정의 들여 쓰기 대신 마법 기본 상수 10이 너비 계산에 사용됩니다.

내 관점에서 보면 이것이 JavaFX의 버그라고 말하지만, 내 결론은 잘못된 것일 수 있습니다. 따라서 다른 의견이나 견해를 환영합니다.

결과적으로 각 열에 대한 prefWidth는 항상 레벨 당 들여 쓰기를 10으로 사용합니다. 들여 쓰기를 변경 한 경우 FX 계산 후에 수동으로 추가해야합니다. 이를 달성하기 위해 표시된 트리의 최대 깊이를 계산합니다 (구현은 아마도 가장 효율적이지는 않지만이 모든 시간 이후에는별로 신경 쓰지 않았습니다 ...). 또한 각 레벨에 대해 누락 된 들여 쓰기를 계산합니다. 좋은 파고와 대담한 솔루션 : BTW, 내가 행이 가지고 있기 때문에 instanceof를 검사가 실패 의심을 위해

TreeItem<S> rootItem = aTreeTableView.getRoot(); 
Stack<TreeItem<S>> items = new Stack<>(); 
if (aTreeTableView.isShowRoot() && rootItem != null) { 
    items.push(rootItem); 
} else if (rootItem != null) { 
    rootItem.getChildren().forEach(items::push); 
} 

int maxLevel = -1; 
while (!items.isEmpty()) { 
    TreeItem<S> curItem = items.pop(); 
    int curLevel = aTreeTableView.getTreeItemLevel(curItem); 
    maxLevel = Math.max(curLevel, maxLevel); 
    if (curItem.isExpanded()) { 
    curItem.getChildren().forEach(items::push); 
    } 
} 
if (maxLevel >= 0) { 
    double indentation = 20; // the indentation used in the css stylesheet 
    double additionalIndentPerLevel = indentation - 10; // constant from TreeTableCellSkin 
    treeTableColumn.setPrefWidth(treeTableColumn.getWidth() + maxLevel * additionalIndentPerLevel); 
} 
+1

1 : 누락 된 들여 쓰기를 계산하고 단지 컬럼에 추가 할 수 있습니다 두 값을 곱하면 피부가 없습니다 (아무데도 추가되지 않습니다). fx9에서 메소드 resizeColumnToFitContent가 패키지 개인 클래스의 정적 유틸리티 메소드로 이동 했으므로 액세스 할 수 없음을 유의하십시오. – kleopatra

+1

예, 그 이유가 될 수 있습니다 ... fx9를 사용하여 조언 해 주셔서 감사합니다. 이 메소드는 fx9가있는 공개 API로 이동하고 어디서나 찾을 수 없을 때 매우 놀랐습니다 ... – Rosso

+0

우리 모두는 낙천적입니다. 우리는 항상 그래 왔고 다시 실망하더라도 ...) – kleopatra