deutsch     english    français     Print

 

3.13 WIDGETS

 

 

INTRODUCTION

 

Programs you know usually have a graphical user interface (GUI). You will recognize a menu bar, input fields, and buttons. GUI components, also called widgets, are regarded as objects, which you already know from the chapter Turtle Objects. If you want to write a program with a modern user interface, it is essential that you know and understand the basic concepts of object-oriented programming (OOP) [more...The concepts of OOP are discussed in Chapter Game Programming].

The widgets are divided into different classes according to the following list:

Widget Klasse
Buttons JButton
Labels JLabel
Text fields JTextField
Menu bars JMenuBar
Menu items JMenuItem
Menus with menu items JMenu

Just like you generated a turtle by calling the constructor of the class turtle, you need to create a GUI component by calling the corresponding class constructor. The constructors often have parameters with which you can set certain properties of the widget. For example, you can create an input field with a length of 10 characters using tf = JTextField(10).

When calling the constructor, you also need to define a variable that you will use later to access the object. For example, tf.getText() returns the text currently in the text field tf.

In order to make a widget visible in GPanel, you use the function addComponent() and provide it with the object variable. The widgets are automatically placed in the order of the calls in the upper part of the GPanel window [more...For a more general layout you would have to use a layout manager].

PROGRAMMING CONCEPTS: Graphical user interface, GUI component, GUI callback

 

 

PI WITH THE RAINDROP SIMULATION

 

You have already learned how to determine an area using the Monte Carlo simulation. Imagine that you are drawing a quarter circle with a radius of 1 into a square with a side length of 1. If you now let n raindrops fall evenly onto the square you will easily be able to figure out how many of them fall onto of the quarter circle on average. Since the area of the quarter circle is

  S =  (1)/ 4 * r2* π = (π)/ 4

and the area of the square is 1, the number of drops should be

  k = n  * (π)/ 4

So, if in a computer simulation you let n drops fall and count k, you get an approximation of Pi with

  π = (4 * k)/   n  
 

The GUI consists of two labels, two text boxes, and a button. Once created, you add them to GPanel with addComponent().

It should be clear that clicking on the OK button can be considered an event. The callback is registered via the parameter named actionListener in the constructor of JButton. Hopefully you remember that you should not execute lengthy code in a callback. So, you merely call  wakeUp() in the callback, whereby the program, which was halted in the while loop using putSleep(), is awakened and then executes the simulation.

from gpanel import *
from random import random
from javax.swing import *

def actionCallback(e):
    wakeUp()
    
def createGUI():
    addComponent(lbl1)
    addComponent(tf1)
    addComponent(btn1)
    addComponent(lbl2)
    addComponent(tf2)
    validate()

def init():
    tf2.setText("")
    clear()
    move(0.5, 0.5)
    rectangle(1, 1)
    move(0, 0)
    arc(1, 0, 90)

def doIt(n):
    hits = 0
    for i in range(n):
        zx = random()
        zy = random()
        if zx * zx + zy * zy < 1:
            hits = hits + 1
            setColor("red")
        else:
            setColor("green")
        point(zx, zy)
    return hits

lbl1 = JLabel("Number of drops: ")
lbl2 = JLabel("             PI = ")
tf1 = JTextField(6)
tf2 = JTextField(10)
btn1 = JButton("OK", actionListener = actionCallback)

makeGPanel("Monte Carlo Simulation", -0.1, 1.1, -0.1, 1.1)
createGUI()
tf1.setText("10000")
init()

while True:
    putSleep()
    init()
    n = int(tf1.getText())
    k = doIt(n)
    pi =  4 * k / n
    tf2.setText(str(pi))
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

Widgets are objects of the Swing class library. They are created with the constructor that has the name of the class. When calling the constructor, you define a variable with which you can access the object. To display the widget in the GPanel, call the function addComponent() and pass it the widget variable.

After you have added all of the widgets to the GPanel, you should call validate() so that the window is rebuilt with the inserted widgets with certainty.

You can register button callbacks with the parameter named actionListener. Remember that a callback should never execute lengthy code.

 

 

MENUS (but not for food!)

 

Many windows have a menu bar with many menu items. When you click on a menu item, a submenu can also be opened, which in turn contains menu items. Menus and menu items are also regarded as objects. The selection of a menu option triggers an event that is handled by a callback.

You build a menu by creating a JMenuBar() object and adding JMenuItem objects to it using add(). You can also add a submenu. For this, create a JMenu object, and add JMenuItem objects to it. Thus, a menu is built hierarchically.

In order to simplify the code a bit, you can use the same  callback actionCallback() for all menu options. Register it with each constructor of JMenuItem with the parameter actionPerformed. In the callback, you can determine by which menu option the callback was triggered with getSource().

 
from gpanel import *
from javax.swing import *

def actionCallback(e):
    if e.getSource() == goItem:
        wakeUp()
    if e.getSource() == exitItem:
        dispose()
    if e.getSource() == aboutItem:
        msgDlg("Pyramides Version 1.0")

def doIt():
    clear()
    for i in range(1, 30):
        setColor(getRandomX11Color())
        fillRectangle(i/2, i - 0.35, 30 - i/2, i + 0.35)

fileMenu = JMenu("File")
goItem = JMenuItem("Go", actionPerformed = actionCallback)
exitItem = JMenuItem("Exit", actionPerformed = actionCallback)
fileMenu.add(goItem)
fileMenu.add(exitItem)

aboutItem = JMenuItem("About", actionPerformed = actionCallback)

menuBar = JMenuBar()
menuBar.add(fileMenu)
menuBar.add(aboutItem)

makeGPanel(menuBar, 0, 30, 0, 30)

while not isDisposed():
    putSleep()
    if not isDisposed():
        doIt()
Highlight program code (Ctrl+C copy, Ctrl+V paste)

 

 

MEMO

 

Remember to follow the rule that a callback should never execute lengthy code. You therefore perform the drawing in the main block.

To ensure that your program terminates with certainty after you press the close button of the window or the exit option, use isDisposed() to test whether the window was closed [more...When the window is closed or dispose() is called, putSleep() returns].

 

 

EXERCISES

 

1.


Edit the program Moiré from chapter 3.2 and add a text label, an input field for the delay time, and an OK button. When you click on the OK button, the image will be recreated with the specified delay time (in milliseconds).


2.

Edit the program under "Elegant Thread Graphic Algorithms" in chapter 3.8 and add the following menu: The menu item "Options" should contain a submenu with the text "Red", "Green", and "Blue". The menu item "Go" should draw the thread graphics with the color selected under Options. If no color is chosen yet, it will be drawn using black.


3*.

Take one of your favorite programs from the GPanel graphic and add some useful widgets to it.