CS2212 - Brief Introduction to Writing Java Code that has a Graphical User
Interface
This workshop will probably take about 2 hours.
- NOTE: In Eclipse, to see the classes pop after you hit the . after an object, you should go to Windows>Preferences>Java>Editor>Content Assist>Advanced and make sure that Java Proposal is selected.
- Go to the website:http://java.sun.com/docs/books/tutorial/ui/features/components.html and browse to see what objects (buttons, menus, textboxes) are available to you to use in a Java Graphical User Interface. Also, here is another tutorial you might want to bookmark, it was suggested by a former cs2212 student as very useful: http://zetcode.com/tutorials/javaswingtutorial/
- Start Eclipse on Unix by typing eclipse or on Windows by clicking on the
icon. If the Icon in Windows does NOT work, you should go to C:\Program Files\eclipse and click on the icon there (this is likely happening because your workspace area is not set yet)
- Do File>New>Project>Java Project, give it any project name you want, then click on the Finish button
- Do File>New>Class Call your class FirstGUI, make sure it has public static
void main
- In FirstGUI, we are going to create a simple gui, (copy and paste the code below) into that file.
This program will have a frame (this is your outer window) and a panel inside your frame
that holds components, in this case 2 components (2 buttons). You can cut the code from below, or get it from this file http://www.csd.uwo.ca/~lreid/cs2212/Worksheets/FirstGUI.java this code
does the following:
- Creates a frame
- Creates a panel
- Creates 2 buttons
- Puts the panel inside the frame
- Puts the buttons inside the panel
- Add listeners for the 2 buttons
- Does something if either of the buttons is pressed
- Makes the frame visible
- Look over the code to make sure you see where the 8 steps above happen and the lines of code that cause them..
Sample code:
/*
* FirstGUI.java - an example of handling events.
* For this example, we will use inner member classes to
* implement an ActionListener for each button. This approach
* can avoid some of the code clutter that anonymous classes
* can sometimes cause. It also concentrates the action code
* all in one place, and allows synonyms.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FirstGUI extends JPanel
{
private static JFrame frame; //
static so main can use it
private static JPanel myPanel; // a
panel for contentPane
private JButton button1; // Define
out here to make
private JButton button2; // visible
to ActionListener
// Define handlers for each event
needed (button1, button2)
private class Button1Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JButton tempButton;
tempButton = (JButton) e.getSource();
JOptionPane.showMessageDialog(frame,"Button 1 pressed");
tempButton.setToolTipText("Hi, I am a cs2212 button");
tempButton.setForeground(Color.ORANGE);
}
}
private class Button2Handler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(frame,"Button 2 pressed");
}
}
public FirstGUI() // Construct, build
GUI
{
// Create a
panel
myPanel = new JPanel();
// Create
the buttons
button1 = new JButton("Button 1");
button2 = new JButton("Button 2");
// For each
component add it ActionListener class
button1.addActionListener(new
Button1Handler());
button2.addActionListener(new
Button2Handler());
myPanel.add(button1); // Adds to current JFrame
myPanel.add(button2);
}
public static void main(String s[])
{
FirstGUI gui = new FirstGUI(); // FirstGUI component
frame = new JFrame("My Very First Java GUI"); // JFrame for the panel
// Standard idiom
to catch close event
frame.addWindowListener(new
WindowAdapter() {
public void windowClosing(WindowEvent
e)
{System.exit(0);} });
frame.getContentPane().add(myPanel);
frame.pack(); // Ready to go
frame.setVisible(true);
}
}
//from The essence of OO programming with java
and uml by wampler |
- RUNNING THE SIMPLE GUI: Save the code (save the code will display any syntax errors you have, if you just cut and pasted the code from above, you should NOT have any syntax errors). Then run the program to see what is displayed. NOTE: The first time you run it, run it from the Menu Bar (don't use the run button on the tool bar), to run it from the menu bar: select Run>Run As>Java Application Try clicking on each of the 2 buttons to see what happens. After clicking button1, try hovering over it.
- CHANGING ATTRIBUTES: See if you can figure out how to change the buttons background colour and
foreground colour. Hint: go to the java api
for javax.swing. Then look up JButton and find the method that will set the
background color...I have bolded the words that might help you find the correct methods ;-), they are methods from the JComponent class that are inherited by the JButton class. You might want to use the static Color class constants for
the colours you want, for example Color.BLACK). NOTE: if you are doing this on a Mac computer, the background colour might not change (it is using the default look and feel for Macs, but the foreground should change color). Hint: In Eclipse, if you type slowly, after you hit a period, you will see available methods for that object. For example, type button1. and then wait for a second after hitting the period and you will see some methods pop up, then continue typing like this button1.s (just the s) and you will see all methods that start with s. Try this also with Color. Run the program again to test your code.
- ADDING A MENU BAR: See if you can figure out how to add a menu: Hint: create a JMenuBar (this
is a menu bar at the top of a window) and
attach it to the frame, create a JMenu (this would be like the File
menu or the Edit menu) object, create some JMenuItem objects (these
would be like the New, Open, Print, Print Preview or Exit inside the File
menu) and
add them to the JMenu, attach the JMenu object to the JMenuBar. I had to make
the JMenuBar static (like my JFrame) and construct it (using new) inside the main, then I had
to use a command setJMenuBar from the frame inside the main. HINT: when you
use the new command to create a JMenu or JMenuItem, make sure you put the name
you want as a parameter, for example: printMenu= new JMenuItem("Print");
or else it wont show up on the menu bar. After you get the
menu displaying, try adding a separator (addSeparator)
- MAKE THE MENU BAR DO SOMETHING: Add an exit menu item and make the code quit when the user its that menu
item. Hint: System.exit(0); will cause the code to quit, so this is the action
you want to occur when the user picks the exit option from the menu. (remember
to tell the Exit JMenuItem to listen by adding an actionlistener to it, like
was done for the JButtons, also you will have to write a private class just like Button1Handler for the exit menu item that calls the code System.exit(0);)
- ADDING BUTTONS THAT PERFORMS AN ACTION: Add 3 more buttons. Make one of the buttons actually do something: it should change the colour of the
background of myPanel. Hint: not only will you need to define the buttons and created
them and add them to the panel, but to to make one of the buttons change the background colour,
you will need to add an action listener for that button. When testing the new button, try
resizing the window FIRST, then set the background colour. Notice that the
buttons dont resize.
- EXPERIMENTING WITH LAYOUT OF THE ITEMS ON THE SCREEN: We are now going to try moving the buttons around. Change the code as
follows and then try resizing the windows and try clicking on your button to
change the background.
myPanel = new JPanel();
myPanel.setLayout(new BorderLayout());
myPanel.add(button1, BorderLayout.NORTH); // Adds
to current JFrame
myPanel.add(button2, BorderLayout.EAST);
myPanel.add(button3, BorderLayout.WEST);
myPanel.add(button4, BorderLayout.CENTER);
myPanel.add(button5, BorderLayout.SOUTH); |
- Run the program. Resize the screen, notice what happens to button 4.
- Now change the line: myPanel.setLayout(new BorderLayout()); to be
myPanel.setLayout(new BorderLayout(10,20)); save the program, run
it again and click on your
background button.
- Now change that line to: myPanel.setLayout(new GridLayout(1,5));
and run the program and try resizing the window, TRY MAXIMIZING YOUR WINDOW.
- Now change that line to: myPanel.setLayout(new GridLayout(5,1));
and run the program
- Now change that line to: myPanel.setLayout(new GridLayout(5,1,10,20));
and run the program
- Now change that line to: myPanel.setLayout(new GridLayout(3,5));
and run the program
- Now change that line to: myPanel.setLayout(new GridLayout(4,6));
and run the program
- Now add the following pieces of code in the appropriate places:
private JPanel
myInnerPanel;
myInnerPanel = new JPanel();
myInnerPanel.setLayout(new BorderLayout(10,10));
myPanel.add(button1,BorderLayout.NORTH);
// Adds to current JFrame
myPanel.add(button2,BorderLayout.SOUTH);
myPanel.add(myInnerPanel);
myInnerPanel.add(button3, BorderLayout.WEST);
myInnerPanel.add(button4, BorderLayout.CENTER);
myInnerPanel.add(button5, BorderLayout.SOUTH); |
19. Try changing the GridLayout rows and columns and see what happens (try 3,1
then try 1, 3, then try 2,2)
Approximate Time to Complete the Above Exercises: 1 hour
Making Your First Blackberry Application
- Make sure you are on a machine that has the Blackberry Plugin for Eclipse. As of August 2011, the latest version was 1.3. The link is: http://us.blackberry.com/developers/javaappdev/javaplugin.jsp. As of August 2011, it seems to only work with Java 6 (not Java 7).
- Start up Eclipse. If the Icon in Windows does NOT work, you should go to C:\Program Files\eclipse and click on the icon there (this is likely happening because you workspace area is not set yet)
- Do File>New>Other>BlackBerry>BlackBerry Project, give it the project name of FirstBB, then click on the Finish button. In the tab that appears, you can give your Blackberry application a title such as "Your Names First Blackberry App"
- Do File>New>Class Call your class SimpleBB, and put the following code in class SimpleBB
import net.rim.device.api.ui.*;
public class SimpleBB extends UiApplication {
public static void main (String[] args) {
SimpleBB splash = new SimpleBB();
splash.enterEventDispatcher();
}
public SimpleBB() {
pushScreen (new FirstScreen());
}
}
|
:
- Now make another class called FirstScreen and put the following code in class FirstScreen:
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public class FirstScreen extends MainScreen implements FieldChangeListener {
private ButtonField buttonPressMe1;
private ButtonField buttonPressMe2;
private ButtonField buttonQuit;
public FirstScreen() {
super();
buttonPressMe1 = new ButtonField("Press Me");
buttonPressMe2 = new ButtonField("Press Me TOO");
buttonQuit = new ButtonField("Quit");
buttonPressMe1.setChangeListener(this);
buttonPressMe2.setChangeListener(this);
buttonQuit.setChangeListener(this);
this.add(buttonPressMe1);
this.add(buttonPressMe2);
this.add(buttonQuit);
}
public void fieldChanged(Field field, int context) {
if (field == buttonQuit) {
this.close();
}
}
} |
- Save both files/classes. At the top left, open the FirstBB folder, then open the src folder. Likely you have 2 folders in here called --> (default package) and mypackage. mypackage contains sample source code that is always created when you make a new blackberry project (notice it has the 2 classes in it called MyApp.java and MyScreen.java). Remove the mypackage folder so that it will run the classes you just created.Now click on Run>Run As>BlackBerry Simulator. Click on ALL, then scroll till you find either Your Name First Blackberry App or FirstBB and click on it and try out the buttons and see what happens. Note: the extended class MainScreen is the main display area for holding buttons, text boxes, etc... It takes up the width of the display. Only the top screen will show (think of the list of screens like a stack that you push and pop screens onto). Also note: the simulator is very slow to start up and shut down, I havent figured out a work around for this, if you do, please email me your solution.
- Add the code that will change the words (the label) on buttonPressMe2 to Press Me ALSO if the user clicks on buttonPressMe1, Make sure that your code works.
- When working with Blackberry screens you push and pop them onto the screen. Only the most recently pushed screen will appear. Lets make another screen and try pushing it on and then popping it off. Create another class called AnotherScreen. In this class we will make a text box and 2 buttons. The one button will pop off the current screen. The second button will show you how to get at information in the text box. Create the class AnotherClass with the following code:
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public class AnotherScreen extends MainScreen implements FieldChangeListener {
private ButtonField buttonGoBack;
private ButtonField buttonTest;
private EditField someText;
private WhoIsIt someone;
public AnotherScreen () {
buttonGoBack=new ButtonField("Go Back",ButtonField.CONSUME_CLICK);
buttonTest=new ButtonField("Test Me",ButtonField.CONSUME_CLICK);
buttonTest.setChangeListener(this);
buttonGoBack.setChangeListener(this);
someone=new WhoIsIt("Brad Pitt");
someText = new EditField("Who are you:", someone.getMessage());
this.add(someText);
this.add(new SeparatorField());
this.add(buttonTest);
this.add(buttonGoBack);
}
public void fieldChanged(Field field, int context) {
if (field == buttonGoBack) {
UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
} else if (field == buttonTest) {
this.add(new LabelField(someText.getText()));
someone.setMessage (someText.getText());
}
}
}
|
- Now create another class called WhoIsIt with the following code:
public class WhoIsIt { private String msg; public WhoIsIt(String who) {
msg=who;
}
public String getMessage() { return msg; } public void setMessage(String message) { this.msg = message; } } |
- In your FirstScreen class, add code to make the buttonPressMe2 push the AnotherScreen onto the display. You will need to create a new instance of AnotherScreen and then write code similar to the code in AnotherScreen that pops the screen, but instead of popScreen, call pushScreen with the new instance.
- Notice that every component on Blackberry screen is stacked vertically. That is because the default layout is called a VerticalFieldManager. Lets try out some of the other Field Managers. Add the following code to the AnotherScreen constructor::
HorizontalFieldManager hfm = new HorizontalFieldManager();
this.add(hfm);
- Now change all the lines for this.add(.... to be hfm.add(... Remove the SeparatorField (it makes a horizontal line across the screen) Change the order so the buttons are added first. Then run the code again and notice the difference
- In order to save data on the Blackberry (you will need to have data persistence for your project), you need to use the Blackberry class called Persistable There is a good tutorial on Persistable objects here. We will attempt to make the name we type in on the screen (over top of the Brad Pitts name) actually save to the Blackberry, thus when we run the program again, it will use the name we saved rather than "Brad Pitt".
- First add the lines implements Persistable immediately after the class definition for WhoIsIt, thus you should now have public class WhoIsIt implements Persistable {
- Also, in the WhoIsIt class, make sure you import the following package: net.rim.device.api.util.Persistable
- In the AnotherScreen class, import the following classes: net.rim.device.api.system.PersistentObject and net.rim.device.api.system.PersistentStore;
- For the AnotherScreen class, create a new private attribute (just under the declaration for WhoIsIt) that will hold the data to be stored. It should be declared as follows: private static PersistentObject store;
- In constructor for AnotherScreen, before you create anything else, add the line to create the storage item called store. The code is:
store = PersistentStore.getPersistentObject(0x1dfc10ec9447eb14L); //NOTE; the part in the brackets just must be a unique LONG
- Now let's write the code to store something in the store object. In the AnotherScreen, in the method fieldChanged, find the area where you do something if the button buttonTest is pressed. Then add the following code under the line someone.setMessage (someText.getText()); The code to be added is:
synchronized(store) {
store.setContents(someone); //moves the data inside of someone into the store variable
store.commit(); //writes the store variable to the blackberry memory
}
- When the application is exited, the data (the name we typed) in the WhoAmI class (in the variable somone), will now be written somewhere in memory on the Blackberry. Now we need to make sure when we open the application again that it no longer says "Brad Pitt" but instead it reads the name we typed from the Blackberry memory and displays that instead of Brad Pitt. Thus, as soon as we create the AnotherScreen, we should read in the data stored in the Blackberry memory. So let us put the new code into the constructor for AnotherScreen. We need to make sure we remove the old line: someone=new WhoIsIt("Brad Pitt"); and replace it with the following code:
synchronized (store) {
someone=(WhoIsIt)store.getContents(); //read the data from the blackberry memory and put it back in someone
if (someone==null) { //if initially the store had never been assigned, then just give it the default value
someone = new WhoIsIt("Brad Pitt");
}
}
- Close the emulator COMPLETELY and then run the program again (don't leave the emulator running for this step)
- Then try running your application. If you are having problems, try cleaning the simulator (Blackberry>Clean Simulator)
- The above code made use of the Blackberry widgets. Thus, the program above will run wonderfully on a Blackberry but not on any other system. If we change the above code to use J2ME Widgets instead of the Blackberry widgets, then the code will run on any handheld device that supports J2ME AND on a Blackberry (this would include devices built by Nokia, Motorola, see here for a list). There are several types of screens but the most useful is the Form because it can hold components. There are useful features in the J2ME libraries that you may HAVE to use in your project such as connections to the internet and writing and reading from files.
- HINT: If you want to start fresh (remove any applications from the emulator that you have been testing), then do this: In Eclipse, from the Blackberry Menu, select Clean Simulator. One group from the 2010/2011 year did this command EVERY time they tested their code, they swore that it helped clean things up (but you shouldnt have to do this everytime).
- Here are some helpful sites that the students found the first time we did this course using blackberries:
- UI Components Quick Reference Guide
- User Interface Field Reference
- Blackberry Fields and Borders and Backgrounds
- User Interface Overview
- Java Development Support Forum
More GUI Stuff --> Something fun, adding a slider
1. Edit the FirstGUI.java class file from above that you have already copied. MAKE SURE YOU CHANGE TO THE JAVA PERSPECTIVE IN ECLIPSE
2. Add a slider bar. I will give you the code, you have to figure out where it should go. Here are the pieces you will need to add (you just need to figure out where to put them AND you need to write the code to add the slider to the panel.)
import javax.swing.event.*; |
private JSlider redSlider; |
redSlider = new JSlider();
redSlider.setOrientation(JSlider.VERTICAL);
redSlider.setPaintLabels(true); //show tick mark labels
redSlider.setPaintTicks(true); //show tick marks
redSlider.setMinimum(0);
redSlider.setMaximum(255);
redSlider.setValue(100);
redSlider.setMajorTickSpacing(50);
redSlider.setMinorTickSpacing(25);
redSlider.addChangeListener(new SliderHandler()); |
private class SliderHandler implements ChangeListener {
public void stateChanged(ChangeEvent event) {
int r;
r=redSlider.getValue();
button1.setBackground(new Color(r,0,0));
}
} |
Now add the redSlider to the panel right after the buttons are added to the panel |
3.After you get your red slider bar working, try adding a green and blue one!
Approximate Time to Complete the Above Exercise: 15 minutes
More GUI Stuff -->Changing the color of groups of buttons/components
1. One fairly simple way to change the look of your window is to change the background and foreground of all the buttons/menu bars items/panels etc. on the window. For example, for a sunset theme, you might set the foreground to be red and the background to be yellow for some of the components on your window. One way to implement this, is to add all the components (buttons, etc) that you wish to change, to a bag/collections and then everytime you want to change the look, you just use an iterator to walk through the collection and change the colors. We are going to do this with FirstGUI (and the sliders that you added).
2. Add the following code in the correct locations to get access to a linkedlist where we will store all the buttons:
import java.util.*;
private LinkedList itemsForSkin;
3. Add the code to construct the LinkedList and add code similar to this: itemsForSkin.add(button1) to add ALL the components whose look you wish to change to the LinkedList (we will add the 2 buttons and the 3 sliders you made)
4. Add the following code in the appropriate location, so that when the user clicks on button2, the foreground and background of the buttons and sliders change as indicated in the code: (NOTE: this code walks through all the items in the linkedlist and changes them all to have a background color of BLUE, also add the line of code needed to make sure the items have a foreground color of YELLOW)
Iterator itr;
JComponent holder;
itr = itemsForSkin.iterator();
while (itr.hasNext()) {
holder = (JComponent) itr.next();
holder.setBackground(Color.BLUE);
}
Approximate Time to Complete the Above Exercise: 10 minutes