This old dog decided to try to teach himself some new tricks

 

By Peter Seaman

December 2007

 

www.Stable-Software.co.uk

 

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.

Summary 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

 

 

 

 

Programming Effort

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.

 

Comparison on of VB code and Java code

 

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 BasicStroke, but also by the transform attribute of the Graphics2D object”

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

 

 

 

 

 

 

 

Some difficulties I encountered with Java

Arrays of controls

 

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.

Dates and Times

 

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.

Scaling a drawing area

 

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:

 

// Transform matrix:
// a 0 c
// 0 e f

// means

// xnew = a*x + c
// ynew = e*y + f

// so by a bit of algebra:

double a = width /(x1-x0);
double c = - a * x0;
double e = height/(y1-y0);
double f = - e * y0;

g2d.transform(new AffineTransform( a, 0, 0, e, c, f));

 

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.

Passing a shape around

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.

 

Conclusion

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

 

www.Stable-Software.co.uk

 

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