title: How make TableView calculate its preferred width to display all columns
body: <p>Consider the following example:</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.beans.property.SimpleStringProperty;
  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 TableMCVE extends Application {
      @Override
      public void start(Stage stage) {
          int numOfCols = 3;
  
          ObservableList&lt;ObservableList&lt;String&gt;&gt; tableData = FXCollections.observableArrayList();
  
          // Generate dummy data.
          for (int i = 0; i &lt; 100; i++) {
              ObservableList&lt;String&gt; row = FXCollections.observableArrayList();
  
              for (int j = 0; j &lt; numOfCols; j++)
                  row.add("Row" + i + "Col" + j);
  
              tableData.add(row);
          }
  
          TableView&lt;ObservableList&lt;String&gt;&gt; table = new TableView&lt;ObservableList&lt;String&gt;&gt;();
  
          // Add columns to the table.
          for (int i = 0; i &lt; numOfCols; i++) {
              table.getColumns().add(addColumn(i, "Column " + i));
          }
  
          table.getItems().addAll(tableData);
  
          Scene scene = new Scene(table);
  
          // Adding some listeners.
          table.widthProperty().addListener((obs, oldValue, newValue) -&gt; {
              System.out.println("Table: " + newValue);
          });
          scene.widthProperty().addListener((obs, oldValue, newValue) -&gt; {
              System.out.println("Scene: " + newValue);
          });
          stage.widthProperty().addListener((obs, oldValue, newValue) -&gt; {
              System.out.println("Stage: " + newValue + "\n");
          });
  
          stage.setScene(scene);
          stage.show();
      }
  
      /**
       * Returns a simple column.
       */
      private TableColumn&lt;ObservableList&lt;String&gt;, String&gt; addColumn(int index, String name) {
          TableColumn&lt;ObservableList&lt;String&gt;, String&gt; col = new TableColumn&lt;ObservableList&lt;String&gt;, String&gt;(name);
          col.setCellValueFactory(e -&gt; new SimpleStringProperty(e.getValue().get(index)));
          return col;
      }
  
      public static void main(String[] args) {
          launch();
      }
  }
  </code></pre>
  
  <p>Even though there are only three narrow columns in the <code>TableView</code>, the entire <code>TableView</code> isn't shown by default.</p>
  
  <p>The initial value of my listeners are</p>
  
  <pre><code>Table: 248.0
  Scene: 248.0
  Stage: 266.0 (248 if you exclude the window borders from the calculation).
  </code></pre>
  
  <p>Since the widths of the three components are the same, this tells me that the computed width of the <code>TableView</code> and the actual width it would need to show all of its columns are two different things. </p>
  
  <p>So how do I get the table to take as much width as it needs to show all of its columns? This would be the preferred behavior when e.g. you want to display many different generated tables in separate windows.</p>
  
  <p>First I thought I could maybe calculate the total size of the columns, and then set the preferred width of the <code>TableView</code> to that:</p>
  
  <pre><code>for (TableColumn&lt;ObservableList&lt;String&gt;, ?&gt; col : table.getColumns()) {
      // Add a listener to the widthProperty of each column.
      col.widthProperty().addListener((obs, oldValue, newValue) -&gt; {
          double width = 0.0;
  
          // Get the sum of the width of all columns.
          for (TableColumn&lt;ObservableList&lt;String&gt;, ?&gt; column : table.getColumns()) {
                      width += column.getWidth();
          }
  
          System.out.println("Width of all columns: " + width);
          table.setPrefWidth(width);
          table.setMinWidth(width);
      });
  }
  </code></pre>
  
  <p>(Is there a prettier way to this by the way? Maybe using <code>Bindings.createDoubleBinding()</code>.)</p>
  
  <p>But for some reason, this does not work. </p>
  
  <p>If I add a listener to the <code>prefWidthProperty</code> of the table. I can see that the preferred width is actually set to 277, which is the width needed to display all columns. But for some reason, the <code>widthProperty</code> remains 248. If set the preferred width outside the for loop, the <code>widthProperty</code> value is changed with <code>prefWidthProperty</code>, and the whole table is displayed. I have no idea why it does that.</p>
  
  <p>But even if that trick did work, I'm thinking there might be an easier/better way. What is the best practice to achieve the kind of behaviour I'm looking for?</p>
  
  <p>Environment: <code>Windows 8.1</code> with <code>Java 8u102</code>.</p>