18

だから私は TextArea を持っていて、ユーザーが段落を貼り付けたり、書き込んだりすると、垂直方向に拡大して利用可能なすべてのテキストを表示したいと考えています。つまり、テキスト フィールド自体でスクロールバーを使用しないでください...多くの Web ページで起こることと同じです。私を含め、多くのユーザーは、小さなウィンドウで強制的に編集することを好みません。Facebook ステータス更新ボックスの仕組みとまったく同じです。

私はもう試した

myTextArea.autoSize()

に包まれた

myTextArea.textProperty().addListener(new ChangeListener()....);

しかし、それはうまくいきません。現在のサイズに自動的にサイズ変更されて満足していると思います。

左、右、および上部のアンカーは、その親の AnchorPane に設定されます。ボトムを付けた状態と付けていない状態で試してみました。理想的には、テキストエリアの拡大に合わせてアンカー ペインを拡大したいと考えています。

TextProperty を読んで、自分で設定したトリガー サイズを計算してもかまいませんが、ベスト プラクティスが既にある場合、これはハッキーなアプローチのようです。javafx のプロパティとサブオブジェクトの数は非常に難しいため、フォントや段落などが何ピクセルを占めているかを把握しようとするよりも、ここで質問するのが適切だと思われます。

アップデート:

だから私はそれを考えすぎていたのではないかと思いました.スクロールバーをオフにするだけで、残りは起こります. 残念ながら、「scroll」、「vertical」、「vbar」で使用可能なフィールドとメソッドを探しても、使用できるものは何もありません。ScrollTopProperty は別のもののように見えます。

4

5 に答える 5

14

問題; ユーザーの入力またはコピーと貼り付けによってテキストが変更されている間、textArea の高さを拡大または縮小する必要があります。別のアプローチを次に示します。

public class TextAreaDemo extends Application {

    private Text textHolder = new Text();
    private double oldHeight = 0;

    @Override
    public void start(Stage primaryStage) {
        final TextArea textArea = new TextArea();
        textArea.setPrefSize(200, 40);
        textArea.setWrapText(true);

        textHolder.textProperty().bind(textArea.textProperty());
        textHolder.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
            @Override
            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
                if (oldHeight != newValue.getHeight()) {
                    System.out.println("newValue = " + newValue.getHeight());
                    oldHeight = newValue.getHeight();
                    textArea.setPrefHeight(textHolder.getLayoutBounds().getHeight() + 20); // +20 is for paddings
                }
            }
        });

        Group root = new Group(textArea);
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();

        //  See the explanation below of the following line. 
        //  textHolder.setWrappingWidth(textArea.getWidth() - 10);  // -10 for left-right padding. Exact value can be obtained from caspian.css
    }

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

しかし、これには欠点があります。テキストエリアの高さは、複数の行の間に改行 (つまり、Enter キー) がある場合にのみ変化します。ユーザーが十分に長く入力すると、テキストは複数の行に折り返されますが、高さは変化しません。

この欠点を回避するために、この行を追加しました

textHolder.setWrappingWidth(textArea.getWidth() - 10);

primaryStage.show();。ユーザーが改行しない長いタイピングに適しています。ただし、これにより別の問題が発生します。この問題は、ユーザーが「バックスペース」を押してテキストを削除しているときに発生します。この問題は、textHolder の高さが変更され、textArea の高さが新しい値に設定されたときに正確に発生します。IMO バグかもしれませんが、詳しくは観察していません。

どちらの場合も、コピーと貼り付けは適切に処理されています。

于 2013-10-04T20:26:29.077 に答える
0

以前の回答で見つかったコードの一部を使用しました。growTextAreaIfNecessary メソッドは、スクロールバーが表示されなくなるまで textArea の高さを増やします (この例では 20 行に制限されています)。

このアプローチの問題点は、完璧な高さが見つかるまでウィンドウを何度も再描画する必要があることです。

private ScrollBar lookupVerticalScrollBar(Node node) {
    if (node instanceof ScrollBar && ((ScrollBar) node).getOrientation() == Orientation.VERTICAL) {
        return (ScrollBar) node;
    }
    if (node instanceof Parent) {
        ObservableList<Node> children = ((Parent) node).getChildrenUnmodifiable();
        for (Node child : children) {
            ScrollBar scrollBar = lookupVerticalScrollBar(child);
            if (scrollBar != null) {
                return scrollBar;
            }
        }
    }
    return null;
}

private void growTextAreaIfNecessary(TextArea textArea) {
    Platform.runLater(() -> {
        ScrollBar lookupVerticalScrollBar = lookupVerticalScrollBar(textArea);
        int prefRowCount = textArea.getPrefRowCount();

        if (lookupVerticalScrollBar.isVisible() && prefRowCount < 20) {
            textArea.setPrefRowCount(prefRowCount + 1);
            System.out.println("increasing height to: " + (prefRowCount + 1));
            growTextAreaIfNecessary(textArea);
        }
    });
}
于 2020-05-12T17:17:58.377 に答える