2016-11-24 80 views
0

我試圖用javaFX建立一個聊天框。我試圖在當前頁面填滿時自動向下滾動頁面。但它不能正常工作。javaFX中的自動滾動

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.TextField; 
import javafx.scene.input.KeyCode; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Priority; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Text; 
import javafx.scene.text.TextFlow; 
import javafx.stage.Stage; 

public class ChatBox extends Application{ 
final ScrollPane sp = new ScrollPane(); 
public static void main(String[] args){ 
launch(args); 
} 
public void start(Stage stage){ 
TextFlow textFlow = new TextFlow(); 
textFlow.setPadding(new Insets(10)); 
textFlow.setLineSpacing(10); 
textFlow.setPrefSize(300,300); 
TextField textField = new TextField(); 
textField.setPrefSize(50,30); 
Button button = new Button("Send"); 
button.setPrefSize(80,30); 
VBox container = new VBox(); 
VBox box = new VBox(); 
box.getChildren().addAll(sp,textFlow); 
container.setPadding(new Insets(10)); 
container.getChildren().addAll(box, new HBox(textField, button)); 
VBox.setVgrow(sp, Priority.ALWAYS); 
VBox.setVgrow(textFlow, Priority.ALWAYS); 
textField.prefWidthProperty().bind(container.widthProperty().subtract(button.prefWidthProperty())); 

// On Enter press 
textField.setOnKeyPressed(e -> { 
    if(e.getCode() == KeyCode.ENTER) { 
     button.fire(); 
    } 
}); 

button.setOnAction(e -> { 
    Text text; 
    if(textFlow.getChildren().size()==0){ 
     text = new Text(textField.getText()); 
    } else { 
     // Add new line if not the first child 
     text = new Text("\n" + textField.getText()); 
    } 
    textFlow.getChildren().add(text); 
    textField.clear(); 
    textField.requestFocus(); 
}); 
VBox vb = new VBox(); 
vb.getChildren().addAll(textFlow); 
sp.setVmax(440); 
sp.setPrefSize(400, 300); 
sp.setContent(vb); 
sp.vvalueProperty().bind((ObservableValue<? extends Number>) vb.heightProperty()); 
//sp.setPannable(true); 
Scene scene = new Scene(container, 400, 300); 
stage.setScene(scene); 
stage.setTitle("ChatBox"); 
stage.show(); 
} 
} 

當我運行它時,頁面出現故障

enter image description here

這裏喜上升,雖然它是第一個消息和滾動條下方指向雖然它的位置應該是在頂部。我該怎麼辦?

回答

1

只是評論文本流的Pref大小,因爲它導致滾動發生,因爲它需要在滾動窗格內時調整其大小。 看看如下:

package com.grs.stackOverFlow.pack161124; 

import javafx.application.Application; 
import javafx.beans.value.ObservableValue; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ScrollPane; 
import javafx.scene.control.TextField; 
import javafx.scene.input.KeyCode; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Priority; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Text; 
import javafx.scene.text.TextFlow; 
import javafx.stage.Stage; 

public class ChatBox extends Application{ 
    final ScrollPane sp = new ScrollPane(); 
    public static void main(String[] args){ 
     launch(args); 
    } 
    public void start(Stage stage){ 
     TextFlow textFlow = new TextFlow(); 
     //textFlow.setPadding(new Insets(10)); 
     textFlow.setLineSpacing(10); 
     //textFlow.setPrefSize(300,300); 
     TextField textField = new TextField(); 
     textField.setPrefSize(50,30); 
     Button button = new Button("Send"); 
     button.setPrefSize(80,30); 
     VBox container = new VBox(); 
     VBox box = new VBox(); 
     box.getChildren().addAll(sp,textFlow); 
     container.setPadding(new Insets(10)); 
     container.getChildren().addAll(box, new HBox(textField, button)); 
     VBox.setVgrow(sp, Priority.ALWAYS); 
     VBox.setVgrow(textFlow, Priority.ALWAYS); 
     textField.prefWidthProperty().bind(container.widthProperty().subtract(button.prefWidthProperty())); 

     // On Enter press 
     textField.setOnKeyPressed(e -> { 
      if(e.getCode() == KeyCode.ENTER) { 
       button.fire(); 
      } 
     }); 

     button.setOnAction(e -> { 
      Text text; 
      if(textFlow.getChildren().size()==0){ 
       text = new Text(textField.getText()); 
      } else { 
       // Add new line if not the first child 
       text = new Text("\n" + textField.getText()); 
      } 
      textFlow.getChildren().add(text); 
      textField.clear(); 
      textField.requestFocus(); 
     }); 
     VBox vb = new VBox(); 
     vb.getChildren().addAll(textFlow); 
     sp.setVmax(440); 
     sp.setPrefSize(400, 300); 
     sp.setContent(vb); 
     sp.vvalueProperty().bind((ObservableValue<? extends Number>) vb.heightProperty()); 
     //sp.setPannable(true); 
     Scene scene = new Scene(container, 400, 300); 
     stage.setScene(scene); 
     stage.setTitle("ChatBox"); 
     stage.show(); 
    } 
} 

[![enter image description here][1]][1] 
+0

感謝現在的工作:)但是當它滾動下來它應該正確顯示當前消息,但它顯示了一半,我必須自己向下滾動才能正確看到它。有什麼辦法解決它? – IAmBlake

+0

@IAmBlake:它再次出現一些佈局問題,請嘗試評論textFlow.setPadding(new Insets(10))。它爲我工作。我已經更新了答案,你可以接受,如果它適合你。如果問題讓我知道。 – grsdev7

0

我建議使用的ListView代替TextFlow這一點。這使得代碼簡單了很多,因爲ListView已經照顧換行的同時還提供了scrollTo方法允許你指定消息索引滾動到視圖:

public void start(Stage stage) { 
    TextField textField = new TextField(); 
    textField.setPrefSize(50, 30); 

    Button button = new Button("Send"); 
    button.setPrefSize(80, 30); 

    VBox container = new VBox(); 

    ListView<String> listView = new ListView(); 
    listView.setFocusTraversable(false); 
    listView.setCellFactory(lv -> new ListCell<String>() { 

     private final Text text; 

     { 
      text = new Text(); 
      setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 
      setGraphic(text); 

      // bind wrapping width to available size 
      text.wrappingWidthProperty().bind(Bindings.createDoubleBinding(() -> { 
       Insets padding = getPadding(); 
       return getWidth() - padding.getLeft() - padding.getRight(); 
      }, widthProperty(), paddingProperty())); 

     } 

     @Override 
     protected void updateItem(String item, boolean empty) { 
      super.updateItem(item, empty); 
      if (empty) { 
       text.setText(null); 
      } else { 
       text.setText(item); 
      } 
     } 

    }); 

    container.setPadding(new Insets(10)); 
    container.getChildren().addAll(listView, new HBox(textField, button)); 
    VBox.setVgrow(listView, Priority.ALWAYS); 

    HBox.setHgrow(textField, Priority.ALWAYS); 
    HBox.setHgrow(button, Priority.NEVER); 

    EventHandler<ActionEvent> handler = e -> { 
     // add new message 
     listView.getItems().add(textField.getText()); 

     textField.clear(); 
     textField.requestFocus(); 

     // scroll to newly added item 
     listView.scrollTo(listView.getItems().size()-1); 
    }; 

    textField.setOnAction(handler); 
    button.setOnAction(handler); 

    Scene scene = new Scene(container, 400, 300); 
    stage.setScene(scene); 
    stage.setTitle("ChatBox"); 
    stage.show(); 
}