2017-11-13 16 views
1

ここで目標はScrollPaneにカスタムScrollBarを使用することです。ウィンドウを最大化/最小化するときにレイアウトに問題はありません。これは、コンテンツ(2つのノードp1及びp2)が境界を超えたときに表示されるカスタムScrollBarと左側にScrollPaneとGUIを生成するウィンドウとレイアウトのパスを最大化

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.geometry.Orientation; 
import javafx.scene.Scene; 
import javafx.scene.control.ScrollBar; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.ScrollPane.ScrollBarPolicy; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.Background; 
import javafx.scene.layout.BackgroundFill; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.CornerRadii; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.Region; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 

public class Layout extends Application 
{ 
    @Override 
    public void start(Stage stage) 
    { 
     BorderPane main = new BorderPane(); 
     main.setPrefSize(800, 600); 

     BorderPane center = new BorderPane(); // begin center 
     center.setBackground(new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY))); 
     main.setCenter(center); // end center 

     BorderPane left = new BorderPane(); // begin left 

     ScrollPane pane = new ScrollPane(); 
     pane.setFitToWidth(true); 

     Pane p1 = new Pane(); // child 1 
     p1.setPrefSize(200, 100); 
     p1.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY))); 
     this.makeResizable(p1); 
     Pane p2 = new Pane(); // child 2 
     p2.setPrefSize(200, 100); 
     p2.setBackground(new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY))); 
     this.makeResizable(p2); 
     VBox content = new VBox(10, p1, p2); // content in scroll pane 
     pane.setContent(content); 

     // replace normal bars 
     pane.setHbarPolicy(ScrollBarPolicy.NEVER); 
     pane.setVbarPolicy(ScrollBarPolicy.NEVER); 

     // with custom 
     ScrollBar sb = new ScrollBar(); 
     sb.setOrientation(Orientation.VERTICAL); 
     sb.minProperty().bind(pane.vminProperty()); 
     sb.maxProperty().bind(pane.vmaxProperty()); 
     sb.visibleAmountProperty().bind(pane.heightProperty().divide(content.heightProperty())); 
     sb.managedProperty().bind(sb.visibleAmountProperty().lessThan(1.0)); // bar should be managed when it is needed (content too long) 
     sb.visibleProperty().bind(sb.managedProperty()); // and also visible only when managed 
     sb.valueProperty().bindBidirectional(pane.vvalueProperty()); 

     left.setCenter(pane); // content 
     left.setRight(sb); // scroll bar 
     main.setLeft(left); //end left 

     Scene scene = new Scene(main); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    // Simple for testing 
    double prevY; 
    boolean dragging; 

    // Makes node resizable on drag. 
    private void makeResizable(Region region) 
    { 
     region.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> 
     { 
      this.dragging = true; 
      region.setPrefHeight(region.getHeight()); 
      this.prevY = e.getSceneY(); 
     }); 
     region.addEventFilter(MouseEvent.MOUSE_DRAGGED, e -> 
     { 
      if (!this.dragging) return; 
      region.setPrefHeight(region.getPrefHeight() + (e.getSceneY() - this.prevY)); 
      this.prevY = e.getSceneY(); 
     }); 
     region.addEventFilter(MouseEvent.MOUSE_RELEASED, e -> this.dragging = false); 
    } 

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

はプログラム例を考えます。簡単にテストできるように、p1p2は、マウスでドラッグするとサイズを変更できます(試してみてください)。 ScrollBarが表示され、期待どおりに動作する間に、ウィンドウの最大化と最小化を開始すると、レイアウトに欠陥があります。例えば

  1. Startプログラム
  2. コンテンツのサイズを変更しますので、ScrollBarが表示されますが、あまりにも 多くの(あなたがそれを最大化するとき、それが境界内になるようにそれを作る)
  3. 最大化ウィンドウ - バーが消えているかもしれないが、空のスペースが表示されます。
  4. ここで、どういうわけかリフレッシュ(コンテンツのサイズ変更など)を行うと、レイアウトパスの更新によってバーが消えます。

その他のバグ:

  1. Startプログラムおよび最大化。
  2. コンテンツが最大化されたウィンドウに含まれるようにサイズを変更しますが、最小化すると境界を超えてしまうほど大きくなります。
  3. 最小化
  4. ScrollBarがどのように配置されているかに注意してください。

あなたは(第一の例を使用して)他のものを試してみてください、しかし、すべてのあなたが最大化する場合/これが起こる最小化するという事実に由来するかどういくつかの他のバグがあります。

  1. ScrollBarの管理と可視されるが(コンテンツが超過していると考えます)。
  2. 最大化
  3. ウィンドウがレイアウトを計算するサイズ変更される(古い値を使用して - 管理=真& &真=目に見える)
  4. レイアウトが発生し、すべての場所にある、すべてのプロパティは、管理ScrollBarセットを作るsb.visibleAmountProperty()を含む、更新を受信し(彼らはバインドされているので、コードを見てください)falseに見えます。
  5. ScrollBarは見えなくなり、管理されなくなりますが、レイアウトは既に発生しており、再実行されません。

ウィンドウを最大化するにはどうすればよいですか?他にどのように私はScrollBarを縛ることができるので、最大化するときに壊れませんか?サイズを変更するのではなく、最大化することについて話をしていることに注意してください。

答えて

0

私は回避策を見つけましたが、より適切なものがあれば絶対に最善のこととは思われません。共有してください。この以来

sb.managedProperty().addListener(e -> Platform.runLater(() -> content.requestLayout())); 

は「後で」実行されます(第1回は、前回のレイアウトを完了する必要があり、メインスレッドでもあるため)、これは再レイアウトが発生する原因となります。

なぜそれが最善ではないですか?まあ1つは、ダブルレイアウトの原因となる(最大化していない)ときにも呼び出されます(if文ではこれをやめることはできません)。

関連する問題