Java Swings/AWT

From Wikibooks, open books for an open world
Jump to: navigation, search

AWT stands for Abstract Windowing Toolkit. Prior to Swing, AWT was used to develop GUI and rich client interface, but AWT had one major problem. AWT was platform dependent, which means a program written in AWT behaves differently in different platforms. Hence it defeats WORA (Write Once, Run Anywhere) purpose which is the key Java philosophy.

Swing on the other hand is purely (100%) written in Java. A swing application developed on one platform behaves the same on any other platform in which Java is installed. Hence today almost all Java programmers prefer Swing over AWT for GUI development.

Java AWT Native Interface is an interface for the Java programming language that enables rendering libraries compiled to native code to draw directly to a Java Abstract Window Toolkit (AWT) object drawing surface.

The Java Native Interface (JNI) enabled developers to add platform-dependent functionality to Java applications. The JNI enables developers to add time-critical operations like mathematical calculations and 3D rendering. Previously, native 3D rendering was a problem because the native code didn't have access to the graphic context. The AWT Native Interface is designed to give developers access to an AWT Canvas for direct drawing by native code. In fact, the Java 3D API extension to the standard Java SE JDK relies heavily on the AWT Native Interface to render 3D objects in Java. The AWT Native Interface is very similar to the JNI, and, the steps are, in fact, the same as those of the JNI.

The AWT Native Interface was added to the Java platform with the Java Platform, Standard Edition J2SE 1.3 ("Kestrel") version.

AWT Native Interface example walk-through[edit]

Create the Java application[edit]

Type in this in a .java file named JavaSideCanvas and compile:

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();
    }
}

The paint() method will be simply invoked when the AWT event dispatching thread repaints the screen.

Create the C++ header file[edit]

Create the C++ header file as usual for JNI.

The header file looks like this now:

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

Implement the C++ native code[edit]

Type this in a file named "NativeSideCanvas.cpp" and compile into a library.

(Microsoft) Don't forget to link this with "jawt.lib" and "gdi32.lib". These libraries are needed because the code draws a rectangle using routines from these libraries.

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);
}

Run the example[edit]

Run the file as usual for JNI.

It's interesting to note that the AWT Native Interface requires the "jawt.dll" (or "jawt.so") to run with the application, so the easiest way to do that is copying the "jawt.dll" (should be in the .../jre/bin file path of the JDK's installation path.)

You should see a window with a rectangle drawn in it.

Congratulations! You have made your first AWT Native Application!

Native painting[edit]

As you can see, you can paint as if it is a native application. In Windows, the JVM will pass a HWND and other window information to your native application so that your application will "know" where to draw. In this example, it uses GDI to draw a Rectangle. The window information your native side need will be in a JAWT_Win32DrawingSurfaceInfo structure (depending on Operating System) which can be retrieved with this line:

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

dsi_win has the information, look in the "jni.h" file for details.