我正在尝试使用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();
}
}
当我运行它时,页面会关闭
这里虽然它是第一条消息但滚动条指向下方虽然它的位置应该在顶部,但是它会上升。我该怎么办?
答案 0 :(得分:1)
只需注释文本流的Pref大小,因为它会导致滚动发生,因为它需要在滚动窗格内部调整其大小。 请查看以下内容:
struct Edge;
struct Vertex {
int key;
int val;
vector<Edge*> connections;
Vertex(int k) {
key = k;
}
};
答案 1 :(得分: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();
}