使用 Robot 類來操作 Keys 沒有枚舉出來的按鍵操作
1.在 WebDriver 中,Keys 枚舉出了鍵盤上大多數的非字母類按鍵,從 F1 到 F10,NUMPAD0 到 NUMPAD9、ALT\TAB\CTRL\SHIFT 等等,你可以通過以下連結檢視 Keys 枚舉出來的所有按鍵,Enum Keys。 但是并沒有列出鍵盤上的所有按鍵,比如字母鍵 a、b、c、d … z,一些符号鍵比如:‘ {}\[] ’、‘ \ ’、‘。’、‘ ? ’、‘:’、‘ + ’、‘ - ’、‘ = ’、、‘“”’,還有一些不常用到的功能鍵如 PrtSc、ScrLk/NmLk。對于字母鍵和符号鍵,前面我們已經提到可以直接使用 sendKeys(“a”),sendKeys(“/”) 的方式來觸發這些鍵盤事件。而對于一些功能組合鍵,如 Fn + NmLk 來關閉或者打開數字鍵,或者 Alt+PrtSC 來抓取目前螢幕的活動視窗并儲存到圖檔,通過 WebDriver 的 Keys 是沒辦法操作的。 這個時候我們就需要用到 Java 的 Robot 類來實作對這類組合鍵的操作了。
2.下面就以對 Alt+PrtSc 為例介紹一下 Robot 對鍵盤的操作。如代碼清單 10。
通過 Robot 發出組合鍵動作
public static void sendComposeKeys(String fileName) throws Exception {
Robot robot = new Robot();
robot.keyPress(java.awt.event.KeyEvent.VK_ALT);
robot.keyPress(java.awt.event.KeyEvent.VK_PRINTSCREEN); ,
robot.keyRelease(java.awt.event.KeyEvent.VK_ALT);
Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable data = sysc.getContents(null);
if (data != null) {
if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) {
Image image = (Image) data
.getTransferData(DataFlavor.imageFlavor);
writeImageToFile(image, fileName);
}
} }
Robot 類對鍵盤的處理是通過 keyPress(int keycode)、keyRelease(int keycode) 方法來實作的,其中他們需要的參數是鍵盤按鍵對應的虛拟鍵碼,虛拟鍵碼的值可以通過 KeyEvent 類來擷取。在 Java API 中對于虛拟鍵碼的解釋如下: 虛拟鍵碼用于報告按下了鍵盤上的哪個鍵,而不是一次或多次鍵擊組合生成的字元(如 "A" 是由 shift + "a" 生成的)。 例如,按下 Shift 鍵會生成 keyCode 為 VK_SHIFT 的 KEY_PRESSED 事件,而按下 'a' 鍵将生成 keyCode 為 VK_A 的 KEY_PRESSED 事件。釋放 'a' 鍵後,會激發 keyCode 為 VK_A 的 KEY_RELEASED 事件。另外,還會生成一個 keyChar 值為 'A' 的 KEY_TYPED 事件。 按下和釋放鍵盤上的鍵會導緻(依次)生成以下鍵事件:
KEY_PRESSED
KEY_TYPED(隻在可生成有效 Unicode 字元時産生。)
KEY_RELEASED
是以當測試中需要用到按下鍵盤 Alt+PrtSc 鍵的時候,隻需要執行代碼清單 10 中兩個 keyPress() 和一個 keyRelease() 方法即可。
3.當這兩個按鍵執行結束之後,螢幕上面的活動視窗已經儲存到剪切闆中。如果需要将其儲存本地圖檔,隻需要從剪切闆讀取并通過 JPEGImageEncoder 類或者 ImageIO 類将其寫入本地即可。
使用 JPEGImageEncoder 将 Image 對象儲存到本地
/**
*
* @Description: 這個方法用來将 Image 對象儲存到本地,主要是通過 JPEGImageEncoder 類來實作圖像的
* 儲存
* @param image : 要儲存的 Image 對象
* @param filename : 儲存圖檔的檔案名稱
*/
public static void writeImageToFile(Image image, String fileName) {
try {
// 擷取 Image 對象的寬度和高度, 這裡的參數為 null 表示不需要通知任何觀察者
int width = image.getWidth(null);
int height = image.getHeight(null);
BufferedImage bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
// 通過 BufferedImage 繪制圖像并儲存在其對象中
bi.getGraphics().drawImage(image, 0, 0, null);
// 建構圖像名稱及儲存路徑
String name = Const.DIRECTORY + fileName + Const.FORMAT;
File dir = new File(Const.DIRECTORY);
if (!dir.exists()) {
dir.mkdir();
}
FileOutputStream out = new FileOutputStream(name);
@SuppressWarnings("restriction")
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(bi);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
通過 JPEGImageEncoder 類将 Image 對象寫到本地檔案流,注意 Image 對象是在代碼清單 10 中的如下語句擷取到的:
Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable data = sysc.getContents(null);
if (data != null) {
if (data.isDataFlavorSupported(DataFlavor.imageFlavor)) {
Image image = (Image) data
.getTransferData(DataFlavor.imageFlavor);
writeImageToFile(image, fileName);
}
}
使用 ImageIO 将 Image 對象儲存到本地
/**
*
* @Description: 通過使用 ImageIO 類來儲存 Image 對象為本地圖檔
* @param image : 需要儲存的 Image 對象
* @param filename : 檔案名
*/
public static void saveImage(Image image, String fileName) throws Exception {
// 擷取 Image 對象的高度和寬度
int width = image.getWidth(null);
int height = image.getHeight(null);
BufferedImage bi = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
//通過 BufferedImage 繪制圖像并儲存在其對象中
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
File f = new File(fileName);
// 通過 ImageIO 将圖像寫入到檔案
ImageIO.write(bi, "jpg", f);
}