Adding Graphics to Your Program

by Welopez

Windows you create with Just Basic are only one of the attractive things you can do. When a program is running, particularly if it will be processing for awhile, graphics can show your user that it hasn't locked up in a "dumb bunny loop." Using a WINDOW for GRAPHICS and GRAPHICBOXes, you can change colors and fonts on the fly, something you can't do when using the MAINWIN.

Most users, new to JB, will use Free Form to create their first GUI. It's quick and easy, and painless too! If you need to make small changes to your GUI after the code has been pasted to your program, check out http://justbasic.conforums.com/index.cgi?board=tutorial&action=display&num=1107313524 to see how really easy it is. With a little practice, you'll be creating GUI's from scratch, and tweaking them as you go.

This demo creates a window for graphics, and includes 3 graphicboxes for the demo, a single statictext to inform the user, and a single textbox to get input from the user. Colors are used throught to create a visual effect.


'Multi Graphicbox/Color Demo1
'by Welo, 2/15/2006

NOMAINWIN

WindowWidth=400
WindowHeight=200
UpperLeftX=INT((DisplayWidth-WindowWidth)/2)
UpperLeftY=INT((DisplayHeight-WindowHeight)/2)
 
GRAPHICBOX #win.gb1, 25, 50, 100, 100
GRAPHICBOX #win.gb2, 150, 50, 100, 100
GRAPHICBOX #win.gb3, 275, 50, 100, 100
TEXTBOX #win.tb1, 275, 10, 30, 25
BUTTON #win.btn1, "Start", [start], UL, 325, 10, 40, 25

OPEN "CountDown Demo" FOR GRAPHICS_nsb AS #win
PRINT #win, "trapclose quit"
PRINT #win.gb1, "FILL 255 200 200"
PRINT #win.gb1, "FLUSH"
PRINT #win.gb2, "FILL 255 255 200"
PRINT #win.gb2, "FLUSH"
PRINT #win.gb2, "BACKCOLOR 255 255 200"
PRINT #win.gb3, "BACKCOLOR green"
PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.gb3, "FLUSH"
PRINT #win, "FILL 245 245 245"
PRINT #win, "BACKCOLOR 245 245 245"
PRINT #win, "COLOR red"
PRINT #win, "PLACE 20, 30"
PRINT #win, "\Time to countdown (1-60)? Press Start."
PRINT #win, "FLUSH"
[reDo]  'Come here if user made an error
PRINT #win.tb1, "!SETFOCUS"
WAIT

[start]
PRINT #win.gb1, "FILL 255 200 200"
PRINT #win.tb1, "!contents? sec"
IF (sec<1) OR (sec>60) THEN
    NOTICE "Error!  Error!  Stupid error!"; CHR$(13);_
        sec; " is not between 1 and 60!"; CHR$(13); CHR$(13);_
        "Please try again!"
        GOTO [reDo]
END IF
PRINT #win.btn1, "!DISABLE"

DO
    PRINT #win.gb3, "FILL green"
    PRINT #win.gb3, "PLACE 20 40"
    PRINT #win.gb3, "\\Running"
    GOSUB [delay]
    PRINT #win.gb2, "FILL 255 255 200"
    PRINT #win.gb2, "PLACE 20 40"
    PRINT #win.gb2, "COLOR 0 0 255"
        sec=sec-1
    PRINT #win.gb2, "\"; sec; " Sec"; "\\to GO!"
LOOP WHILE sec>0

PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.gb1, "FILL red"

PRINT #win.gb2, "FILL 255 255 200"
PRINT #win.gb1, "COLOR white"
PRINT #win.gb1, "BACKCOLOR red"
PRINT #win.gb1, "PLACE 25 50"
PRINT #win.gb1, "\DONE!"
PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.btn1, "!ENABLE"

WAIT
SUB quit handle$
    CLOSE #win
    END
END SUB

[delay]
    TIMER 1000, [more]
    WAIT
    [more]
    TIMER 0
RETURN

You'll notice I put the quit routine in a SUB routine, to avoid that dreaded "Branch label not found" error if the user click the X to close the program while execution is in the [delay] block. Sub routines can see other sub routines when the handle$ is passed to them, as done above.

When printing text to graphicboxes, be sure to specify a BACKCOLOR the same as your FILL color, or your text will be printed over the FILL color, but inside a white box. If your text color is white, it will not be seen.

The graphicboxes provide a visual clue to what is happening while the user is waiting for the countdown, but a similar technique can be used to illustrate the program is still processing information and has not locked up. To provide even more action on the GUI, I modified the code to print graphic representations instead of text.


'Multi Graphicbox/Color Demo2
'by Welo, 2/15/2006

NOMAINWIN

WindowWidth=400
WindowHeight=200
UpperLeftX=INT((DisplayWidth-WindowWidth)/2)
UpperLeftY=INT((DisplayHeight-WindowHeight)/2)

'Place the controls
GRAPHICBOX #win.gb1, 25, 50, 100, 100
GRAPHICBOX #win.gb2, 150, 50, 100, 100
GRAPHICBOX #win.gb3, 275, 50, 100, 100
TEXTBOX #win.tb1, 275, 10, 30, 25
BUTTON #win.btn1, "Start", [start], UL, 325, 10, 40, 25

OPEN "CountDown Demo" FOR GRAPHICS_nsb AS #win
PRINT #win, "trapclose quit"
PRINT #win.gb1, "FILL 255 200 200"  'Paint the graphicbox sickly red
PRINT #win.gb1, "FLUSH"
PRINT #win.gb2, "FILL 255 255 200"  'Paint the graphicbox sickly yellow
PRINT #win.gb2, "FLUSH"
PRINT #win.gb2, "BACKCOLOR 255 255 200"  'Paint the graphicbox sickly green
PRINT #win.gb3, "BACKCOLOR green"
PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.gb3, "FLUSH"
PRINT #win, "FILL 245 245 245"
PRINT #win, "BACKCOLOR 245 245 245"
PRINT #win, "COLOR red"
PRINT #win, "PLACE 20, 30"
PRINT #win, "\Time to countdown (1-60)? Press Start."
PRINT #win, "FLUSH"
[reDo]  'Come here if user made an error
PRINT #win.tb1, ""
PRINT #win.tb1, "!SETFOCUS"
WAIT

[start]
PRINT #win.tb1, "!contents? sec"  'What did the user enter?
IF (sec<1) OR (sec>60) THEN
    NOTICE "Error!  Error!  Stupid error!"; CHR$(13);_
        sec; " is not between 1 and 60!"; CHR$(13); CHR$(13);_
        "Please try again!"
        GOTO [reDo]
END IF
delay=sec
PRINT #win.btn1, "!DISABLE"

DO
    PRINT #win.gb3, "FILL green"
    PRINT #win.gb2, "FILL 255 255 200"
    PRINT #win.gb2, "BACKCOLOR blue"  'Fill color for graphic indicator
        sec=sec-1
        cntDwn=(sec/delay)  'What percentage is finished?
        cntDwn=INT(cntDwn*100)  'Convert decimal fraction to whole number
    PRINT #win.gb3, "PLACE 50 50"
    PRINT #win.gb3, "BACKCOLOR white"  'Origin to paint a circle
    PRINT #win.gb3, "DOWN"
    PRINT #win.gb3, "CIRCLEFILLED "; (cntDwn*.5)  'Radius is ½ cntDwn value
    PRINT #win.gb2, "PLACE 25 "; (100-cntDwn)  'Upper left corner of box
    PRINT #win.gb2, "COLOR blue"
    PRINT #win.gb2, "DOWN"
    PRINT #win.gb2, "BOXFILLED 75 100"  'The lower right corner of box
    GOSUB [delay]
LOOP WHILE sec>1

PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.gb1, "FILL red"  'Fill the box RED when done
PRINT #win.gb2, "FILL 255 255 200"
PRINT #win.gb1, "COLOR white"
PRINT #win.gb1, "BACKCOLOR red"  'The color behind the printed text
PRINT #win.gb1, "PLACE 25 50"
PLAYWAVE "tada.wav", async  'Located in Windows folder, no path needed
PRINT #win.gb1, "\DONE!"
PRINT #win.gb3, "FILL 200 255 200"
PRINT #win.btn1, "!ENABLE"

FOR k=1 to 3
    GOSUB [delay]  'Pause 3 seconds
NEXT k

PRINT #win.gb1, "FILL 255 200 200"  'Repaint the graphicbox with sickly red
PRINT #win.tb1, ""  'Clear the textbox again
PRINT #win.tb1, "!SETFOCUS"  'Ready to run again

WAIT
SUB quit handle$  'Allows user to exit if execution is inside TIMER
    CLOSE #win
    END
END SUB

[delay]
    TIMER 1000, [more]
    WAIT
    [more]
    TIMER 0
RETURN

Some users are more visually inclined, and prefer to see graphic representations as opposed to reading text displays. Graphics can also display information without the need for the user to read and interpret words or numeric values, a technique designers of aircraft instrument panels are incorporating more and more. A brief glance can tell the pilot if everything is OK, or if something requires attention. Colors can be defined by name, as one of the standard graphic colors, or by RGB values. You can determine RGB values by creating custom colors using MS Paint, or by running John Davidson's J-Color Picker, available from http://john.jbusers.com/ See also Janet Terra's tutorial describing using RGB values: http://justbasic.conforums.com/index.cgi?board=tutorial&action=display&num=1109974094

Percentages are a good way to specify values for the size or location of graphics. In this program, sec is the time to countdown specified by the user. Dividing sec by delay provides a decimal fraction which can be used with the y coordinate of the graphic, or the radius of the circle. Cool, eh? Some users prefer to repaint the small graphic only with the FILL color to erase them, but issuing a new FILL command will clear the entire window or graphicbox just as well.

In this demo, we even added a sound to let the user know the program was complete. Because the WAV file is a Windows system file, we did not need to specify a path, providing the user is running Win XP. If you want to include a custom sound (non-system), or if your user is running Win 95/95, you'll have to include the WAV file in your program folder.

Wheeeee! This JB stuff is fun!