在JavaFX中,如何从鼠标单击的事件中获取鼠标指针下的字符(在JavaFX.scene.text.text对象中)的索引?或者更一般地说,如何获取位于javafx.scene.text.text节点中(x,y)坐标处的字符的索引?
我已经使用node.queryAccessibleAttribute()找到了索引,但这感觉有点像是一个黑客攻击,不是JavaFX API的正确使用:
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import static javafx.scene.AccessibleAttribute.OFFSET_AT_POINT;
public class TextClicked extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
final Text textNode = new Text("Hello, world!");
textNode.setOnMouseClicked(event -> {
final int idx = (int) textNode.queryAccessibleAttribute(OFFSET_AT_POINT, new Point2D(event.getScreenX(), event.getScreenY()));
System.out.println("Character clicked: " + textNode.getText().charAt(idx));
});
primaryStage.setScene(new Scene(new HBox(textNode)));
primaryStage.show();
}
}
JavaFX并不真正鼓励这样一种功能,即使用控件注册事件处理程序,然后检查事件的低级细节(例如鼠标坐标),以推断事件的语义信息。首选的方法是在场景图中用单个包含的节点注册监听器。例如,在Swing中,您可以先使用JList
然后使用LocationToIndex(...)
方法注册侦听器,以获取JList
中项的索引,而在JavaFX中,您可以使用单独的ListCell
而不是ListView
本身注册侦听器。
因此,这样做的“惯用”方法可能是创建textflow
并向其添加单独的text
。要确定单击哪个文本
,您可以用每个单独的文本注册监听器。
您可以创建一个可重用的类来封装此功能,当然,根据需要公开包含的textflow
的尽可能多的API。
下面是一个相当基本的例子:
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.InputEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class ClickableTextExample extends Application {
@Override
public void start(Stage primaryStage) {
ClickableText text = new ClickableText("The quick brown fox jumped over the lazy dog.");
text.asNode().addEventHandler(TextClickEvent.CLICKED, e -> {
System.out.println("Click on "+e.getCharacter()+" at "+e.getIndex());
});
StackPane root = new StackPane(text.asNode());
Scene scene = new Scene(root, 350, 120);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class ClickableText {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text ;
}
public String getText() {
return textProperty().get();
}
public void setText(String text) {
textProperty().set(text);
}
private final TextFlow textFlow ;
public ClickableText(String text) {
textFlow = new TextFlow();
textProperty().addListener((obs, oldText, newText) ->
rebuildText(newText));
setText(text);
}
public Node asNode() {
return textFlow ;
}
private void rebuildText(String text) {
List<Text> textNodes = new ArrayList<>();
for (int i = 0; i < text.toCharArray().length; i++) {
char c = text.charAt(i);
Text textNode = new Text(Character.toString(c));
textNodes.add(textNode);
registerListener(textNode, i);
}
textFlow.getChildren().setAll(textNodes);
}
private void registerListener(Text text, int index) {
text.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
TextClickEvent event = new TextClickEvent(text.getText().charAt(0), index, textFlow, textFlow);
Event.fireEvent(textFlow, event);
});
}
}
public static class TextClickEvent extends InputEvent {
private final char c ;
private final int index ;
public static final EventType<TextClickEvent> CLICKED = new EventType<TextClickEvent>(InputEvent.ANY);
public TextClickEvent(char c, int index, Node source, Node target) {
super(source, target, CLICKED);
this.c = c ;
this.index = index ;
}
public char getCharacter() {
return c ;
}
public int getIndex() {
return index ;
}
}
public static void main(String[] args) {
launch(args);
}
}
另一种解决方案是使用不可编辑的文本字段并将其样式设置为文本
(或标签
)。然后可以在用户单击后检查caretposition
。
这段代码基于JavaFX中可复制的label/textfield/labeledtext
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class TextClicked extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
final TextField textNode = new TextField("Hello, world!");
textNode.setEditable(false);
textNode.getStyleClass().add("clickable-text");
textNode.setOnMouseClicked(event -> {
final int idx = Math.max(0, textNode.getCaretPosition() - 1);
System.out.println("Character clicked: " + textNode.getText().charAt(idx));
});
Scene scene = new Scene(new HBox(textNode));
scene.getStylesheets().add("clickable-text.css");
primaryStage.setScene(scene);
primaryStage.show();
}
}
后来呢
clickable-text.css:
.clickable-text, .clickable-text:focused {
-fx-background-color: transparent ;
-fx-background-insets: 0px ;
}
我已经复制了某个节点的xpath Chrome返回 //*[@id=“\uuuuuw2\u cEfEsuQ\u列表项目”]/div/div[2]/div/div[1]/div[2]/a[1] 在Chrome控制台中执行此操作将返回 0可以扩展并包含许多子节点(我删除了其中的大部分,因为我在问题中抱怨代码太多),如下所示: 我需要返回和节点的xpath。我在上尝试了不同的变体,但都没有成功。我该怎么
问题内容: 我希望获得“我是文本节点”,不希望删除“ edit”标签,并且需要跨浏览器解决方案。 问题答案: 这将获取所选元素的,然后对其应用过滤功能。过滤器功能仅返回文本节点(即带有的节点)。
问题内容: 我想获取给定UTF-8字符串的UCS-2代码点。例如,单词“ hello”应变为类似“ 0068 0065 006C 006C 006F”的名称。请注意,字符可以来自任何语言,包括诸如东亚语言之类的复杂文字。 因此,问题归结为“将给定字符转换为其UCS-2代码点” 但是如何?拜托,由于我非常着急,任何帮助都将不胜感激。 提问者的答覆转录为答案 感谢您的答复,但这需要在PHP v 4或5
我在变量中有一个字符串,我想提取第二个冒号后面的数字,即。那么,我怎样才能提取那个数字呢?
问题内容: 我有一段这样的HTML: 我有一个与此HTML匹配的WebElement。如何从中仅提取“标题”?方法.getText()返回“ Title \ nAuthor”。 问题答案: 您无法在WebDriver API中执行此操作,而必须在代码中执行。例如: 请注意,结尾的换行符实际上是元素文本的一部分,因此,如果您不想要它,则需要将其删除。
我在打印同一行的表格数据时遇到了问题。当然,我可以用< code>css_selector("td")来标识,但是这样会在同一列中打印出:姓名地址城市/州电话,而我试图在同一行中创建:姓名、地址、城市/州电话 HTML:(见附图) 这似乎是一个非常愚蠢的问题...但是我已经被困了相当长的一段时间,并且无法隔离< code > 代码: 我以这种方式识别它,试图简单地返回正在进行的兄弟姐妹的文本...