Are you looking for a Java developer?
Do you need custom Java applications or components? Are you building your own Java product and you want to accelerate its development? |
At the beginning of PC era, the screens were monochrome and the applications ran in text mode. Then the color monitors and the user interfaces based on menus and windows showed up. Each programmer wrote his own library. Borland created Turbo Vision. In those days, Microsoft was working at Windows. The programmers had to learn the Windows API. After that MFC and OWL appeared. Today if you want to make a Windows application that looks like those made by Microsoft you must use MFC. If you want to build it easy and quickly, you should use one of the many existing RAD tools. However, if you need a simple interface that anybody can use and the speed of the application is not critical, you should chose Java. In addition, your program will run into a browser and anyone who has access to Internet will be able to use it.
Java's solution named AWT is object oriented and maps a collection of easy-to-use classes on the API of different operating systems. The user who is familiarized with one operating system will be able to distinguish a Java application from a native one (because of the simplicity of the former), but this will not look alien to him.
Sometimes, the same application must look identical no matter the running platform is. In such a situation, you can use a framework that exploits the graphics primitives of AWT (rectangles, lines, text, etc) to create user interface components that are platform independent. One of these frameworks is IFC from Netscape. Another is Sun's Swing, which is a part of JFC. If these solutions aren't good for you, then you can make your own components. You might be forced to do this thing if the components you need are not "standard".
The interface elements of AWT that have a graphics representation derive from java.awt.Component class. Although this class have a few tens of methods, only three of them can modify the look of a component: setFont(), setBackground() and setForeground(). Even more, there is no guaranty that the properties of the graphics object will change in case AWT created this object by calling APIs of the operating system. For example, I succeeded to modify the font of an AWT 1.0 button (java.awt.Button), but I could not change its colors. In such a situation, the only solution is to write your own class. This class must implement the same functions as java.awt.Button does, but it paints itself on screen by using the methods of java.awt.Graphics.
The AltButton class is a subclass of java.awt.Canvas (which derives from java.awt.Component). The methods AltButton inherits indirectly from Component will handle the fonts and the colors. Hence, the member variables, which describe the state of an AltButton, are simply label and pressed.
The minimumSize() and preferredSize() methods return the preferred dimension of a button. The real size of an AltButton's area depends on the type of the LayoutManager used by the Container of the AltButton object.
The paint() method paints the button. Because AWT 1.0 doesn't offer a method for centered drawing of strings, before drawString(), it calls getFontMetrics() method to obtain the font characteristics. Depending on these, it computes the (x,y) coordinates at which it prints the button label. Then it draws a rectangle that indicates the button's state (pressed or not). For this purpose, it uses the draw3DRect() method.
The mouseXXX() methods are called by handleEvent() (inherited from java.awt.Component), depending on the events generated by the user with the mouse. When a button is pushed, mouseDown() method is called and when the button is released mouseUp() method is called. This latter one calls fireActionEvent(), which fires an ACTION_EVENT, with the help of postEvent(). The postEvent() is inherited from java.awt.Component and calls handleEvent(). If this method returns false, the event is posted to button's parent. In this way, the event may traverse the entire hierarchy of containers on whose bottom the button is.
Probably, you are wondering why I need to color the buttons. The AltCheckbox class, which is an AltButton subclass, needs this because it offers a new type of checkbox buttons. The state of such a checkbox is indicated to the user by its color. If the button wasn't selected, it uses its parent's colors (the parent of the button is a container). Otherwise, it uses the colors that are stored in selBackColor and selForeColor public class variables. The state of a button is given by the state member variable and the affiliation to a group is given by the group variable.
The AltCheckbox methods have the same names and functionality as the java.awt.Checkbox methods have.
The setState() method sets the button's state and changes its color to indicate to the user the current state.
The setCheckboxGroup() method changes the button's group. It takes into account that only one button of the group may be selected at a given time.
The action() method will intercept the ACTION_EVENT events fired when the button is pushed. If the button isn't member of a group then its state is inverted. Otherwise, it becomes the current button of its group. The false value returned from the function makes the event to be transmitted up to the component containment hierarchy. Therefore, it can be caught by the button's container, eventually by the container's container, and so on.
The AltCheckboxGroup class does the same thing as java.awt.CheckboxGroup does - it groups a few checkbox buttons and it takes care that only one of them to be selected at a given moment. It has only one member variable named currentChoice, in which it keeps a reference to the current AltCheckbox object of the group.
It isn't necessary to create a list that contains all the buttons of the group.
The setCurrent() method sets the current checkbox of the group.
The Test class is an applet that uses GridLayout manager to group five Panels that use GridLayout manager too. Each of these contains three or two buttons. The buttons from east are AltButton instances. The rest of them are AltCheckbox objects. The buttons from north and those from south are grouped with the help of two objects whose type is AltCheckboxGroup.
The action() method of the applet handle some of the events fired when the buttons are activated. In case of those from east, the state of the western buttons is changed, and in case of those from south, the northern group is synchronized with that from south.
The sources presented in this article are based on Java 1.0. I used this version because there are many users whose browsers and development tools were released before Java 1.1. Nevertheless, the classes can be converted easily to the later Java version.
First, you must convert the calls and the overrides of the deprecated methods. For example the getSize() method must be called instead of size(). The minimumSize() and preferredSize() methods that AltButton overrides are in the same situation. Their new names are getMinimumSize() and getPreferredSize(). They are called by LayoutManagers.
Then, the real conversion to AWT 1.1 is following. This is a more difficult task than former because AWT 1.1 replaces the old model for event processing with a new one, which improves both the performance and the architecture of the applications.
The new delegation-based event model permits the separation between the application lofic and the GUI code. The action() method from Test applet must be eliminated. You will use instead of it classes named Listeners, whose instances will be registered to components that fire events (Sources).
The next article shows how to do the conversion and it explains the advantages.
API - Application Program Interface
AWT - Abstract Window Toolkit (Java + native code, Sun)
GUI - Graphical User Interface
IFC - Internet Foundation Classes (Java, Netscape)
JFC - Java Foundation Classes (Java, Sun)
MFC - Microsoft Foundation Classes (C++, Microsoft)
OWL - Object Windows Library (C++, Borland)
RAD - Rapid Application Development
The AWT Home Page
http://java.sun.com/products/jdk/awt/index.html
JDK1.1 - AWT Enhancements
http://java.sun.com/products/jdk/1.1/docs/guide/awt/designspec/index.html
How to Convert Programs to the 1.1 AWT API
http://java.sun.com/products/jdk/1.1/docs/guide/awt/HowToUpgrade.html
// AltButton.java import java.awt.Color; import java.awt.Dimension; import java.awt.Event; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; public class AltButton extends java.awt.Canvas { private String label; protected boolean pressed; public AltButton() { this(""); } public AltButton(String label) { setLabel(label); pressed = false; } public String getLabel() { return label; } public void setLabel(String label) { this.label = label; repaint(); } public Dimension minimumSize() { FontMetrics m = getFontMetrics(getFont()); int w = 6 * m.charWidth('X'); if (label != null) w += m.stringWidth(label); int h = (int) (m.getHeight() * 1.6); return new Dimension(w, h); } public Dimension preferredSize() { return minimumSize(); } public void paint(Graphics g) { Dimension sz = size(); FontMetrics m = g.getFontMetrics(); int w = m.stringWidth(label); int h = m.getHeight(); int x = (sz.width - w) / 2; int y = (sz.height - h) / 2; y += m.getLeading() + m.getAscent(); if (label != null) g.drawString(label, x, y); g.setColor(Color.white); g.draw3DRect(1, 1, sz.width-3, sz.height-3, !pressed); g.draw3DRect(0, 0, sz.width-1, sz.height-1, !pressed); } public boolean mouseEnter(Event evt, int x, int y) { return true; } public boolean mouseExit(Event evt, int x, int y) { if (pressed) { pressed = false; repaint(); } return true; } public boolean mouseDown(Event evt, int x, int y) { pressed = true; repaint(); return true; } public boolean mouseUp(Event evt, int x, int y) { if (!pressed) return false; pressed = false; repaint(); fireActionEvent(); return true; } public void fireActionEvent() { postEvent(new Event(this, Event.ACTION_EVENT, label)); } }
// AltCheckbox.java import java.awt.Color; import java.awt.Container; import java.awt.Event; import java.awt.Graphics; public class AltCheckbox extends AltButton { static public Color selBackColor = Color.red; static public Color selForeColor = Color.white; private boolean state; private AltCheckboxGroup group; public AltCheckbox() { this("", null, false); } public AltCheckbox(String label) { this(label, null, false); } public AltCheckbox(String label, AltCheckboxGroup group, boolean state) { super(label); setState(state); setCheckboxGroup(group); } public boolean getState() { return state; } public void setState(boolean state) { if (state == this.state) return; this.state = state; if (state && group != null) group.setCurrent(this); if (state) { setBackground(selBackColor); setForeground(selForeColor); } else { Container p = getParent(); if (p != null) { setBackground(p.getBackground()); setForeground(p.getForeground()); } else { setBackground(null); setForeground(null); } } repaint(); } public AltCheckboxGroup getCheckboxGroup() { return group; } public void setCheckboxGroup(AltCheckboxGroup group) { if (this.group == group) return; if (this.group != null) this.group.setCurrent(null); this.group = group; if (state && group != null) group.setCurrent(this); } public boolean action(Event evt, Object what) { if (group == null) setState(!state); else group.setCurrent(this); return false; } }
// AltCheckBoxGroup.java public class AltCheckboxGroup { AltCheckbox currentChoice = null; public AltCheckboxGroup() { } public AltCheckbox getCurrent() { return currentChoice; } public synchronized void setCurrent(AltCheckbox newChoice) { if (newChoice != null && newChoice.getCheckboxGroup() != this) return; AltCheckbox oldChoice = this.currentChoice; if (oldChoice == newChoice) return; this.currentChoice = newChoice; if (oldChoice != null) oldChoice.setState(false); if (newChoice != null) newChoice.setState(true); } }
// Test.java import java.awt.Color; import java.awt.Event; import java.awt.Font; import java.awt.GridLayout; import java.awt.Panel; public class Test extends java.applet.Applet { AltCheckboxGroup n, s; AltCheckbox n1, n2, n3; AltCheckbox s1, s2, s3; AltCheckbox w1, w2, w3; AltButton e1, e2, e3; public void init() { setBackground(Color.lightGray); setForeground(Color.black); setFont(new Font(getFont().getName(), Font.PLAIN, 14)); setLayout(new GridLayout(5,1)); Panel p; p = new Panel(); p.setLayout(new GridLayout(1, 3)); n = new AltCheckboxGroup(); n1 = new AltCheckbox("Radio 1", n, false); p.add(n1); n2 = new AltCheckbox("Radio 2", n, false); p.add(n2); n3 = new AltCheckbox("Radio 3", n, false); p.add(n3); n.setCurrent(n2); add(p); p = new Panel(); p.setLayout(new GridLayout(1, 2)); w1 = new AltCheckbox("Check 1", null, true); p.add(w1); e1 = new AltButton("Button 1"); p.add(e1); add(p); p = new Panel(); p.setLayout(new GridLayout(1, 2)); w2 = new AltCheckbox("Check 2", null, false); p.add(w2); e2 = new AltButton("Button 2"); p.add(e2); add(p); p = new Panel(); p.setLayout(new GridLayout(1, 2)); w3 = new AltCheckbox("Check 3", null, true); p.add(w3); e3 = new AltButton("Button 3"); p.add(e3); add(p); p = new Panel(); p.setLayout(new GridLayout(1, 3)); s = new AltCheckboxGroup(); s1 = new AltCheckbox("First", s, false); p.add(s1); s2 = new AltCheckbox("Second", s, false); p.add(s2); s3 = new AltCheckbox("Third", s, false); p.add(s3); s.setCurrent(s2); add(p); } public boolean action(Event evt, Object what) { if (evt.target == e1) w1.setState(!w1.getState()); else if (evt.target == e2) w2.setState(!w2.getState()); else if (evt.target == e3) w3.setState(!w3.getState()); else if (evt.target == s1) n.setCurrent(n1); else if (evt.target == s2) n.setCurrent(n2); else if (evt.target == s3) n.setCurrent(n3); else return false; return true; } }
Back to Inside AWT
Back to Java Developer's Page
This page hosted by Get your
own Free Homepage