2013-02-01 48 views
24

afaik javafx中的TableView有2列調整策略:CONSTRAINED_RESIZE_POLICY和UNCONSTRAINED_RESIZE_POLICY,但我想調整列的大小以適應他們的單元格的內容 我認爲這是一個簡單的問題,在其他平臺(如在C#中的datagridview)但不能解決javafx column in tableview auto fit size

回答

13

3年後我再回到這個問題又來了,一些建議被計算在每個單元中的數據的文本的大小(它取決於字體大小,字體,填充複雜...)

但我意識到當我點擊表格標題上的分隔符時,它會根據需要調整爲適合內容。所以,我深入到JavaFX的源代碼,我終於找到resizeColumnToFitContent方法TableViewSkin,但保護方法,我們可以通過反射解決:

import com.sun.javafx.scene.control.skin.TableViewSkin; 
import javafx.scene.control.Skin; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

public class GUIUtils { 
    private static Method columnToFitMethod; 

    static { 
     try { 
      columnToFitMethod = TableViewSkin.class.getDeclaredMethod("resizeColumnToFitContent", TableColumn.class, int.class); 
      columnToFitMethod.setAccessible(true); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void autoFitTable(TableView tableView) { 
     tableView.getItems().addListener(new ListChangeListener<Object>() { 
      @Override 
      public void onChanged(Change<?> c) { 
       for (Object column : tableView.getColumns()) { 
        try { 
         columnToFitMethod.invoke(tableView.getSkin(), column, -1); 
        } catch (IllegalAccessException | InvocationTargetException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     }); 
    } 
} 

請注意,我們所說的「tableView.getItems( )「所以我們必須在setItems()

+0

我無法找到或導入類TableViewSkin。我正在使用Java 8,這個類似乎不存在。 – Spen

+0

@Spen:我使用java 8,我可以看到它,你可以檢查是否正確導入jfxrt.jar? – yelliver

8

我認爲通過重寫回調函數返回true將解決您的問題,它將禁用列的重新調整大小和所有列將被重新調整大小,以適應內容他們的細胞。

例子:

TableView<String[]> table = new TableView<>(); 
table.setColumnResizePolicy(new Callback<TableView.ResizeFeatures, Boolean>() { 
    @Override 
    public Boolean call(ResizeFeatures p) { 
    return true; 
    } 
}); 
+9

值得注意,它可以防止用戶從調整大小的列。 – assylias

+0

這不起作用。 –

5

還是要長話短說:

// automatically adjust width of columns depending on their content 
configAttributeTreeTable.setColumnResizePolicy((param) -> true); 
3

我用在這個問題上其他的解決方案,和它的作品相當不錯的。然而,這種情況的缺點是當TableView的寬度大於TableColumns所需的寬度時。我創建了一個黑客來解決這個問題,它的工作原理確定:

orderOverview.setColumnResizePolicy((param) -> true); 
Platform.runLater(() -> FXUtils.customResize(orderOverview)); 

其中FXUtils.customResize()如下創建:

public static void customResize(TableView<?> view) { 

    AtomicDouble width = new AtomicDouble(); 
    view.getColumns().forEach(col -> { 
     width.addAndGet(col.getWidth()); 
    }); 
    double tableWidth = view.getWidth(); 

    if (tableWidth > width.get()) { 
     TableColumn<?, ?> col = view.getColumns().get(view.getColumns().size()-1); 
     col.setPrefWidth(col.getWidth()+(tableWidth-width.get())); 
    } 

} 

我希望這可以爲其他人一樣有用好!

1

經過長時間的研究後調用此函數。最佳解決方案是..

tblPlan.setColumnResizePolicy((param) -> true); 
Platform.runLater(() -> customResize(tblPlan)); 

「自定義調整大小」

public void customResize(TableView<?> view) { 

     AtomicLong width = new AtomicLong(); 
     view.getColumns().forEach(col -> { 
      width.addAndGet((long) col.getWidth()); 
     }); 
     double tableWidth = view.getWidth(); 

     if (tableWidth > width.get()) { 
      view.getColumns().forEach(col -> { 
       col.setPrefWidth(col.getWidth()+((tableWidth-width.get())/view.getColumns().size())); 
      }); 
     } 
    } 
0

如果你想只有一個欄填寫表格的剩餘寬度,我發現了一個非常簡單的解決方案,這是短期和不需要上述的哈克反射解決方案:

DoubleBinding usedWidth = columnA.widthProperty().add(columnB.widthProperty()).add(columnC.widthProperty()); 

fillingColumn.prefWidthProperty().bind(tableView.widthProperty().subtract(usedWidth)); 
0

此代碼autores izes在關係比例在內的所有列寬度表寬度,
而當表寬度大於x

  // To generalize the columns width proportions in relation to the table width, 
     // you do not need to put pixel related values, you can use small float numbers if you wish, 
     // because it's the relative proportion of each columns width what matters here: 

     final float[] widths = { 1.2f, 2f, 0.8f };// define the relational width of each column 

     // whether the first column should be fixed 
     final boolean fixFirstColumm = true; 

     // fix the first column width when table width is lower than: 
     final float fixOnTableWidth = 360; //pixels 

     // calulates sum of widths 
     float sum = 0; 
     for (double i : widths) { 
      sum += i; 
     } 

     // calculates the fraction of the first column proportion in relation to the sum of all column proportions 
     float firstColumnProportion = widths[0]/sum; 

     // calculate the fitting fix width for the first column, you can change it by your needs, but it jumps to this width 
     final float firstColumnFixSize = fixOnTableWidth * firstColumnProportion; 

     // set the width to the columns 
     for (int i = 0; i < widths.length; i++) { 
      table.getColumns().get(i).prefWidthProperty().bind(table.widthProperty().multiply((widths[i]/sum))); 
      // ---------The exact width-------------^-------------^ 
    if (fixFirstColumm) 
      if (i == 0) { 
       table.widthProperty().addListener(new ChangeListener<Number>() { 
        @Override 
        public void changed(ObservableValue<? extends Number> arg0, Number oldTableWidth, Number newTableWidth) { 

         if (newTableWidth.intValue() <= fixOnTableWidth) { 

          // before you can set new value to column width property, need to unbind the autoresize binding 
          table.getColumns().get(0).prefWidthProperty().unbind(); 
          table.getColumns().get(0).prefWidthProperty().setValue(firstColumnFixSize); 

         } else if (!table.getColumns().get(0).prefWidthProperty().isBound()) { 

          // than readd the autoresize binding if condition table.width > x 
          table.getColumns().get(0).prefWidthProperty() 
            .bind(table.widthProperty().multiply(firstColumnProportion)); 
         } 

        } 
       }); 
      } 
     } 

建議下把代碼中的分離TableAutoresizeModel它可以固定第一列的寬度爲給定值類,那裏你可以處理進一步的計算,例如隱藏列添加監聽器...

0

經過測試以前的解決方案,我終於找到一個爲我工作。 因此,這裏是礦(調用該方法在將數據插入表之後):

public static void autoResizeColumns(TableView<?> table) 
{ 
    //Set the right policy 
    table.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY); 
    table.getColumns().stream().forEach((column) -> 
    { 
     //Minimal width = columnheader 
     Text t = new Text(column.getText()); 
     double max = t.getLayoutBounds().getWidth(); 
     for (int i = 0; i < table.getItems().size(); i++) 
     { 
      //cell must not be empty 
      if (column.getCellData(i) != null) 
      { 
       t = new Text(column.getCellData(i).toString()); 
       double calcwidth = t.getLayoutBounds().getWidth(); 
       //remember new max-width 
       if (calcwidth > max) 
       { 
        max = calcwidth; 
       } 
      } 
     } 
     //set the new max-widht with some extra space 
     column.setPrefWidth(max + 10.0d); 
    }); 
}