By Peter
Seaman
December
2007
Peter.Seaman.Java@Stable-Software.co.uk
I have been
a programmer most of my working life and this has been, and still is to some
extent, my hobby too. The last few noddy
programs I have written have been in VB, or a mixture of VB and C. when there
were significant run-time processing considerations. These programs have been easy and quick to
write but often cause problems to users.
Since the VB runtimes are not common and pervasive, one has to ship an
extensive “superstructure” with the application and either provide detailed
installation instructions or an installation program. The superstructure is usually much larger
than the application itself, sometimes by a factor of 10 in VB3 or even 100 in
VB5. This all takes time to download and
occupies space on all user machines.
There is no commonly known standard way for a user to obtain the VB
superstructure separately from a common source, so it is included shipped with
every VB application, and sits on the user machines in a separate directory for
each application. This is all very
inefficient and time consuming. Not
only that, but there are often compatibility problems which can cause both
users and suppliers much frustration.
So I
thought I would bring myself more up to date by learning a bit of Java, which
does not have the above VB disadvantages.
My first exercise was to convert my most recent program, nCyclists from
VB to Java. This report is about that
conversion, which I summarise in the following table.
|
|
VB |
Java |
Comments |
|
Size of
source files in bytes |
16,176 |
43,049 |
Java
names tend to be longer than the VB names. |
|
Lines of
code (excluding that auto-generated by form designer of the IDE) |
532 |
542 |
There are
73 Dim statements in the VB which are each counted as a line of code. In Java declarations are usually coded with
first usage and are not counted separately. |
|
Number of
functions / methods |
36 |
40 |
|
|
Number
of “words” in the source |
1,791 |
1,542 |
VB
included many words like “end” and “sub” whereas in java these are symbols
and not counted as words |
|
Number of
different words in the source |
220 |
314 |
This
measure alone indicates why Java is more difficult. |
|
Executable
size (bytes) |
17,405 |
36,077 |
The VB
figure is the size of the exe, the Java figure is the total size of the
uncompressed application class files. |
|
Programming
effort (days) |
3 |
10 |
See below |
|
|
|
|
|
The java
programming effort was significantly greater than VB partly because of the more
complex language, but more because the Java figure included my significant
learning time, in particular the time it took to resolve a number of problems
by experimentation, documentation study, and use of Sun’s “New to Java” forum. On the other hand, much of the basic logic
was invented for the VB app and included in the VB development time, but
largely merely copied for the Java app.
A few
examples illustrate the relative complexity of my Java code compared to VB. My present view is that however familiar I
become with Java in the future it will usually take more effort to create a Java
app of this type than the equivalent VB, except where there are requirements
that can be met by pre-existing Java classes where no VB equivalent exists.
But I will
persevere with Java as I do see that it its many advantages outweigh its
disadvantages.
|
|
VB |
Java |
|
Setting a
font size at run time |
Following
applies whether or not the panel has a user scale set: panel.fontSize = 12 |
Following
assumes the panel has not been scaled (transformed). If it has been scaled the source is rather
more complicated. Graphics2d g2d = (Graphics2d) panel.getGraphics(); g2d.setFont(g2d.getFont().deriveFont(12)); |
|
Setting a
line width |
panel.DrawWidth = 4 |
Graphics2d g2d = (Graphics2d) panel.getGraphics(); g2d.setStroke(new BasicStroke(4f)); (Same
proviso regarding scaling - “the width of a rendered shape's outline
is determined not only by the width attribute of this |
|
Formatting
a time of day measured as seconds since midnight. |
Format(seconds/(24*3600), “hh:mm”) |
Using java
supplied date/time classes: Calendar
c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone(“Universal”)); // If this is not done the result is one
hour out as a consequence of the British Government decision to have summer
time in the winter of 1970 c.setTimeInMillis(seconds
* 1000); String.format(“%tc”,
c); But
simpler to do it manually: String.format(“%02d:%02d”,
seconds/3600, (seconds % 3600) / 60); |
|
Setting a
scale for a panel to longitude and latitude values in degrees |
Panel.ScaleLeft = leftLongitude Panel.ScaleWidth = longitudeRange Panel.ScaleTop = lowLatitude + latitudeRange Panel.scaleHeight = -latitudeRange |
Don’t
ask! (See later) |
|
Bringing
a control in front |
Use IDE
menu option |
Unable to
find out how to do it |
|
Putting a
control on a panel |
Straightforward |
Had to
set null layout for the panel otherwise the layout manager took control and
the setLocation method had no effect.
Even after that I encountered problems with mysterious rectangles
appearing. This is a problem I have
not solved. |
|
Using an
array of controls |
Create
second & subsequent controls of same name – the VB IDE automatically
passes the array index to methods |
Unsupported
by the Java IDE – see bypass described below |
|
Constant |
Const NCYCLISTS=3 |
public static final int NCYCISTS=3; |
|
Test for
valid floating point number |
isNumeric(string) |
Float.parseFloat(string) in a try-catch block |
|
|
|
|
|
|
|
|
My program
involves arrays of controls for the 3 cyclists.
There are 3 textboxes that specifies average speeds, 3 labels to show
computed mileages, and 3 labels to show estimated times of arrival. There are also 3 combo boxes where the user
can enter the start locations. For
programming simplicity I needed to represent these controls in arrays,
especially as one day I might extend the user interface to 4, 5 or more
cyclists. In VB this is very simple to
do - you just create a new control with the same name as an existing one and
you are then prompted as to whether you require an array. There is one event function for each event
type and each array (not each element of each array) and the event function is
passed the relevant index.
I could
find no way to generate control arrays with the Java IDE form designer. I eventually got round the problem by
declaring arrays for the controls in code, then initialising the arrays from
the individual objects created by the IDE.
For each event for each individual control I inserted a call to an event
handler passing to the handler as an additional argument the index of the
control. Coding these additional
statements in this way then enabled the event handling code to be much the same
as in VB.
My program
involves adding an elapsed time in seconds to a time of day and formatting the
result as a time of day. It is not
concerned with dates or times crossing midnight.
Dates/Times in VB
VB
represents a date/time as a floating point number of days since 30th
December 1899, for example, at the time of writing, the VB “Now” function returns 39418.7656481482, or 02-Dec-2007
18:21:42 PM when formatted. A date/time
can be formatted in many ways by use of the format function, and my program
uses the simple form
format(x, “hh:mm”)
where x is held as a fraction of a
day. The fact that the date held in x
is not today is not relevant.
Dates/Times in Java
My first
attempt to represent n seconds since midnight as a time was
SimpleDateFormat hhmm = new SimpleDateFormat(“HH:mm”);
lblETA.setText(hhmm.format(n
* 1000)); // Argument is in
milleseconds
Unfortunately
this added 1 hour, so I experimented and found that time 0 was 01:00:00 on Jan
1st 1970, not as 00:00:00 on 1970 as I expected and as the
documentation indicated. For example:
Calendar
c = Calendar.getInstance();
c.setTimeInMillis(0);
String.format(“%tc”,
c);
//
result was Thu Jan 01 01:00:00 GMT 1970
There is no
shortage of functions in java for storing, computing and formatting dates and
times - the Calendar class, for example, provides 45 methods, but it was not
clear to me how to format a time of day as hh:mm. Eventually a contributor to the “New to java”
forum suggested this method
static final SimpleDateFormat
formatter
= new SimpleDateFormat("HH:mm");
static
{
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
static String format(int seconds)
{
return
formatter.format(new Date(1000L * seconds));
}
It turns
out that, though the problem is still not resolved entirely to my satisfaction,
a contributory factor to the problem was a peculiar decree by the British
Government in 1970 to use summer time ( i.e. GMT + 1 hour) in the winter of
1969/70. I eventually decided to not use
any Java date/time objects or methods, and coded the conversion both ways
manually.
“Java 2D objects exist on a plane called user coordinate space, or just user space. When objects are rendered on a screen or a printer, user space coordinates are transformed to device space coordinates”
I was pleased to learn of this characteristic of the Java Graphics2d class as this was exactly what my application needed: I did not want to have to think in terms of pixels or twips. Ignoring aspect ratio considerations for now, I wanted to set the horizontal user co-ordinate space to floating point longitude degrees (i.e. -6 to +4 degrees longitude, left to right, and the vertical user space to latitude degrees (49 at the bottom of the panel to 57 degrees at the top). In VB this was easily achieved by
Pic1.ScaleLeft = -6
Pic1.ScaleWidth = 10
Pic1.ScaleTop = 57
Pic1.ScaleHeight = -8
This permitted all drawing co-ordinates (and also control placement) to be done using longitude / latitude degree data and gave rise to no problems at all.
It turned out that this was not easy in Java, and as time progressed more and more complexities arose until I eventually reverted to untransformed pixel co-ordinate space.
My first problem was to specify the correct parameters for the Java Affine transform matrix. This was what I did:
Another, giving the same effect as the above, was suggested by Darryl Burke:
double left =
panel.getX();
double width
= panel.getWidth();
double x0 =
100.0; // or whatever
double x1 =
200.0; // or whatever
AffineTransform
at = AffineTransform.getScaleInstance (width / (x1 - x0), 1);
at.concatenate(AffineTransform.getTranslateInstance
(-x0, 0.0));
Graphics2D g2
= (Graphics2D) panel.getGraphics ();
g2.setTransform
(at);
But this made my
lines and text become about 200 times the expected size, so there clearly were other
things to do. Whereas in VB setting a
user scale did not affect line width and text size, in Java it does. In fact, in my units, a font size of 10 no
longer meant 1 point, it now meant 10 degrees.
OK, by writing more code one could get round this, but the text was
still drawn upside down. I eventually
dropped use of AffineTransform class and coded the drawing primitives using
returns from methods lon2x and lat2y.
In VB a
shape is an object that only carries co-ordinates relative to itself. I found this more convenient to use that the
Java Shape class, which carries absolute co-ordinates. I failed to work out a simple method to draw
a given a shape at any position on a panel.
I welcome
comments on any of the above, especially where I have made wrong assumptions or
errors.
For me, VB
is simple, java is still complicated.
Even so, the Java advantages of efficiency, portability and especially ease
of deployment over the web outweigh the disadvantages I have unearthed so far
so I intend now to drop VB and do all future work in Java. I suspect it will also be much easier in the
future to create libraries of common functions for use across projects.
I should
also mention the fundamental object-oriented nature of Java which has become
very fashionable nowadays, but for my little app it seems to me this aspect was
not particularly relevant – in both the VB
and Java versions the function/methods were small and similar and
directly related to real-world requirements. Anyone who disagrees is welcome to
take my source code and prove me wrong.
Peter
Seaman
December
2007
Peter.Seaman.Java@Stable-Software.co.uk
Java
Application: www.Stable-Software.co.uk/nCyclists
Comments on
this report can be found in Sun’s “New to Java” forum where I append under the
name rps774:
http://forum.java.sun.com/forum.jspa?forumID=54&start=15