跳转到内容

Java Swing/AWT

100% developed
来自维基教科书,开放的书本,开放的世界

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 平台的。

AWT 原生接口示例演练

[编辑 | 编辑源代码]

创建 Java 应用程序

[编辑 | 编辑源代码]

在名为 JavaSideCanvas 的 .java 文件中输入以下内容并编译

Computer code 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() 方法将被简单地调用。

创建 C++ 头文件

[编辑 | 编辑源代码]

像往常一样为 JNI 创建 C++ 头文件。

头文件现在看起来像这样

Computer code 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

实现 C++ 原生代码

[编辑 | 编辑源代码]

在名为 "NativeSideCanvas.cpp" 的文件中输入以下内容,并编译成库。

(微软) 不要忘记将它与 "jawt.lib" 和 "gdi32.lib" 连接起来。这些库是必需的,因为代码使用这些库中的例程绘制矩形。

Microsoft C++

Computer code 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 结构中(取决于操作系统),可以使用以下代码行检索它

Example JAWT_Win32DrawingSurfaceInfo 结构
dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;

dsi_win 包含信息,请查看 "jni.h" 文件以获取详细信息。


华夏公益教科书