2015-04-26 29 views
8

Possiedo un controllo ListView con cella personalizzata. Calcolo il massimo su celle minWidth e lo imposta come minWidth per l'intero ListView. Quindi il ListView vincolato da altre regioni nel layout viene ridotto esattamente a minWidth. Ma le celle che contiene sono ridimensionate alla larghezza preferita, non minima. Di conseguenza i nodi non si adattano a contenere la vista e viene mostrata la barra di scorrimento orizzontale.Come rendere ListView larghezza larghezza delle celle

È brutto. Mi piacerebbe rendere ogni cella esattamente adatta a ListView e sbarazzarsi della barra di scorrimento. Più preciso. Quando ListView è ridotto alla sua larghezza minima, anche tutte le sue celle dovrebbero essere ridotte a questa larghezza minima.

Sono alla ricerca di alcune proprietà di controllo che modificano il criterio di ridimensionamento della cella di alcuni hack per ottenere un comportamento descritto nel caso in cui non vi siano switch predefiniti.


aggiornamento: aggiunto example graphic

ho creato SplitPane semplificare layout di prova. Posso definire le restrizioni del layout spostando il suo separatore con il mouse.

Il primo scatto mostra il problema iniziale: le dimensioni effettive (min, max, pref) dei nodi di cella non vengono rispettate. ListView utilizza sempre prefWidth anche se è maggiore della larghezza della finestra. Quindi lo scroll orizzontale viene usato quando può essere evitato.

bad

Dopo che ho cercato di impostare manualmente larghezza preferita minore. Quindi la cella ora è completamente visibile. Questa non è la soluzione. Fornisco questo scatto per dimostrare che la cella ha una larghezza minima sufficiente per adattarsi all'interno di ListView.

ugly

L'ultimo colpo è troppo brutto. Lascia lo spazio libero che può essere riempito con il contenuto della cella. È naturale: se viewport è più grande della larghezza preferita e minore della larghezza massima, allora dovrebbe essere usato per ridimensionare il contenuto della cella.

Il problema può essere eliminato passando a dimensioni statiche di elementi specificati in modo esplicito. Ma farlo significa scartare tutti i vantaggi dei layout dinamici: il programmatore sarebbe obbligato a modificare le costanti di dimensione ogni volta che viene applicato un nuovo skin con i CSS e all'utente sarà vietato ridimensionare la finestra o spostare il separatore con il mouse.

E anche questa è una soluzione sbagliata. Quello di cui ho bisogno - per far funzionare il motore di layout di javafx. La larghezza minima di ListView dovrebbe essere la larghezza minima delle celle. La larghezza massima di ListView dovrebbe essere la larghezza massima più bassa delle sue celle. La larghezza preferita di ListView dovrebbe essere la maggiore larghezza preferita delle sue celle. E rispetto alla larghezza effettiva di ListView dovrebbe essere impostato dal suo genitore (SplitPane in questo esempio) con rispetto a tutti e tre i limiti del layout. E dopo che questa dimensione dovrebbe essere passata alle cellule.

La barra di scorrimento orizzontale deve essere visualizzata solo nel caso in cui la larghezza minima di una cella sia troppo grande per essere inserita nella finestra.

+1

Potete aggiungere codice per quello che avete già provato. Se possibile un'immagine pure. – ItachiUchiha

+0

In realtà ho scritto in scala. È adatto per inserire il codice scala nella domanda javafx? – ayvango

+0

Sì dopo aver aggiunto il tag "scala". Uno può convertirlo in Java anche se ci possono essere diversi comportamenti. –

risposta

2

Basta associare il numero di cella prefWidthProperty a ListView widthProperty. Sottraggo un po 'per i bordi e così via.

Con le stringhe, otterrete i puntini di sospensione ... anziché una barra di scorrimento.

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.control.SplitPane; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class CellSize extends Application { 

    @Override 
    public void start(Stage stage) { 
     ObservableList<String> items = FXCollections.observableArrayList(
       "hello world", "This is a test", "this is not a drill","vroom...this IS a drill"); 

     ListView<String> lv = new ListView(items); 
     final VBox leftBox = new VBox(lv,new Button("Unused")); 

     lv.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 

      @Override 
      public ListCell<String> call(ListView<String> param) { 
       ListCell lc = new ListCell<String>() { 

        @Override 
        protected void updateItem(String item, boolean empty) { 
         super.updateItem(item, empty); 
         if (empty) { 
          setText(null); 
          setGraphic(null); 
         } else { 
          setGraphic(null); 
          if (item == null) setText("null"); 
          else { 
           setText(item); 
           double minWidth = 5 * item.length(); 
           double maxWidth = 10 * item.length(); 
           leftBox.setMinWidth(Math.max(minWidth, leftBox.getMinWidth())); 
           leftBox.setMaxWidth(maxWidth); 
          } 
         } 
        } 
       }; 
       lc.prefWidthProperty().bind(lv.widthProperty().subtract(4)); 
       return lc; 
      } 
     }); 

     SplitPane root = new SplitPane(); 
     root.getItems().addAll(leftBox,new VBox(new Label("Hello"))); 
     Scene scene = new Scene(root, 300, 250); 

     stage.setScene(scene); 
     stage.show(); 

    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 
+0

Ciò aumenterebbe inutilmente la larghezza preferita. La larghezza preferita può essere utilizzata dal genitore (ad es. SplitPane) per distribuire equamente lo spazio dello schermo tra i bambini – ayvango

+0

Sto impostando il 'prefWidth' della cella in modo che abbia la stessa dimensione del' ListView', che non sprechi spazio ma lo renda la giusta dimensione in modo che non vi sia alcuna barra di scorrimento e nessuno spazio vuoto. Ho notato che hai aggiornato la domanda, modifico l'esempio per aggiungere un minimo, un massimo e uno 'SplitPane' – brian

Problemi correlati