Do Robot methods need to be run on the event queue?

前端 未结 3 1619
小蘑菇
小蘑菇 2020-12-06 05:13

Robot is part of the AWT library, but it seems quite different from most all the rest of the library. I am creating a Swing GUI that mixes Swing with Java Native Access (JNA

相关标签:
3条回答
  • 2020-12-06 05:27

    The Robot methods you mentioned should not be run on the EDT. Taking a look at the source code revealed that each one of these "event" methods has one thing in common (the afterEvent call):

    public synchronized void keyPress(int keycode) {
        checkKeycodeArgument(keycode);
        peer.keyPress(keycode);
        afterEvent();
    }
    
    public synchronized void mousePress(int buttons) {
        checkButtonsArgument(buttons);
        peer.mousePress(buttons);
        afterEvent();
    }
    
    // etc
    
    private void afterEvent() {
        autoWaitForIdle();
        autoDelay();
    }
    
    private void autoWaitForIdle() {
        if (isAutoWaitForIdle) {
            waitForIdle();
        }
    }
    
    public synchronized void waitForIdle() {
        checkNotDispatchThread();
        /* snip */
    }
    
    private void checkNotDispatchThread() {
        if (EventQueue.isDispatchThread()) {
            throw new IllegalThreadStateException("Cannot call method from the event dispatcher thread");
        }
    }
    

    If you call any of these methods on the EDT while Robot.isAutoWaitForIdle is true, an exception will be thrown. This stands to reason that even if isAutoWaitForIdle is false, these methods shouldn't be called from the EDT.

    0 讨论(0)
  • 2020-12-06 05:37
    • API quite exactly talks, then I'm understand that that Robot should be ignore if is invoked from EDT or not

    Using the class to generate input events differs from posting events to the AWT event queue or AWT components in that the events are generated in the platform's native input queue.

    • I'm rellative new in Java, my first touch was Java1.6.009, then I can't compare changes for AWT and (when born) Swing in Java1.3 and rest in Java1.4

    my example

    import javax.imageio.*;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.image.*;
    import java.io.*;
    
    public class CaptureScreen implements ActionListener {
    
        private JFrame f = new JFrame("Screen Capture");
        private JPanel pane = new JPanel();
        private JButton capture = new JButton("Capture");
        private JDialog d = new JDialog();
        private JScrollPane scrollPane = new JScrollPane();
        private JLabel l = new JLabel();
        private Point location;
    
        public CaptureScreen() {
            capture.setActionCommand("CaptureScreen");
            capture.setFocusPainted(false);
            capture.addActionListener(this);
            capture.setPreferredSize(new Dimension(300, 50));
            pane.add(capture);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(pane);
            f.setLocation(100, 100);
            f.pack();
            f.setVisible(true);
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    createPicContainer();
                }
            });
        }
    
        private void createPicContainer() {
            l.setPreferredSize(new Dimension(700, 500));
            scrollPane = new JScrollPane(l,
                    ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
            scrollPane.setBackground(Color.white);
            scrollPane.getViewport().setBackground(Color.white);
            d.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
            d.add(scrollPane);
            d.pack();
            d.setVisible(false);
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("CaptureScreen")) {
                Dimension d1 = Toolkit.getDefaultToolkit().getScreenSize(); // gets the screen size
                Robot r;
                BufferedImage bI;
                try {
                    r = new Robot(); // creates robot not sure exactly how it works
                    Thread.sleep(1000); // waits 1 second before capture
                    bI = r.createScreenCapture(new Rectangle(d1)); // tells robot to capture the screen
                    showPic(bI);
                    saveImage(bI);
                } catch (AWTException e1) {
                    e1.printStackTrace();
                } catch (InterruptedException e2) {
                    e2.printStackTrace();
                }
            }
        }
    
        private void saveImage(BufferedImage bI) {
            try {
                ImageIO.write(bI, "JPG", new File("screenShot.jpg"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void showPic(BufferedImage bI) {
            ImageIcon pic = new ImageIcon(bI);
            l.setIcon(pic);
            l.revalidate();
            l.repaint();
            d.setVisible(false);
            location = f.getLocationOnScreen();
            int x = location.x;
            int y = location.y;
            d.setLocation(x, y + f.getHeight());
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    d.setVisible(true);
                }
            });
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    CaptureScreen cs = new CaptureScreen();
                }
            });
        }
    }
    
    0 讨论(0)
  • 2020-12-06 05:50

    Amplifying on @mKorbel's thoughtful answer, and confirming his empirical result, note how the various Robot methods delegate to an internal instance of the RobotPeer interface, the native implementation of which varies by platform. Moreover, the methods are synchronized. The synthetic events all arrive on the EventQueue, irrespective of the source.

    0 讨论(0)
提交回复
热议问题