I ran across a floppy disk (remember those?) a short while back that had some of my old assembly language code. Thought it'd be fun to convert some of those old programs to Java. Started with the easiest one, my "Hello World" of the graphics world. Basic idea is that it does a Sierpinski gasket by randomly hopping about. A no-brainer to code, so it lets one get familiar with the graphics environment. Here's the core of the original assembly code (leaving out the random number library code and the stack frame):
.public main
.proc main auto
mov ax,0012h
int 10h
call rand_init
mov cx,319
mov dx,239
again: mov bx,3
call randr_w
cmp ax,1
jb zero
je one
add cx,639
shr cx,1
add dx,479
shr dx,1
mov al,4
jmp continue
zero: add cx,319
shr cx,1
shr dx,1
mov al,1
jmp continue
one: shr cx,1
add dx,479
shr dx,1
mov al,2
continue: mov ah,0ch
int 10h
mov ah,01h
int 16h
jz again
mov ax,0003h
int 10h
xor ah,ah
int 16h
ret ;exit to DOS with ERRORLEVEL=0
.endp main
So, I grab my various Java books and start banging out some quick code. I rapidly end up with the following (after following the suggestions/guidelines in the various books):
package chaos;
import java.awt.*;
import java.awt.event.*;
public class Main extends Frame {
public Main() {
addWindowListener(new MyWindowAdapter());
}
@Override
public void paint(Graphics g) {
Dimension d=this.getSize();
int x=(d.width-1)/2;
int y=(d.height-1)/2;
int minx=this.getInsets().left;
int maxx=d.width-this.getInsets().right-1;
int miny=this.getInsets().top;
int maxy=d.height-this.getInsets().bottom-1;
g.setColor(new Color(0,0,0));
g.fillRect(minx,miny,maxx,maxy);
for (int count=0; count <=500000; count++) {
switch((int) Math.floor(Math.random()*3)) {
case 0:
x=(x+((d.width-1)/2))/2;
y=(y+miny)/2;
g.setColor(new Color(255,0,0));
break;
case 1:
x=(x+maxx)/2;
y=(y+maxy)/2;
g.setColor(new Color(0,255,0));
break;
case 2:
x=(x+minx)/2;
y=(y+maxy)/2;
g.setColor(new Color(0,0,255));
break;
}
g.drawLine(x,y,x,y);
}
}
public static void main(String[] args) {
Main output = new Main();
output.setSize(new Dimension(800, 600));
output.setResizable(false);
output.setTitle("Chaos");
output.setVisible(true);
}
}
class MyWindowAdapter extends WindowAdapter {
@Override
public void windowClosing(WindowEvent we) {
System.exit(0);
}
}
So far, so good. Is reasonably simple (although I'm somewhat dismayed by the number of lines of code compared to assembly and annoyed by having to calculate insets to avoid painting UNDER the window borders and title bar). Runs great. EXCEPT, it doesn't redraw properly on window resizes (unless you cover up the window or do a minimize/maximize sequence)! Despite the paint code being run again, the actual screen updates for the portion that was already visible never happen! It appears that the JVM is optimizing them away, despite them being in the paint code. Many attempts to avoid that behaviour (in all kinds of different ways) fail. I finally give up, disallow resizing in that code (to just avoid the situation) and ask a Java guru at work. He did some research and tweaked my code to look like this:
import java.awt.*;
import java.awt.event.*;
public class Chaos {
public static void main( String[] args ) {
Frame f = new Frame("Chaos");
f.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
f.add(new ChaosCanvas());
f.pack();
f.setVisible(true);
f.setSize( new Dimension(800, 600) );
}
}
class ChaosCanvas extends Canvas {
public void paint(Graphics g) {
Dimension d=this.getSize();
int x=(d.width-1)/2;
int y=(d.height-1)/2;
int minx=0;
int maxx=d.width;
int miny=0;
int maxy=d.height;
g.setColor(new Color(0,0,0));
g.fillRect(minx,miny,maxx,maxy);
for (int count=0; count <=500000; count++) {
switch((int) Math.floor(Math.random()*3)) {
case 0:
x=(x+((d.width-1)/2))/2;
y=(y+miny)/2;
g.setColor(new Color(255,0,0));
break;
case 1:
x=(x+maxx)/2;
y=(y+maxy)/2;
g.setColor(new Color(0,255,0));
break;
case 2:
x=(x+minx)/2;
y=(y+maxy)/2;
g.setColor(new Color(0,0,255));
break;
}
g.drawLine(x,y,x,y);
}
}
}
Now it also works properly on resizes! Not only that, but the whole insets problem goes away too! The major difference being that he paints into a Canvas that's packed into the Frame, NOT directly into the Frame. In hindsight it sounds VERY obvious, however, all those books that I have that talk about graphics have you painting directly into a Frame. Not a single one of them on my shelf even mentions the Canvas object! Thank you David, and hopefully this helps out someone else that's using one of those millions of Java books that only talks about doing graphics inside empty Frames!
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5