Проблема с SwingUtilities.getLocationOnScreen();

У меня есть следующий код внутри ActionListener на "поддержке" JButton. cl.across.text - это другая область JTextArea внутри моего графического интерфейса. Проблема в результатах, приведенных для точки pt1. Рамка имеет размер 600x600, кнопка находится посередине, а JTextArea — посередине справа. Результат команды печати: java.awt.Point[x=501,y=187] java.awt.Point[x=370,y=1062] Теперь первые координаты правильные (проверено с помощью MouseListener), но вторые один полностью вне досягаемости, они даже за пределами моего кадра (считайте, что это 600 и y = 1062). Любой совет, как получить правильные, потому что мне нужно сделать робота, который нажимает, и это моя единственная идея, чтобы получить его с изменением размера графического интерфейса.

Код:

Point pt=new Point(cl.across.text.getLocation());
SwingUtilities.convertPointToScreen(pt, cl.across.text);
Point pt1=new Point(support.getLocation());
SwingUtilities.convertPointToScreen(pt1, support);
System.out.println(pt+" "+pt1);

person Alex Botev    schedule 19.05.2011    source источник
comment
Опубликуйте свой SSCCE (sscce.org), демонстрирующий проблему. Зачем нужен робот. Звучит как плохой дизайн каждый раз, когда вам нужен робот для генерации событий.   -  person camickr    schedule 19.05.2011
comment
Это из-за этой ошибки. Я хочу, чтобы щелчок мыши выполнялся два раза, поэтому мне нужно сгенерировать MouseEvent.   -  person Alex Botev    schedule 19.05.2011


Ответы (2)


Я думаю, что причина, по которой вы получаете неверные координаты точки, заключается в неправильном использовании метода SwingUtilities.convertPointToScreen(point, component);.

Не волнуйтесь, я совершил ту же ошибку, когда использовал этот метод в первый раз. :)

Из описания метода Component.getLocation() получаем, что он возвращает: "экземпляр Point, представляющий левый верхний угол границ компонента в координатном пространстве родительского компонента"

Поэтому в качестве аргумента компонента нам нужно указать его родительский объект, например. SwingUtilities.convertPointToScreen(point, component.getParent());

Таким образом, для вашего случая у вас будет:

Point pt=new Point(cl.across.text.getLocation());
SwingUtilities.convertPointToScreen(pt, cl.across.text.getParent());
Point pt1=new Point(support.getLocation());
SwingUtilities.convertPointToScreen(pt1, support.getParent());
System.out.println(pt+" "+pt1);

Пример: в этом примере вы можете видеть, что getLocationOnScreen() "достаточно хорош", чтобы заставить робота выполнять свою работу, и возвращает тот же результат, что и "правильно" использованный метод SwingUtilities.convertPointToScreen().

Чтобы увидеть, как это работает, запустите пример, уберите руки с мыши и подождите несколько секунд.

import java.awt.AWTException;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class RobotLocOnScreenTest{
    public static void main(String[] args){
        final JTextArea ta = new JTextArea(21, 12);
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                JFrame f = new JFrame();
                JPanel p = new JPanel();
                JTextField tf = new JTextField("asadasdasd", 15);
                p.add(tf);
                p.add(ta);
                p.add(new JTextField(11));
                f.setContentPane(p);
                f.setSize(800, 600);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
                //request focus so the text field tf has it first
                tf.requestFocusInWindow();
            }
        });
        /* A hack to allow the GUI to build so we can see all robot's operations on the area 
        * and avoid the IllegalComponentStateException exception thrown by
        * Component.getLocationOnScreen() method when the component is not showing.
        */
        try{
            Thread.sleep(2000);
        }catch(InterruptedException ex) {
            Logger.getLogger(RobotLocOnScreenTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        findAndOperateOnTextArea(ta);           
    }

    private static void findAndOperateOnTextArea(JTextArea ta){
        try{
            Robot robot = new Robot();
            Point taLOSP = ta.getLocationOnScreen();
            Point taLPBad = ta.getLocation();
            SwingUtilities.convertPointToScreen(taLPBad, ta);           
            Point taLPGood = ta.getLocation();
            SwingUtilities.convertPointToScreen(taLPGood, ta.getParent());
            System.out.println("ta.getLocationOnScreen()=" + taLOSP 
                    + "; taLPBad=" + taLPBad+"; taLPGood="+taLPGood);           
            robot.mouseMove(taLOSP.x, taLOSP.y);
            robot.delay(1111);
            robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_0);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_1);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_2);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_3);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_4);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_5);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_6);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_7);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_8);
            robot.delay(333);
            robot.keyPress(KeyEvent.VK_9);
        }catch(AWTException ex){
            Logger.getLogger(RobotLocOnScreenTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
person Boro    schedule 19.05.2011
comment
Да, это отвечает и решает это вообще. Просто хочу отметить, что в API, который я прочитал в Интернете, описание обоих методов было плохим и даже не включало элемент для верхнего левого угла. В любом случае большое спасибо :) - person Alex Botev; 19.05.2011

«pt» — это точка координат экрана. Итак, вы хотите использовать SwingUtilities.convertPointFromScreen(pt, frame), чтобы преобразовать его в координаты вашего фрейма.

person karmakaze    schedule 19.05.2011
comment
Но мне нужны экранные координаты, так как робот moveMouse() принимает экранные координаты в качестве аргументов. - person Alex Botev; 19.05.2011
comment
В вашем описании ожидались значения от 0 до 600, которые находятся в координатах фрейма. Да, вы можете преобразовать координаты между экраном и рамкой (или мышью, или другим компонентом) по мере необходимости с помощью двух методов convertPoint(To/From)Screen. Чтобы преобразовать из компонента в координаты другого компонента, сначала преобразуйте его в экран, а затем в другой компонент. - person karmakaze; 19.05.2011