我试图这样做,以便当我点击某个字符串时,闪烁的光标不会被放置在那里。类似于命令行界面中的工作目录显示。 我以为我可以
问题是,文本位于TextArea中,因此我必须覆盖TextAreas MouseEvent侦听器。
对于这个问题,似乎有一个更好,更少hacky的解决方案。我更喜欢JavaFX中的答案,但如果不可能,那么Swing答案就可以了。
答案 0 :(得分:1)
尝试以下解决方案,看看它是否合适。它的作用是覆盖positionCaret
中的TextArea
方法,并防止它在用户点击阻止范围内时执行任何操作。在该示例中,用户无法在其中放置插入符号的被阻止文本是" Lorem Ipsum:"每行都有前缀。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class InputBlocker extends Application {
private static final String TEXT =
"Lorem ipsum: dolor sit amet, consectetur adipiscing elit. Nulla in nisi sed neque porttitor volutpat. \n" +
"\n" +
"Lorem ipsum: Maecenas non mauris scelerisque, egestas felis quis, venenatis risus. Etiam eu ornare justo, at pulvinar tortor. ";
private static final String FORBIDDEN_PREFIX = "Lorem ipsum: ";
@Override
public void start(final Stage stage) throws Exception {
TextArea textArea = new BlockingTextArea(TEXT, FORBIDDEN_PREFIX);
textArea.setWrapText(true);
stage.setScene(new Scene(textArea));
stage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
class BlockingTextArea extends TextArea {
private final String forbiddenPrefix;
private List<Range> blockedRanges;
public BlockingTextArea(String text, String forbiddenPrefix) {
super(text);
this.forbiddenPrefix = forbiddenPrefix;
this.blockedRanges = findBlockedRanges(text);
textProperty().addListener((observable, oldValue, newValue) ->
blockedRanges = findBlockedRanges(newValue)
);
}
@Override
public void positionCaret(int pos) {
Optional<Range> blockedRange =
blockedRanges.stream()
.filter(range -> range.containsExclusive(pos))
.findFirst();
if (blockedRange.isPresent()) {
return;
}
super.positionCaret(pos);
}
private List<Range> findBlockedRanges(String text) {
List<Range> blocked = new ArrayList<>();
int idx = 0;
while (idx < text.length()) {
if (text.startsWith(forbiddenPrefix, idx)) {
blocked.add(new Range(idx, idx + forbiddenPrefix.length()));
idx += forbiddenPrefix.length();
}
int nextIdx = text.indexOf("\n", idx);
if (nextIdx == -1) {
break;
}
idx = nextIdx + 1;
}
return blocked;
}
private class Range {
private final int min;
private final int max;
Range(int min, int max) {
this.min = min;
this.max = max;
}
public int getMin() {
return min;
}
public int getMax() {
return max;
}
boolean containsExclusive(int pos) {
return min <= pos && pos < max;
}
}
}
上述解决方案存在一些可用性问题:
replaceText
或deleteText
可能有助于解决这个问题。selectPositionCaret
或selectRange
或其他一些方法可能有助于解决这个问题。但无论如何,也许上面的代码可以举例说明如何解决问题并解决问题。
而不是TextArea,第三方RichTextFX可能是一个更好的候选控件,可用于此类应用程序,因为它允许样式化文本内容,可以提供更好的用户体验,其中插入符号的文本无法定位的方式与文本的其余部分的方式不同。我还没有就如何为RichTextFX实现插入符号阻止功能进行任何调查。