2015-02-18 2 views
2

Я пытаюсь создать представление презентации для своего приложения Drawing, где видна только панель чертежа (панель). Таким образом, пользователь может отображать представление презентации на проекторе, имея фактическую панель рисования и инструменты на ПК.Представление презентации JavaFX8 (дублирующаяся область и содержимое)

Мой текущий подход - создать снимок с панели в каждом кадре и отобразить его в ImageView на втором этапе.

public void startStream(){ 

    new AnimationTimer() { 
     @Override 
     public void handle(long now) { 
      WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null); 
      stream.setImage(image); 
     } 
    }.start(); 

    final Screen screen = Screen.getPrimary(); 
    final Stage stage = new Stage(); 
    StackPane root = new StackPane(); 
    root.getChildren().add(stream); 
    Scene scene = new Scene(root, drawingPane.getWidth(), drawingPane.getHeight()); 
    stage.setScene(scene); 
    stage.setTitle("streaming stage"); 

    Rectangle2D bounds = screen.getBounds(); 
    System.out.println(bounds); 
    stage.setX(bounds.getMinX() + (bounds.getWidth() - 300)/2); 
    stage.setY(bounds.getMinY() + (bounds.getHeight() - 200)/2); 
    stage.show(); 
} 

проблема здесь есть много ОЗУ, например 800 МБ, а также на 30% больше использования ЦП. Я могу понять, что создание изображения на каждом кадре неэффективно, поэтому я хотел бы спросить, есть ли способ повысить эффективность этой работы.

Также, если есть лучший подход/решение этой функции, я был бы благодарен за это.

ответ

2

Чтобы уменьшить использование ЦП, не делайте моментальный снимок в AnimationTimer —, это действительно делает снимок на частоте кадров (60 FPS), даже если ничего не изменилось в drawingPane. Вместо этого сделайте снимок после макета drawingPane. Добавление слушателя к drawingPane «s needsLayoutProperty должен сделать трюк:

drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> { 
    if(!isDirty) { 
     WritableImage image = drawingPane.snapshot(new SnapshotParameters(), null); 
     stream.setImage(image); 
    } 
}); 

Это должно снизить нагрузку на процессор, когда вы не редактируя drawingPane.

Это может также снизить использование памяти, поскольку сборщик мусора может быстрее выстрелить и собрать старые снимки. Если нет, то рассмотреть повторное использование экземпляра WritableImage, если он уже имеет правильный размер:

WritableImage image = null; 

drawingPane.needsLayoutProperty().addListener((obs, wasDirty, isDirty) -> { 
    if(!isDirty) { 
     if(this.image != null && 
       (this.image.getWidth() != drawingPane.getWidth() || 
       this.image.getHeight() != drawingPane.getHeight())) { 
      this.image = null; 
     } 
     this.image = drawingPane.snapshot(new SnapshotParameters(), this.image); 
     stream.setImage(this.image); 
    } 
}); 

Примечание, что этот ответ предполагает, что дети drawingPane являются удалось детей (это значение по умолчанию), и поэтому их расположение обозначено как грязное приводит к тому, что макет drawingPane помечен как грязный, чтобы вы могли фактически наблюдать за любыми изменениями свойства needsLayout.

+0

спасибо, это сбило использование процессора до 10% и использования памяти до менее 350 МБ – Murdoc