当前页面: 开发资料首页 → Eclipse 英文资料 → A small cup of SWT
摘要: Are you interested in developing applications for the Microsoft® Pocket PC? Are you a desktop developer curious about embedded user interfaces? A well-built embedded application is both user and resource friendly. User expectations are high. Resources are very limited... By Christophe Cornu, IBM OTI Labs
In the first part of the article, we will list some common UI guidelines that are followed by native Pocket PC applications. We will show how they map to the SWT API. In the second part, we will look at ways to reduce the size of SWT applications. In the last part, we will examine how application startup time can be improved by writing an SWT application using the Connected Limited Device Configuration (CLDC) Java™ profile.
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class FileDialogMain {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Main");
Menu menu = new Menu(shell, SWT.BAR);
shell.setMenuBar(menu);
shell.open();
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
String name = dialog.open();
if (name != null) shell.setText(name);
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Use to create
your application window. Two other styles are commonly used by Pocket
PC applications. If your application is dialog-based, as in Figure 3,
you
would invoke the constructor Shell(display, SWT.CLOSE)
.
The style SWT.RESIZE
creates a Shell that is
automatically resized when the virtual keyboard of the Pocket PC is
used (Figure 4). No other Shell style is relevant to the Pocket PC.
Note about Pocket PC 2002
The Shell created in contains a smart minimize
button on Pocket PC 2002 (see Figure 2 - upper-right corner). The user
can tap on the smart minimize button to hide (but not close) the
current application and to return to the last application used. The
application can then be restored through the system task list - a
utility for managing applications currently running. To see the smart
minimize button in Figure 2, run the previous example and click Cancel
to close the File dialog.
Figure 2 - Smart minimize on Pocket PC
2002
Shell.setText
specifies
the text displayed in the navigation bar at the top of the screen
(Figure 1). This text is also displayed in the system task list.
There is one last important step to accomplish before we get a nice-looking
Pocket PC application.... We need to create a menu bar and
attach it to the Shell.
The menu bar is a gray rectangular area at the very bottom of the
screen (Figure 1). Any Pocket PC application must set a menu bar on the
top-level Shell.
PDA users don't explicitly terminate an application prior
to switching to a new one. Consequently, the menu bar never contains a
Close menu item. This differs from desktop applications, which often
define a File menu with a Close menu item.
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class OkButton {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display, SWT.CLOSE);
shell.setText("Main");
Menu menu = new Menu(shell, SWT.BAR);
shell.setMenuBar(menu);
shell.addListener(SWT.Close, new Listener() {
public void handleEvent(Event e) {
System.out.println("Ok button tapped");
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
The shell style SWT.CLOSE
creates
a dialog with a small OK button. The application registers the SWT.Close
event that is notified
when the OK button is selected. The shell can then process user data before closing.
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
public class SipResize {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display, SWT.RESIZE);
shell.setLayout(new FillLayout());
shell.setText("Main");
Menu mb = new Menu(shell, SWT.BAR);
shell.setMenuBar(mb);
Text text = new Text(shell, SWT.MULTI | SWT.V_SCROLL);
String buffer = "";
for (int i = 0; i < 100; i++) {
buffer += "This is line " + i + "\r\n";
}
text.setText(buffer);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
The style SWT.RESIZE
creates a full-screen shell that is
resized automatically when the user shows or hides the input panel.
The shell fills the space left between the navigation menu bar at the
top
and the input panel or the menu bar at the bottom (Figure 5). The
sample adds widgets to make the
transition more visual.
A native Pocket PC
application is expected to be "friendly" with the input panel. That
implies:
SWT.RESIZE
,
as shown in the sample above.
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class StylusHold {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Main");
Menu mb = new Menu(shell, SWT.BAR);
shell.setMenuBar(mb);
Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem item = new MenuItem(menu, SWT.CASCADE);
item.setText("item 1");
MenuItem item2 = new MenuItem(menu, SWT.CASCADE);
item2.setText("item 2");
shell.setMenu(menu);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
The pop-up menu uses the same SWT.POP_UP
style as on the desktop platform.
The event SWT.MenuDetect
can be registered to detect the
hold gesture
on a Shell. The events SWT.MOUSE_UP
, SWT.MOUSE_DOWN
and SWT.MOUSE_MOVE
map to the corresponding stylus
actions on the Pocket PC.
org.eclipse.swt.widgets.Tree
can be removed if the
SWT
application is not using the tree widget. SWT is mostly implemented in
Java. A tool - an obfuscator for example - can be used to exclude
unused SWT classes.#ifndef
OS_METHODNAME
. Special tools can determine which SWT native
methods
are not referenced through all possible execution paths of a
particular SWT application. This information is used to build a header
file with a list of native methods to exclude. A sample header file
defines.h is available in the org.eclipse.swt project under the
folder "Eclipse SWT PI"/win32/library.
import org.eclipse.swt.widgets.*;
public class MyApp {
static {
connectDataBase();
}
public static void main(String argv[]) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("MyApp");
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
closeDataBase();
display.dispose();
}
static void connectDataBase() {
try {
Thread.sleep(5000);
} catch (Exception e) {}
}
static void closeDataBase() {
try {
Thread.sleep(5000);
} catch (Exception e) {}
}
}
The application MyApp
becomes visible on the Pocket PC
when the Java
virtual machine has opened the shell. At this moment, a full-size window is
opened. The title is visible in the navigation bar. The title
also appears in the Pocket PC task list. is the first step providing visual
feedback to the user. This application will be invisible for at least five
seconds, time for the connection to the
database to be realized.
The
while loop encloses the SWT event loop. No user interaction occurs
until
the Java virtual machine (JVM) enters the event loop. No paint callback is
processed and native widgets dont draw until this happens. In summary,
the user does not see the application prior to opening the shell
.
The
application is not usable prior to running the event loop.
connectDataBase()
should be
executed after the
Shell
is opened and after the event loop is entered. One
solution is to
bring up a screen with a message asking the user to tap on a button to
start the connection. The selection callback for the button is used to
call connectDataBase()
. The startup time is not impacted
by
lengthy initialization user code anymore.
import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class MyApp {
public static void main(String argv[]) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("MyApp");
shell.setLayout(new FillLayout());
final Button button = new Button(shell, SWT.PUSH);
button.setText("Connect");
button.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event e) {
button.setText("Connecting");
connectDataBase();
button.setText("Connected");
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
closeDataBase();
display.dispose();
}
static void connectDataBase() {
try {
Thread.sleep(5000);
} catch (Exception e) {}}
static void closeDataBase() {
try {
Thread.sleep(5000);
} catch (Exception e) {}
}
}
The
lengthy call to the connectDataBase()
method has moved
from the class
constructor to an event callback. This event callback is executed after
the
event
loop is entered. This refactoring improves the startup time of the
application. This implementation is still very naive. It
illustrates the need to avoid lengthy initialization code before
running the event loop. A better solution may use a progress meter and
a
separate thread.
Diagnose if an application runs too much initialization code
Follow these two easy steps to evaluate
application initialization time.
1. Add a line at the beginning of the Main class (If Main extends
one of your classes, instrument this super class instead. This
superclass is loaded first).
static long start = System.currentTimeMillis(); 2. Add the following lines before entering the SWT event loop:
long end = System.currentTimeMillis();
System.out.println("User init time: " + (end - start));
Then check the list of application classes loaded on startup by the
JVM, as indicated below.
Start the application with the Java console (e.g., java.exe instead of
javaw.exe). Use the VM argument -verbose
. Most JVMs
output the list
of Java classes as they get loaded. This can yield useful results
and direct the effort for refactoring.
If overall startup time remains too high, a lighter Java profile needs
to be considered as discussed below.
java.lang.Object
.
The actual number of core Java classes depends on which Java profile
the application runs against.
The SWT Pocket PC port can be run against the familiar J2SE profile and
the J2ME CLDC one.
-verbose
to the Java console.
For the second run, the VM was executed without any -verbose
flag
and without console. The time was measured from the moment the
application shortcut is tapped in the Pocket PC Windows Explorer and
the moment the HelloWorld application comes up.-jcl:cldc:loadlibrary=swt-win32-3002
Total number of classes loaded: 87 (see
detailed list)
Number of core classes loaded prior to reaching the Main class: 48
Startup time: about 1.9 seconds
Figure 10 -
Number of classes loaded (J2SE versus CLDC)
The number of core classes loaded prior to reaching the Main class
in the J2ME CLDC profile is about one fourth of the number the JVM needs to
load for the same program when using the J2SE profile. The startup
time is roughly cut in half in this example. Application classes
represent the Main class of the user
application and all classes subsequently loaded. SWT classes are
included in this category. The number of application classes does not
really vary with the Java profile in this example.
The J2ME CLDC profile is a good choice for people developing embedded
applications. It is possible to write an application that runs on
either J2SE or J2ME CLDC profiles by following some simple rules.
Profile-specific calls can be constrained to a particular
class. This profile class encapsulates the required refactoring when
porting a J2SE application to CLDC. For example, a stream opened using
java.io.FileOutputStream in the J2SE profile could be implemented with
the CLDC Connector.open API.
Further startup time improvement may require using special deployment
features specific to certain VMs and platforms. For example, the IBM J9
VM
can load classes under an optimized format called JXE. This format
reduces the work required by the classloader at runtime.
In summary, application startup time is dependent on two factors.
SWT
FAQ - What do I need to do to run SWT on the PocketPC?
SWT
FAQ - Where is the SWT library for the PocketPC?
IBM is a registered trademark of International Business Machines Corporation in the United States, other countries, or both.
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.
Microsoft and Windows are registered trademarks of Microsoft Corporation in the United States, other countries, or both.
Other company, product, and service names may be trademarks or service marks of others.