麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

JDK1.3中的本地繪制支持

2019-11-18 14:04:54
字體:
來源:轉載
供稿:網友

  作者:Davanum Srinivas

java 技巧 86:JDK1.3 中的本地繪制支持 -- JavaWord
在不犧牲本地 GUI 代碼性能的條件下獲得可移植性并縮短開發周期

(本文選自IBM developerWorks中文網站)

 

摘要
假如您正在使用 JDK1.3,則您可以借助于 Java 2 AWT 本地接口,使用 C 或 C++ 方法來繪制基于 AWT 的 Canvas 對象。因此,本地 GUI 組件可以嵌入到 Java 應用程序中;同時,正像 JDK1.3 以前的其他版本一樣,您可以使用 Java 本地接口從 Java 應用程序中調用本地方法。Davanum Srinivas 解釋了如何在 Java 中使用現有的本地用戶界面庫。他還提供了 Win32 操作系統下的一個具體示例。
在 JDK1.3 出現以前,您僅能將 Java 本地接口用于非用戶界面的工作。JDK 1.3 引入了新的 Java 2 AWT 本地接口,這使您可以在 Java 程序中使用非 Java 的 GUI 組件,盡管這樣做會失去純 Java 解決方案的可移植性。在使用 J2AWT 時,您必須針對要使用它的每個平臺制作本地動態連接庫或共享庫。
下面這段話摘自 JDK1.3 的某個頭文件,它說明了這種新的 API 的開發背景及原因:


AWT 支持使用本地 C 或 C++ 應用程序訪問 AWT 的本地結構。這是為了便于將原有的 C 或 C++ 應用程序移植到 Java 并滿足需要 ... [這些應用程序] 出于性能方面的原因在畫布上自行進行本地繪制
在 JDK1.3 以前,Java 編程沒有明確的方法來訪問基層的同等 GUI 組件的句柄。在 JDK 1.3 中, Sun 公司創建了一種標準機制,通過這種機制,開發人員可以使本地 GUI 應用程序和庫在 Java AWT Canvas 對象中進行繪制。這意味著現在有一種正式的、有保證的方法來獲得支持這一功能的信息。當 JDK 1.3 與其他操作平臺對接時,所有的接口都提供相同的信息 -- 而不管使用的是什么系統。JDK 1.3 的 Windows 版本和 Solaris 版本是首先提供這種支持的實現。

Sun 公司引入這一功能組件有幾方面的原因。首先, JDK 1.3 使得人們可以將依靠第三方產品的復雜原有軟件移植到 Java 上,而不必等到第三方產品本身完成移植以后。第二個原因即性能;假如本地的 GUI 代碼經過人們長時期的努力得到優化,則原樣保留這些軟件具有重要的商業價值。

在本文中,我將介紹一些該功能部件的基本概念。我將逐步開發一個窗口小部件樣例,該窗口小部件使用Win32 API 進行繪制。下圖是最終的窗口小部件的快照,一個帶有笑臉的圓形窗口。



運行中的窗口小部件

分步概覽
第一步,定義一個 Java 類 -- 比如說,Mywindow -- 使其繼續 Canvas 類并重載 paint 方法。您使用 paint 方法執行 AWT 對象的繪制操作,并在覆蓋該方法時加上 native 要害字。覆蓋方法使您能夠使用自己的本地代碼。您必須構建自己的本地代碼并把它編譯成一個動態連接庫,就像我們處理其他的 Java 本地接口應用程序一樣,在本例中,我們將調用 MyWindow.DLL 庫。在 Solaris 和 linux 上則為共享對象或共享庫。您還需要用 System.loadLibrary("MyWindow") 調用將 MyWindow.DLL 庫加載到您的名為 MyWindow 的 Java 類中。

完成這一示例需要二個部分:其一是 MyWindow.Java ,它提供 Canvas 類的子類,其二是 MyWindow.CPP ,它包含基于 Java 本地接口的繪制子程序的入口點。 在參考資源部分可找到 MyWindow.Java、MyWindow.CPP 及自動執行編譯的批處理文件 BUILD.BAT。

第一步: 創建 MyWindow Java 類
J2AWT 用于這種方法時有一個主要的局限性:本地代碼只能對 java.awt.Canvas 類的子類進行操作。這正是 MyWindow 繼續 Canvas 類的原因。在 Java 應用程序中,您可以像使用 Canvas 的其它子類那樣使用 MyWindow;在本例中,我將 MyWindow 添加到 Jwindow 中。

import java.awt.*;
import javax.swing.*;

public class MyWindow extends Canvas {
static {
//加載包含 paint 代碼的庫。
System.loadLibrary("MyWindow");
}

//繪制操作的本地入口點
public native void paint(Graphics g);

public static void main( String[] argv ){
Frame f = new Frame();
f.setSize(300,400);

JWindow w = new JWindow(f);
w.setBackground(new Color(0,0,0,255));
w.getContentPane().setBackground(new Color(0,0,0,255));
w.getContentPane().add(new MyWindow());
w.setBounds(300,300,300,300);
w.setVisible(true);
}
}


請注重:您是在靜態塊中加載 MyWindow.DLL。這正是 Java 應用程序訪問本地代碼的方式。(我稍候就會開發這段本地代碼。)同時還應注重:paint 方法是用 native 要害字聲明的,并且沒有提供任何實現;這樣做是為了讓虛擬機知道,應該從在靜態塊中加載的動態連接庫中調用該本地方法。

第二步:生成該類的 JNI 頭文件
要為以上定義的類生成 Java 本地接口頭文件,需使用 javah MyWindow.class 命令。首先應確保這個類文件在您的 CLASSPATH 中。以下是所生成的 MyWindow.h 的一部分,給出了函數聲明。

/*
* Class: MyWindow
* Method: paint
* Signature: (Ljava/awt/Graphics;)V
*/
JNIEXPORT void JNICALL Java_MyWindow_paint
(JNIEnv *, jobject, jobject);


第三步:開發完整的 MyWindow.CPP
以下是完整的 MyWindow.CPP,其中包含 MyWindow.Java 中所需要的繪圖程序的本地代碼。

#include <windows.h>
#include <assert.h>
#include "jawt_md.h"
#include "MyWindow.h"

#define X(x) (int)(xLeft + (x)*xScale/100) // 縮放宏
#define Y(y) (int)(yTop + (y)*yScale/100) // 以使尺度在 0-100 之間
#define CX(x) (int)((x)*xScale/100)
#define CY(y) (int)((y)*yScale/100)

void DrawSmiley(HWND hWnd, HDC hdc);
HRGN hrgn = NULL;

JNIEXPORT void JNICALL
Java_MyWindow_paint(JNIEnv* env, jobject canvas, jobject graphics)
{
JAWT awt;
JAWT_DrawingSurface* ds;
JAWT_DrawingSurfaceInfo* dsi;
JAWT_Win32DrawingSurfaceInfo* dsi_win;
jboolean result;
jint lock;

// 獲取 AWT
awt.version = JAWT_VERSION_1_3;
result = JAWT_GetAWT(env, &awt);
assert(result != JNI_FALSE);
// 獲取繪圖界面
ds = awt.GetDrawingSurface(env, canvas);
if(ds == NULL)
return;
// 鎖定繪圖表面
lock = ds->Lock(ds);
assert((lock & JAWT_LOCK_ERROR) == 0);

// 獲取繪圖表面的信息
dsi = ds->GetDrawingSurfaceInfo(ds);

// 獲取特定平臺的繪圖信息
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;

HDC hdc = dsi_win->hdc;
HWND hWnd = dsi_win->hwnd;
//////////////////////////////
// !!! 在此處進行繪圖 !!! //
//////////////////////////////
if(hrgn == NULL)
{
RECT rcBounds;
GetWindowRect(hWnd,&rcBounds);
long xLeft = 0; // 用于縮放宏
long yTop = 0;
long xScale = rcBounds.right-rcBounds.left;
long yScale = rcBounds.bottom-rcBounds.top;
hrgn = CreateEllipticRgn(X(10), Y(15), X(90), Y(95));
SetWindowRgn(GetParent(hWnd),hrgn,TRUE);
InvalidateRect(hWnd,NULL,TRUE);
} else {
DrawSmiley(hWnd,hdc);
}
// 釋放繪圖表面的信息
ds->FreeDrawingSurfaceInfo(dsi);
// 為繪圖表面解鎖
ds->Unlock(ds);
// 釋放繪圖表面
awt.FreeDrawingSurface(ds);
}

void DrawSmiley(HWND hWnd, HDC hdc)
{
RECT rcBounds;
GetWindowRect(hWnd,&rcBounds);
long xLeft = 0; // 用于縮放宏
long yTop = 0;
long xScale = rcBounds.right-rcBounds.left;
long yScale = rcBounds.bottom-rcBounds.top;

// 基于控制大小的畫筆寬度
int iPenWidth = max(CX(5), CY(5));
HBRUSH brushBlack;
HBRUSH brushYellow;
HPEN penBlack = CreatePen(PS_SOLID, iPenWidth, RGB(0x00,0x00,0x00));
// 用于繪制填充橢圓的空畫筆
HPEN penNull = CreatePen(PS_NULL, 0, (COLORREF)0);

brushBlack = CreateSolidBrush(RGB(0x00,0x00,0x00));
brushYellow = CreateSolidBrush(RGB(0xff,0xff,0x00));

HPEN pPenSave = (HPEN)SelectObject(hdc, penBlack);
HBRUSH pBrushSave = (HBRUSH)SelectObject(hdc,brushYellow);
Ellipse(hdc,X(10), Y(15), X(90), Y(95)); // 頭部

Arc(hdc,X(25), Y(10), X(75), Y(80), // 嘴部(微笑)
X(35), Y(70), X(65), Y(70));

SelectObject(hdc,&penNull); // 無繪圖寬度
SelectObject(hdc,&brushBlack);

Ellipse(hdc,X(57), Y(35), X(65), Y(50));
Ellipse(hdc,X(35), Y(35), X(43), Y(50)); // 右眼
Ellipse(hdc,X(46), Y(50), X(54), Y(65)); // 鼻子

SetBkMode(hdc,TRANSPARENT); // 使用前景顏色

SelectObject(hdc,pBrushSave);
SelectObject(hdc,pPenSave);
}


這里的要害數據結構是 JAWT,它是在 jawt.h 中定義的(通過 jawt_md.h 包含在內)。它使程序可以訪問本地代碼在基于 Java 的 GUI 組件上繪圖所需的所有信息。本地方法的第一部分是套式:置入 JAWT 結構,獲得一個 JAWT_Win32DrawingSurfaceInfo 結構,鎖定表面(請一次只使用一種繪圖工具!),然后,獲取一個 JAWT_DrawingSurfaceInfo 結構,該結構包含特定平臺下繪圖所必需的指針(在 platformInfo字段中)。它也包含繪圖界面的矩形界限框及當前剪切區域。有關具體信息,請查看 jawt.h 和 jawt_md.h (請參閱下面標題為 “構建環境”的部分)。

Java_MyWindow_paint 是一個入口點,JVM 通過調用它來繪制 MyWindow。輔助函數 DrawSmiley 使用 Win32 調用來完成實際的繪制工作。要在您的應用程序中包含 GetDrawingSurfaceInfo,請使用外部庫 jawt.lib(請參閱 “構建環境”)。

第四步:編輯 BUILD.BAT
在運行 BUILD.BAT 之前首先對它進行編輯,并像如下所示的那樣,為您的 Visual C++ 及 JDK1.3 設置路徑。BUILD.BAT 對 MyWindow.java 進行編譯,生成 MyWindow.h,然后將 MyWindow.CPP 編譯為 MyWindow.DLL。

SET DEVSTUDIO=D:PRogram FilesMicrosoft Visual StudioVC98
SET JDK13=D:JDK1.3


好了,一切預備就緒。在運行該樣例之前,請確保 MyWindow.DLL、JDK1.3BIN 及 JDK1.3JREBIN 都在 PATH 內,還要保證當前目錄在 CLASSPATH 中;這將確保 MyWindow.class 會被成功加載。在確信 PATH 和 CLASSPATH 都設置妥當后,在命令行輸入 java MyWindow 來運行此應用程序。為方便您的使用,window.zip 中包含了一個批處理文件 RUN.BAT(請參閱參考資源)。要為 JDK 1.3 設置PATH 和 CLASSPATH,請編輯 RUN.BAT。

構建環境


頭文件:在 JDK 的 include 目錄中新增了專用于 Windows 的 C 頭文件。它們是:
include/jawt.h.
include/win32/jawt_md.h.


依據 JavaSoft 網站的說明,這些頭文件并不是 Java 2 平臺正式規范的組成部分;提供這些頭文件只是為希望用一種標準化方法訪問本地繪圖功能的開發人員提供一種便利。我認為這表示將 JDK 移植到其它平臺的廠商可以不提供這個 API。


庫:一個以 jawt.lib 命名的新庫已添加到 SDK 的庫目錄中。如前所述,這個庫包含一個用于把 J2AWT 包含到您的應用程序中所需要的入口點。例如,要鏈接到 GetDrawingSurfaceInfo 入口點,您需要在您的程序中包含 jawt.lib。

工具:javah 工具用來為 Java 類的本地函數生成 C/C++ 頭文件,javac 工具用來編譯 Java 源文件。

小結
將原有軟件系統移植到 Java 中并不輕易,尤其是當原有軟件包含高性能的繪圖器時。Java 2 AWT 本地接口使得分階段移植變得較為輕易,它答應您首先移植對性能要求不高的代碼,然后再移植要害的繪制代碼。它同時使第三方窗口小部件開發廠商更能嚴厲地看待針對 Java 產品的開發。有了 Java 2 AWT 本地應用程序接口,您就可以移植原有的 GUI 代碼,并更快地完成開發,這樣就不會犧牲您為提高本地代碼要害部分的性能而作的投資。

作者簡介
Davanum Srinivas 目前在 Computer Associates 公司從事軟件開發工作。

參考資源

本壓縮文件包含本文章涉及的所有源代碼和一個批處理文件:
window.zip
Sun 公司對 AWT 本地接口的介紹:
http://java.sun.com/prodUCts/jdk/1.3/AWT_Native_Interface.Html
SUN 公司在 Java 2 SDK,版本 1.3 中所作的增強:
http://java.sun.com/products/jdk/1.3/docs/guide/awt/enhancements.html
Sun 公司對本地繪圖 JAWT 接口的改進,post-Kestrel(只需免費注冊):
http://developer.java.sun.com/developer/bugParade/bugs/4281429.html
"Enhance your Java application with Java Native Interface (JNI)," TalLyron(JavaWorld,1999 年 10 月):
http://www.javaworld.com/javaworld/jw-10-1999/jw-10-jni.html
"Java Tip 23: Write native methods," John D. Mitchell (JavaWorld):
http://www.javaworld.com/javaworld/javatips/jw-javatip23.html

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 日韩黄色av网站 | 国产精品成人av片免费看最爱 | 久久777国产线看观看精品 | 国产精品久久久久久久四虎电影 | 成人男女啪啪免费观看网站四虎 | 亚欧在线免费观看 | 香蕉视频1024 | 免费在线观看午夜视频 | 久久综合精品视频 | 日日噜噜噜噜久久久精品毛片 | 在线观看一二三 | 一区二区久久电影 | 国产深夜福利视频在线播放 | 91精品欧美一区二区三区 | 精品国产一区二区三区四区阿崩 | 国产精品久久久乱弄 | 99欧美精品 | 免费观看欧美一级片 | 日本精品网 | 亚洲精品 在线播放 | 天天草夜夜 | 国产精品亚洲综合一区二区三区 | 国产精品久久久久久影院8一贰佰 | 玖草在线资源 | 亚洲国产超高清a毛毛片 | 久久区二区 | 日韩视频在线观看免费视频 | 在线日韩av电影 | 久久久久久久久久久久久久久久久久 | 久久午夜神器 | 九九热欧美 | 中国av免费在线观看 | 爱视频福利 | 成人在线视频一区 | 深夜福利视频免费观看 | 免费视频xxxx | 国产在线91| 在线免费视频a | 久久大陆 | 精品在线视频播放 | 在线播放黄色片 |