2012-05-06 23 views
18

機器人是AWT圖書館的一部分,但它與大多數圖書館的其餘部分看起來有很大不同。我創建了一個Swing GUI,將Swing與Java Native Access(JNA)和Robot混合在一起,允許Java驅動一些MS Windows/Citrix工作程序。我的直覺是,由於Robot會在「平臺本地輸入隊列」中排列事件,因此我想要做的最後一件事是在EDT上運行它,但另一方面,AWT和Swing庫中的大部分類應該在上運行Swing事件線程。因此,爲了澄清這一點,我想讓我儘可能地提出一個具體的問題:Do Robot方法是否需要在事件隊列上運行?

如果機器人方法(特別是按鍵和釋放,鼠標移動,鼠標按下和釋放)運行在或關閉Swing事件調度線程(EDT)?

+1

我不知道答案,但問題+1。我一直對Sun/Oracle的聲明感到困惑:「應該在EDT上創建和更新** Swing ** GUI」 - 爲什麼這個***不適用於AWT? –

+1

在這裏,我猜不知道,這會有多大幫助,但斯蒂芬[答案](http://groups.google.com/group/jfxtras-dev/browse_thread/thread/d0521de3af5e3ded)可能可以幫助位,在後臺啓動Robot相關的東西。 –

+0

Andrew和Kindly Udders,感謝您提供有用信息。如果有其他事情發生在你身上,請分享! –

回答

10

Robot您提到的方法應該是而不是可以在EDT上運行。縱觀源代碼透露,這些「事件」的方法,每一個都有一個共同點(的afterEvent調用):

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"); 
    } 
} 

如果你調用任何這些方法在EDT而Robot.isAutoWaitForIdletrue,將會拋出異常。這意味着即使isAutoWaitForIdlefalse,這些方法也不應該從EDT中調用。

+0

就是這樣!謝謝! –

6
  • API相當準確的會談,然後我明白,如果從EDT調用或不

使用類來生成輸入事件可以發佈事件的不同之處在於機器人應該被忽略AWT事件隊列或AWT組件,因爲事件是在平臺的本機輸入隊列中生成的。

  • 我rellative在Java中新的,我第一次接觸是Java1.6.009,那麼我不能爲AWT比較變化和Java1.3(出生時),Swing和休息Java1.4

我的例子

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

感謝一如既往mKorbel(你的名字是怎麼回事?)。讓我稍後再研究並回復你。 –

+0

Miroslav,Mike應該是英語......,我的問題是這個控制檯是通過Citrix Farm的遠程會話? – mKorbel

+0

(Miroslav):驅動應用程序的性質(由我的Java程序驅動)將取決於位置。如果我在辦公室,它將是一個獨立的應用程序。如果我在家中並通過計算機連接到辦公室,它將成爲Citrix客戶端(這極大地限制了我可以與之交互的方式)。 –

6

放大上@ mKorbel的周到的答案,並確認他的實證結果,注意如何使用各種方法Robot代表到RobotPeer的內部實例接口,其本機實現因平臺而異。而且,這些方法是同步的。無論來源如何,合成事件全部到達EventQueue

+0

我認爲對於反覆截圖需要通過Thread.sleep(int)打破所有線程; +1,我也認爲從Java1-3變成的以前的AWT方法可以忽略如果有沒有EDT,簡單的工作,有些奇怪的延遲,但作品 – mKorbel

+0

['Zoom'](http://stackoverflow.com/ a/3742841/230513)在'mouseDragged()'中調用'createScreenCapture()';它似乎沒有任何延遲,但每個'MouseEvent'是分開的。 – trashgod

+0

非常感謝垃圾! –

相關問題