Java Swing/AWT
AWT 代表抽象窗口工具包。在 Swing 出现之前,AWT 被用来开发 GUI 和富客户端界面,但 AWT 有一个主要问题。AWT 是平台相关的,这意味着在不同的平台上,用 AWT 编写的程序会有不同的表现。因此它违背了 **WORA** (Write Once, Run Anywhere) 的目的,而这正是 Java 哲学的关键所在。
另一方面,Swing 纯粹(100%)用 Java 编写。在一个平台上开发的 Swing 应用程序在安装了 Java 的任何其他平台上都能保持相同的效果。因此,今天几乎所有 Java 程序员都更喜欢使用 Swing 而不是 AWT 进行 GUI 开发。
**Java AWT 原生接口** 是 Java 编程语言的一种接口,它使编译成原生代码的渲染库能够直接绘制到 Java 抽象窗口工具包 (AWT) 对象的绘制表面。
Java 原生接口 (JNI) 使开发人员能够为 Java 应用程序添加平台相关的功能。JNI 使开发人员能够添加时间关键操作,如数学计算和 3D 渲染。以前,原生 3D 渲染是一个问题,因为原生代码无法访问图形上下文。AWT 原生接口旨在让开发人员访问 AWT Canvas
,以便原生代码可以直接绘制。事实上,Java SE JDK 中的 Java 3D API 扩展在很大程度上依赖于 AWT 原生接口来渲染 Java 中的 3D 对象。AWT 原生接口与 JNI 非常相似,实际上,它的步骤与 JNI 的步骤相同。
AWT 原生接口是在 Java Platform, Standard Edition J2SE 1.3 ("Kestrel") 版本中添加到 Java 平台的。
在名为 JavaSideCanvas 的 .java 文件中输入以下内容并编译
JavaSideCanvas.java
import java.awt.Canvas;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class JavaSideCanvas extends Canvas {
static {
System.loadLibrary("NativeSideCanvas");
}
public native void paint(Graphics g);
public static void main(String[] args) {
Frame frame = new Frame();
frame.setBounds(0, 0, 500, 500);
JavaSideCanvas jsc = new JavaSideCanvas();
frame.add(jsc);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
System.exit(0);
}
});
frame.show();
}
}
|
当 AWT 事件分派线程 *重新绘制* 屏幕时,paint()
方法将被简单地调用。
像往常一样为 JNI 创建 C++ 头文件。
头文件现在看起来像这样
JavaSideCanvas.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JavaSideCanvas */
#ifndef _Included_JavaSideCanvas
#define _Included_JavaSideCanvas
#ifdef __cplusplus
extern "C" {
#endif
#undef JavaSideCanvas_FOCUS_TRAVERSABLE_UNKNOWN
#define JavaSideCanvas_FOCUS_TRAVERSABLE_UNKNOWN 0L
#undef JavaSideCanvas_FOCUS_TRAVERSABLE_DEFAULT
#define JavaSideCanvas_FOCUS_TRAVERSABLE_DEFAULT 1L
#undef JavaSideCanvas_FOCUS_TRAVERSABLE_SET
#define JavaSideCanvas_FOCUS_TRAVERSABLE_SET 2L
#undef JavaSideCanvas_TOP_ALIGNMENT
#define JavaSideCanvas_TOP_ALIGNMENT 0.0f
#undef JavaSideCanvas_CENTER_ALIGNMENT
#define JavaSideCanvas_CENTER_ALIGNMENT 0.5f
#undef JavaSideCanvas_BOTTOM_ALIGNMENT
#define JavaSideCanvas_BOTTOM_ALIGNMENT 1.0f
#undef JavaSideCanvas_LEFT_ALIGNMENT
#define JavaSideCanvas_LEFT_ALIGNMENT 0.0f
#undef JavaSideCanvas_RIGHT_ALIGNMENT
#define JavaSideCanvas_RIGHT_ALIGNMENT 1.0f
#undef JavaSideCanvas_serialVersionUID
#define JavaSideCanvas_serialVersionUID -7644114512714619750i64
#undef JavaSideCanvas_serialVersionUID
#define JavaSideCanvas_serialVersionUID -2284879212465893870i64
/*
* Class: JavaSideCanvas
* Method: paint
* Signature: (Ljava/awt/Graphics;)V
*/
JNIEXPORT void JNICALL Java_JavaSideCanvas_paint
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif
|
在名为 "NativeSideCanvas.cpp" 的文件中输入以下内容,并编译成库。
(微软) 不要忘记将它与 "jawt.lib" 和 "gdi32.lib" 连接起来。这些库是必需的,因为代码使用这些库中的例程绘制矩形。
Microsoft C++
NativeSideCanvas.cpp
#include "jawt_md.h"
#include <assert.h>
#include "JavaSideCanvas.h"
JNIEXPORT void JNICALL Java_JavaSideCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
{
JAWT awt;
JAWT_DrawingSurface* ds;
JAWT_DrawingSurfaceInfo* dsi;
JAWT_Win32DrawingSurfaceInfo* dsi_win;
jboolean result;
jint lock;
// Get the AWT
awt.version = JAWT_VERSION_1_3;
result = JAWT_GetAWT(env, &awt);
assert(result != JNI_FALSE);
// Get the drawing surface
ds = awt.GetDrawingSurface(env, canvas);
assert(ds != NULL);
// Lock the drawing surface
lock = ds->Lock(ds);
assert((lock & JAWT_LOCK_ERROR) == 0);
// Get the drawing surface info
dsi = ds->GetDrawingSurfaceInfo(ds);
// Get the platform-specific drawing info
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
//////////////////////////////
// !!! DO PAINTING HERE !!! //
//////////////////////////////
//Simple paints a rectangle (GDI32)
//It's a GDI API, Use Windows provided GDI library in order to compile the code.
Rectangle(dsi_win->hdc, 50, 50, 200, 200);
// Free the drawing surface info
ds->FreeDrawingSurfaceInfo(dsi);
// Unlock the drawing surface
ds->Unlock(ds);
// Free the drawing surface
awt.FreeDrawingSurface(ds);
}
|
像往常一样为 JNI 运行文件。
值得注意的是,AWT 原生接口需要 "jawt.dll" (或 "jawt.so") 与应用程序一起运行,因此最简单的方法是复制 "jawt.dll" (它应该位于 JDK 安装路径的 .../jre/bin 文件路径中)。
你应该看到一个窗口,里面画了一个矩形。
恭喜!你已经创建了你的第一个 AWT 原生应用程序!
正如你所见,你可以像原生应用程序一样进行绘制。在 Windows 中,JVM 会将 HWND 和其他窗口信息传递给你的原生应用程序,以便你的应用程序能够 "知道" 在哪里绘制。在本例中,它使用 GDI 绘制一个矩形。你的原生端需要的窗口信息将在 JAWT_Win32DrawingSurfaceInfo
结构中(取决于操作系统),可以使用以下代码行检索它
JAWT_Win32DrawingSurfaceInfo 结构
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
|
dsi_win 包含信息,请查看 "jni.h" 文件以获取详细信息。