2013-07-22 34 views
12

Tôi đang cố gắng để có được một TextArea để autoscroll đến phía dưới với văn bản mới được đưa vào thông qua một xử lý sự kiện. Mỗi mục nhập mới chỉ là một chuỗi văn bản dài với mỗi mục được phân tách bằng dấu ngắt dòng. Tôi đã thử xử lý thay đổi đặt setscrolltop thành Double.MIN_VALUE nhưng không có kết quả. Bất kỳ ý tưởng nào về cách thức này có thể được thực hiện?JavaFX TextArea và autoscroll

+1

Nhận xét của bạn đã bị xóa (không phải bởi tôi) vì bạn đã đăng nhận xét đó làm câu trả lời. Tôi trả lời ở đó với bạn rằng bạn có thể muốn chấp nhận câu trả lời mà bạn đánh giá là chính xác để cho người khác biết bạn đã tìm ra một giải pháp thỏa mãn bạn. Để làm như vậy, nhấp vào 'V' bên cạnh câu trả lời bạn thích làm cho nó trở thành màu xanh lá cây. Điều này cũng hợp lệ cho [câu trả lời của riêng bạn] (http://stackoverflow.com/questions/19122056/camel-jpa-component-forcing-a-commit) – Math

Trả lời

20

Bạn cần phải thêm một người biết lắng nghe để các yếu tố TextArea để di chuyển đến phía dưới khi giá trị của nó được thay đổi:

@FXML private TextArea txa; 

... 

txa.textProperty().addListener(new ChangeListener<Object>() { 
    @Override 
    public void changed(ObservableValue<?> observable, Object oldValue, 
      Object newValue) { 
     txa.setScrollTop(Double.MAX_VALUE); //this will scroll to the bottom 
     //use Double.MIN_VALUE to scroll to the top 
    } 
}); 

Nhưng nghe này không được kích hoạt khi bạn sử dụng phương pháp setText(text), vì vậy nếu bạn muốn kích hoạt nó sau một setText(text) sử dụng appendText(text) ngay sau nó:

txa.setText("Text into the textArea"); //does not trigger the listener 
txa.appendText(""); //this will trigger the listener and will scroll the 
        //TextArea to the bottom 

này nghe có vẻ giống như một lỗi, một khi setText() nên kích hoạt các changed người nghe, tuy nhiên nó d không. Đây là cách giải quyết tôi sử dụng bản thân mình và hy vọng nó sẽ giúp bạn.

+2

'setScrollTop (Double.MIN_VALUE);' cuộn lên trên cùng, trong khi 'MAX_VALUE' cuộn xuống dưới cùng. –

+0

@AdamJensen Tôi sẽ làm một bài kiểm tra ở đây, bởi vì tôi đã trả lời điều này một thời gian trước và tôi không thể nhớ bằng cách nhìn vào nó. Cảm ơn báo cáo. – Math

+1

@AdamJensen bạn hoàn toàn đúng. Tôi vừa sửa nó. Cảm ơn! – Math

7

txa.appendText ("") sẽ cuộn xuống dưới cùng mà không có người nghe. Điều này sẽ trở thành một vấn đề nếu bạn muốn cuộn lùi và văn bản đang được cập nhật liên tục. txa.setText ("") đặt thanh cuộn trở lại ở đầu và cùng một vấn đề được áp dụng.

Giải pháp của tôi là mở rộng lớp TextArea, đồng thời thêm thẻ FXML từ textArea vào LogTextArea. Trong trường hợp công trình này, nó gây ra rõ ràng các vấn đề trong xây dựng cảnh như nó không biết gì thành phần này là

import javafx.scene.control.TextArea; 
import javafx.scene.text.Font; 

public class LogTextArea extends TextArea { 

private boolean pausedScroll = false; 
private double scrollPosition = 0; 

public LogTextArea() { 
    super(); 
} 

public void setMessage(String data) { 
    if (pausedScroll) { 
     scrollPosition = this.getScrollTop(); 
     this.setText(data); 
     this.setScrollTop(scrollPosition); 
    } else { 
     this.setText(data); 
     this.setScrollTop(Double.MAX_VALUE); 
    } 
} 

public void pauseScroll(Boolean pause) { 
    pausedScroll = pause; 
} 

} 
3

Thay thế cho rằng lỗi setText lạ mà không sử dụng appendText

textArea.selectPositionCaret(textArea.getLength()); 
textArea.deselect(); //removes the highlighting 
1

Một phụ lục I sẽ thêm vào của jamesarbrown phản ứng sẽ là điều này sẽ là sử dụng một thuộc tính boolean thay vì vậy bạn có thể truy cập nó từ bên trong FXML. Một cái gì đó như thế này.

import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.scene.control.TextArea; 

public class LogTextArea extends TextArea { 
    private final BooleanProperty pausedScrollProperty = new SimpleBooleanProperty(false); 
    private double scrollPosition = 0; 

    public LogTextArea() { 
     super(); 
    } 

    public void setMessage(String data) { 
     if (isPausedScroll()) { 
      scrollPosition = this.getScrollTop(); 
      this.setText(data); 
      this.setScrollTop(scrollPosition); 
     } else { 
      this.setText(data); 
      this.setScrollTop(Double.MAX_VALUE); 
     } 
    } 

    public final BooleanProperty pausedScrollProperty() { return pausedScrollProperty; } 
    public final boolean isPausedScroll() { return pausedScrollProperty.getValue(); } 
    public final void setPausedScroll(boolean value) { pausedScrollProperty.setValue(value); } 
} 

Tuy nhiên, vấn đề với câu trả lời này là nếu bạn bị tràn ngập với một số tiền bất hợp lý lớn của đầu vào (như có thể xảy ra khi lấy một khúc gỗ từ một suối IO) thread JavaFX sẽ bị khóa vì TextArea được quá nhiều dữ liệu.