JavaFX 8对"textarea"中的行进行计数. [英] JavaFX 8 count rows in "textarea"

查看:356
本文介绍了JavaFX 8对"textarea"中的行进行计数.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试计算TextArea中的行数
这是TextArea属性PrefWidth 600和PrefHeight 620,以及MaxHeight 620
自动换行设置为true.我们将JavaFX 8与Scene Builder结合使用
我们有一个textPropertyListiner,当TextArea.getLength大于某个值时,它将触发警报.
此方法的问题在于它不考虑用户输入回车符\ n

We are trying to count the number of rows in a TextArea
Here are the TextArea properties PrefWidth 600 and PrefHeight 620 with MaxHeight 620
Wrap Text is set to true. We are using JavaFX 8 with Scene Builder
We have a textPropertyListiner that will fire an Alert when the TextArea.getLength is greater than some value
The issue with this method is it does not consider the user entering a carriage return \n

因此我们实现了此代码以捕获\ n

So we implemented this code to capture the \n

    String toCount = txaDiaryEntry.getText();
    String [] lineArray = toCount.split("\n");
    int LA = lineArray.length - 1;

    if(LA == 0){
      rc = rc - 1;
      System.out.println("###### LA "+LA+" RC "+rc);
    }

if测试始终为零,因此每次输入回车符后用户每次键入任何内容均会运行
这段代码在textPropertyListiner
中 输入的文本进行换行时,不会创建\ n
我们查看了许多旧帖子,并尝试了一些没有结果的示例
问题是如何计算具有回车符和换行符的TextArea中的行?
在测试时,我注意到所发布代码的一些问题是LA值继续增加.因为我们很少使用Array,所以我的猜测是,当值达到1时需要清除Array
因此,如果有人愿意解释如何使用String []数组完成此操作,我们将进行测试

The if test is always ZERO so this runs every time the user types anything after one carriage return is entered
This code is inside the textPropertyListiner
When the entered text does a line wrap no \n is created
We have looked at numerous old post and tried a few examples with no results
The question is how to count rows in a TextArea that has carriage returns and line wrap is true?
As I am testing I notice some of the issue with the posted code is that the LA value continues to increase. Because we seldom work with Array My guess is that the Array needs to be cleared when the value reaches 1
So if anyone would care to explain how to accomplish that with this String[] array we will give that a test

我们已经对问题代码进行了编辑,以反映计数两个换行以及用户按下ENTER键时的工作示例.虽然这项工作可行,但我们可能会补充说,使用行计数来防止进一步的文本输入不如计算TextArea中的字符数那么有利.

@Override
public void initialize(URL url, ResourceBundle rb) {
txtTitle.setStyle("-fx-text-fill: black;");
getDate();

    if(doEDIT.equals("TRUE")){
       btnEdit.setVisible(true);
       btnSave.setVisible(false);
        try {
            ReadChildTable();
        } catch (SQLException ex) {
            Logger.getLogger(EnterController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    try {
        ReadParent();
    } catch (SQLException | IOException ex) {
        Logger.getLogger(EnterController.class.getName()).log(Level.SEVERE, null, ex);
    }

    txaDiaryEntry.textProperty().addListener((observable, oldValue, newValue) -> {

    EC = txaDiaryEntry.getLength();
    tEC = tEC + 1;
    // this counts line wraps every 62 char
    if(tEC == 62){
        RC = RC - 1;
        tEC = 0;
    }

    // This counts ENTER key presses
    String toCount = txaDiaryEntry.getText();
    String [] lineArray = toCount.split("\n");
    LA = lineArray.length - 1;

    if(LA == tLA){
        tLA = LA + 1;
        RC = RC - 1;
    }else if(tLA < LA){
            tLA = LA + 1;
             RC = RC - (LA - 1);
    }else{  
    }

    // This test counter
    int minus = EC+(LA * 40);
    int val = 1200 - minus ;
    txtCR.setText(String.valueOf(val));
    uEC = uEC - val;

    if(LA == 0){
       uEC = 1200;
    }else{
       uEC = 960;// 880
    }

    if(EC > uEC){
    //if(RC == 0){  
        alertTYPE = "4";
        //RC = RC + 1;
        try {
            customAlert();
        } catch (IOException ex) {
            Logger.getLogger(EnterController.class.getName()).log(Level.SEVERE, null, ex);
        }
        txaDiaryEntry.requestFocus();
    }     
    });     
} 

请注意代码中的注释,因为此方法可以管理其他任务.

Please see comments in the code as this method manages other tasks.

推荐答案

@Slaw在他的评论之一中已经指出,没有 public API可以访问textArea中的行数(由我强调).另一方面,如果我们足够大胆并且允许使用内部组件,则可以使用内部API满足我们的需求.

As already noted by @Slaw in one of his comments, there is no public API to access the line count in a textArea (emphasis by me). On the other hand, there is internal API that provides what we need - if we are daring enough and allowed to work with internals.

查看公共api并深入研究TextAreaSkin的实现细节,结果发现(当前,最多fx13,可能更高)

Looking at public api and digging into the implementation details of TextAreaSkin, it turns out that (currently, up to fx13 and probably later)

  • textArea.getParagraphs()似乎返回由硬换行符分隔的charSequences
  • 皮肤将所有段落合并到一个文本节点中
  • 文本具有-处理行/字符布局的textLayout字段
  • textLayout提供了一种方法getLines(),该方法返回由软换行符或硬换行符分隔的textLines数组,用于计数,我们仅对其长度感兴趣.
  • textArea.getParagraphs() seems to return the charSequences that are separated by a hard linebreak
  • the skin merges all paragraphs into a single text node
  • text has-a textLayout field that handles the line/char layout
  • textLayout provides a method getLines() which returns an array of textLines separated by either soft or hard linebreaks, for counting we are only interested in its length.

下面是一个简单的示例,演示了如何利用这些内部组件.基本上,它查找区域的文本节点(在粘贴皮肤后可用),以反射方式访问其textLayout并查询lines数组的长度.

Below is a quick example that demonstrates how to make use of these internals. Basically, it looks up the area's text node (available after the skin is attached), reflectively accesses its textLayout and query the length of the lines array.

请注意,这是针对fx9 +(与fx8相比,变化不大,除了将皮肤拉到公共范围内,尽管未检查).为了允许内部访问,我们需要在编译时和运行时都调整模块访问限制.

Note that this is for fx9+ (probabbly not much changed against fx8 except for pulling the skins into public scope, didn't check, though). To allow access to internals, we need to tweak module access restrictions at both compiletime and runtime.

编译时间:

--add-exports javafx.graphics/com.sun.javafx.scene.text=ALL_UNNAMED

运行时:

--add-opens javafx.graphics/com.sun.javafx.scene.text=ALL-UNNAMED
--add-opens javafx.graphics/javafx.scene.text=ALL-UNNAMED

示例:

public class TextAreaLineCount extends Application {

    String info = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
            "Nam tortor felis, pulvinar in scelerisque cursus, pulvinar at ante. " +
            "Nulla consequat congue lectus in sodales.";

    private Parent createContent() {
        TextArea area = new TextArea(info);
        area.setWrapText(true);

        area.appendText("\n" + info);

        Button append = new Button("append paragraph");
        append.setOnAction(e -> {
            area.appendText("\n " + info);
            LOG.info("paragraphs: " + area.getParagraphs().size());
        });
        Button logLines = new Button("log lines");
        logLines.setOnAction(e -> {
            Text text = (Text) area.lookup(".text");
            // getTextLayout is a private method in text, have to access reflectively
            // this is my utility method, use your own :)
            TextLayout layout = (TextLayout) FXUtils.invokeGetMethodValue(Text.class, text, "getTextLayout");
            LOG.info("" + layout.getLines().length);
        });
        BorderPane content = new BorderPane(area);
        content.setBottom(new HBox(10, append, logLines));
        return content;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle(FXUtils.version());
        stage.show();
    }

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

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger
            .getLogger(TextAreaLineCount.class.getName());

}

这篇关于JavaFX 8对"textarea"中的行进行计数.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆