跳轉到內容

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" 檔案以獲取詳細資訊。


華夏公益教科書