Java JScrollPane中的JTextArea,查看坐标转换
我试图在视图坐标和视口坐标之间进行转换。 但是JViewport/JScrollpane似乎并不像文档中描述的那样工作<代码>JViewport.toViewCoordinates() 认为视图始终位于组件的左上角,尽管情况显然并非如此Java JScrollPane中的JTextArea,查看坐标转换,java,swing,jscrollpane,jtextarea,Java,Swing,Jscrollpane,Jtextarea,我试图在视图坐标和视口坐标之间进行转换。 但是JViewport/JScrollpane似乎并不像文档中描述的那样工作JViewport.toViewCoordinates() 认为视图始终位于组件的左上角,尽管情况显然并非如此 String text = "blahblahblah\nblahblah\nblah"; JFrame frame = new JFrame("title"); JTextArea textArea = new JTextArea(text, 1, 30); // s
String text = "blahblahblah\nblahblah\nblah";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30); // shows only one line
frame.add(new JScrollPane(textArea));
frame.pack();
frame.setVisible(true);
textArea.setCaretPosition(text.length()); // now showing the last line
JViewport viewport = ((JViewport)textArea.getParent());
viewport.getViewRect(); // returns java.awt.Rectangle[x=0,y=0,width=330,height=16]
viewport.getViewPosition(); // returns java.awt.Point[x=0,y=0]
viewport.toViewCoordinates(new Point(0,0)); // returns java.awt.Point[x=0,y=0]
以上是人为的例子。我的真实JTextArea
大于一行。我不需要JTextArea“model”坐标(文本中的偏移量)。我需要真正的二维坐标
视图位置不应为(0,0),因为视口中的第一个可见字符实际上位于JTextArea的第三行
关于如何在使用JScrollPane时在视图和组件坐标之间进行转换,还有其他建议吗
---增加---
这也失败了
SwingUtilities.convertPoint(viewport,0,0, textArea);
(java.awt.Point) java.awt.Point[x=0,y=0]
---增加---
这是最后的工作版本,基于我收到的答案。
它显示了java.awt.Point[x=0,y=32]
这正是我所期望的
@Test
public void test() throws InterruptedException {
String text = "blahblahblah\nblahblah\nblah";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30);
frame.add(new JScrollPane(textArea));
frame.pack();
frame.setVisible(true);
textArea.setCaretPosition(text.length());
final JViewport viewport = ((JViewport)textArea.getParent());
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run() {
System.out.println(viewport.getViewPosition());
}
});
Thread.sleep(1000);
}
可能
是否有用?问题在于获取viewPosition()的方法在视口实际滚动之前执行。这是因为有时Swing会将代码添加到事件线程的末尾以供以后处理 通常,这个问题可以通过将代码包装在SwingUtilities.invokeLater()中来解决,这样代码就可以在Swing完成所有处理后执行。然而,在下面的简单演示中,我发现我需要添加两个invokeLater()方法。我不知道为什么 向上/向下移动插入符号,您将看到视图位置的更改。第二个值将包含正确的位置:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test5
{
public static void createAndShowGUI()
{
String text = "one\ntwo\nthree\nfour\nfive";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30); // shows only one line
JScrollPane scrollPane = new JScrollPane( textArea );
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
final JViewport viewport = scrollPane.getViewport();
textArea.addCaretListener( new CaretListener()
{
public void caretUpdate(CaretEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("First : " + viewport.getViewPosition() );
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("Second: " + viewport.getViewPosition() );
}
});
}
});
}
});
textArea.setCaretPosition(text.length());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
这也失败了。不过,我把它添加到了上面的问题中。谢谢。我不是有意投你反对票,但是系统现在不允许我改变。EDT。非常感谢。你帮我省了很多工作。如果我在测试中更加勤奋一点,我就不会错过这个机会。我编辑了我的问题以包含最终的工作版本,它比您的稍微简单一些。是的,在您的简单示例中,您只需要一个invokeLater()。出于某种原因,当您通过在“插入符号移动”上跟踪视口位置来动态执行此操作时,您需要两个invokeLater()。我不知道为什么。此外,
JViewport.toViewCoordinates()
仍然失败并返回点(0,0)的(0,0),但另一个答案是,SwingUtilities.convertPoint
工作正常。
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test5
{
public static void createAndShowGUI()
{
String text = "one\ntwo\nthree\nfour\nfive";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30); // shows only one line
JScrollPane scrollPane = new JScrollPane( textArea );
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
final JViewport viewport = scrollPane.getViewport();
textArea.addCaretListener( new CaretListener()
{
public void caretUpdate(CaretEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("First : " + viewport.getViewPosition() );
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("Second: " + viewport.getViewPosition() );
}
});
}
});
}
});
textArea.setCaretPosition(text.length());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}