2016-05-19 3 views
9

I Scene haben, die auf die Scene meiner primaryStage eingestellt ist, dass - neben anderen Knoten - enthält eine VBox mit einem TableView und einige Tasten. Wenn ich eine Momentaufnahme in einer Zeile in der Tabelle unter Verwendung TableRow.snapshot(null, null) mache, wird die Größe der Scene geändert. Die Breite wird um etwa 10 Pixel geändert, während die Höhe um etwa 40 - manchmal mehr als 600 (!) - Pixel geändert wird.Node.snapshot (null, null) ändert die Größe der Szene

Dies passiert, weil Node.snapshot(null, null)Scene.doCSSLayoutSyncForSnapshot(Node node) aufruft, die die bevorzugte Größe aller Knoten in der Größe zu erhalten scheint und die Größe neu berechnen. Dies gibt irgendwie die falschen Werte zurück, da meine Knoten nur bevorzugte Größen haben und groß aussehen, bevor diese Methode aufgerufen wird. Gibt es einen Weg dies zu verhindern?

Die Größenänderung ist ein Problem, aber es ist auch ein Problem, dass die Primärstufe die Größe nicht mit der Scene ändert, die es enthält.

Ich habe versucht, einen MCVE zu erstellen, der das Problem reproduziert, aber nach ein paar Tagen, in denen ich das versuche, kann ich das Problem nicht reproduzieren. Das ursprüngliche Programm enthält ungefähr 2000 Codezeilen, die ich hier nicht veröffentlichen möchte.

Warum würde Scene.doCSSLayoutSyncForSnapshot(Node node) mein Layout kompromittieren, wenn es richtig angelegt ist? Kann ich irgendwie sicherstellen, dass das Layout richtig synchronisiert ist, bevor diese Methode aufgerufen wird, um sicherzustellen, dass es nichts ändert?

+0

gut können Sie versuchen, Einschränkungen auf Ihrem Knoten vor dem evozieren diese Funktion zu setzen und rückgängig machen sie, ich meine, ' setMinSize (Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE); 'und' setMaxSize (Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE); 'könnte helfen, wie Sie Ihr Problem beschrieben haben, :) – Elltz

+0

Danke, dass Sie nicht alle 2000 Codezeilen gepostet haben. Aber wenn Sie ein kurzes, kompilierbares Beispiel schreiben können, um das Problem zu reproduzieren, das hilfreich wäre. Sonst ein Link zu all deinem Code, wenn du ein kleines Sample nicht reproduzieren kannst? – Amber

+0

Ich empfehle, [Scenic View] (http://fxexperience.com/scenic-view/) zu verwenden, mit dem Sie alle Eigenschaften einer View während der Laufzeit Ihrer GUI anzeigen können. So können Sie zumindest überprüfen, ob das Problem, das Sie beschreiben, wirklich das Problem ist. Sie können auch einige Screenshots mit Scenic View veröffentlichen. Mit diesem Tool können Sie auch alle Ereignisse in Ihrer GUI anzeigen. Ich benutze es sehr :-) – Westranger

Antwort

1

Das Problem wurde behoben. Ich musste mein gesamtes Projekt kopieren und dann Teile des Codes entfernen, bis das Problem verschwunden war.

Wie auch immer. Ich hatte im Grunde drei Komponenten in meiner Anwendung. Eine Navigationskomponente, eine Tabellenkomponente und eine Statusleistenkomponente. Es sah wie folgt aus:

app sketch

Das Problem, das ich hatte, war, dass die Breite der Statusleiste und die Breite und Höhe der Tabellenkomponente erhöht wurde, wenn ich in der Tabelle eine Momentaufnahme einer Reihe nahm.

Offenbar war dies aufgrund der Auffüllung der Statusleiste Komponente. Es hatte eine rechte und linke Auffüllung von 5 Pixeln, und sobald ich die Auffüllung entfernte, verschwand das Problem.

Die hinzugefügten 10 Pixel in der Breite machte die BorderPane, die all dies mit der gleichen Anzahl von Pixeln erweitert, und da die Tabellenbreite an die Breite BorderPane gebunden war, stieg um den gleichen Betrag. Was ich aber immer noch nicht verstehe, ist warum sich die Stage, die die BorderPane enthält, nicht an die neue Breite anpasst.

Die Komponente wurde ordnungsgemäß aufgefüllt, bevor aufgerufen wurde, so dass ich nicht verstehe, warum die zusätzliche Breite von zehn Pixeln hinzugefügt wird.

Jedenfalls: Entfernen der Auffüllung von der Statusleiste Komponente und stattdessen Auffüllen der Komponenten in der Statusleiste das Problem behoben. Wenn jemand eine gute Erklärung dafür hat, bin ich ganz Ohr.

Hier ist ein MCVE wo Sie das Problem reproduzieren können in der Tabelle eine Zeile durch Ziehen:

import java.io.File; 
import java.sql.SQLException; 
import java.util.ArrayList; 

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Insets; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableRow; 
import javafx.scene.control.TableView; 
import javafx.scene.input.ClipboardContent; 
import javafx.scene.input.Dragboard; 
import javafx.scene.input.TransferMode; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Region; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

public class MCVE extends Application { 

    private Stage primaryStage; 
    private BorderPane rootLayout; 
    private VBox detailsView; 
    private StatusBar statusBar; 

    public void start(Stage primaryStage) throws SQLException { 

     this.primaryStage = primaryStage; 
     this.primaryStage.setTitle("MCVE"); 

     initRootLayout(); 
     showStatusBar(); 
     showDetailsView(); 

     detailsView.prefWidthProperty().bind(rootLayout.widthProperty()); 
     detailsView.prefHeightProperty().bind(rootLayout.heightProperty()); 
    } 

    @Override 
    public void init() throws Exception { 
     super.init(); 

    } 

    public void initRootLayout() { 
     rootLayout = new BorderPane(); 

     primaryStage.setWidth(1000); 
     primaryStage.setHeight(600); 

     Scene scene = new Scene(rootLayout); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public void showStatusBar() { 
     statusBar = new StatusBar(); 
     rootLayout.setBottom(statusBar); 
    } 

    public void showDetailsView() { 
     detailsView = new VBox(); 
     rootLayout.setCenter(detailsView); 

     setDetailsView(new Table(this)); 

     detailsView.prefHeightProperty().bind(primaryStage.heightProperty()); 
     detailsView.setMaxHeight(Region.USE_PREF_SIZE); 
    } 

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

    public VBox getDetailsView() { 
     return detailsView; 
    } 

    public void setDetailsView(Node content) { 
     detailsView.getChildren().add(0, content); 
    } 

    public StatusBar getStatusBar() { 
     return statusBar; 
    } 

    class StatusBar extends HBox { 
     public StatusBar() { 
      setPadding(new Insets(0, 5, 0, 5)); 

      HBox leftBox = new HBox(10); 

      getChildren().addAll(leftBox); 

      /** 
      * CONTROL SIZES 
      */ 
      setPrefHeight(28); 
      setMinHeight(28); 
      setMaxHeight(28); 

      // Leftbox takes all the space not occupied by the helpbox. 
      leftBox.prefWidthProperty().bind(widthProperty()); 

      setStyle("-fx-border-color: black;"); 
     } 
    } 

    class Table extends TableView<ObservableList<String>> { 

     private ObservableList<ObservableList<String>> data; 

     public Table(MCVE app) { 

      prefWidthProperty().bind(app.getDetailsView().widthProperty()); 
      prefHeightProperty() 
        .bind(app.getDetailsView().heightProperty()); 

      widthProperty().addListener((obs, oldValue, newValue) -> { 
       System.out.println("Table width: " + newValue); 
      }); 

      setRowFactory(r -> { 
       TableRow<ObservableList<String>> row = new TableRow<ObservableList<String>>(); 

       row.setOnDragDetected(e -> { 
        Dragboard db = row.startDragAndDrop(TransferMode.ANY); 
        db.setDragView(row.snapshot(null, null)); 

        ArrayList<File> files = new ArrayList<File>(); 

        // We create a clipboard and put all of the files that 
        // was selected into the clipboard. 
        ClipboardContent filesToCopyClipboard = new ClipboardContent(); 
        filesToCopyClipboard.putFiles(files); 

        db.setContent(filesToCopyClipboard); 
       }); 

       row.setOnDragDone(e -> { 
        e.consume(); 
       }); 

       return row; 
      }); 

      ObservableList<String> columnNames = FXCollections.observableArrayList("Col1", "col2", "Col3", "Col4"); 

      data = FXCollections.observableArrayList(); 

      for (int i = 0; i < columnNames.size(); i++) { 
       final int colIndex = i; 

       TableColumn<ObservableList<String>, String> column = new TableColumn<ObservableList<String>, String>(
         columnNames.get(i)); 

       column.setCellValueFactory((param) -> new SimpleStringProperty(param.getValue().get(colIndex).toString())); 

        getColumns().add(column); 
      } 

      // Adds all of the data from the rows the data list. 
      for (int i = 0; i < 100; i++) { 
       // Each column from the row is a String in the list. 
       ObservableList<String> row = FXCollections.observableArrayList(); 

       row.add("Column 1"); 
       row.add("Column 2"); 
       row.add("Column 3"); 
       row.add("Column 4"); 

       // Adds the row to data. 
       data.add(row); 
      } 

      // Adds all of the rows in data to the table. 
      setItems(data); 
     } 
    } 
} 
Verwandte Themen