CS 121 – Intro to Programming: Lecture 24 Announcements CS 187

CS 121 – Intro to Programming: Lecture 24
Announcements
CS 187- now two discs on Wed, 9:05, and 10:10
Program 7b due tonight
4/22 OWL assignment #11 due
4/23 - embedded 12 due
4/26 - OWL assignment #12 due
4/28 - embedded 13 due
5/3 - OWL assignment #13 due
Final Exam: Tues May 11, 1:30 PM, Totman
Current Topic:
Graphical User Interfaces - how to think
about them, code them
Underlying big idea - the Java event model
Principal players - Inheritance, Interfaces
A warm-up example that uses labels -a program that takes repeated square roots
until a value very close to 1.0 is reached…
A JLabel
import java.awt.*;
import javax.swing.*;
public class RootTester{
}
public static void main(String[] args){
try{
DisplayWindow display = new DisplayWindow();
RootPanel w = new RootPanel();
display.add(w);
display.showFrame();
}
catch(Exception e)
{e.printStackTrace();}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class RootPanel extends JPanel
implements ActionListener {
JButton quit = new JButton("Quit");
JButton roots = new JButton("Take roots");
JTextField startVal = new JTextField(15);
JLabel label = new JLabel(" Enter start value");
double x = 0.0;
int y = 150;
int drop = 20;
public RootPanel() {
setPreferredSize(new Dimension(600,600));
setBackground(Color.green);
this.add(quit); // place button in panel
quit.addActionListener(this);
this.add(label);
this.add(startVal);
this.add(roots); // place button in panel
roots.addActionListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
while (x > 1.000001){
x = Math.sqrt(x);
y = y + drop;
g.drawString(""+x,100,y);}
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == quit)
System.exit(0);
else if(e.getSource() == roots) {
x = Double.parseDouble(startVal.getText());
if (x < 1.0)
System.out.println("bad input, try again");
else
repaint();
}
}
Now: a very big idea
In complex graphics programming, separate
the underlying computational model from the
rendering code.
Example: a program that, at each mouse click,
draws up to 100 random red points in a window.
The model: generates 100 random points
The renderer: takes those points, and on a
JPanel, makes the appropriate number of
suitably positioned red circles.
Structure of separation
MVC - Model-View-Controller pattern
•Model - where underlying computation occurs
•View - where results are rendered graphically
•Controller - where model/view controlled
•In fairly simple toy examples we’ll merge the
viewer and controller
BabyPanel4
PointPix
controller
model
BabyPanel4
view
public class PointTester{
public static void main(String[] args)
{
DisplayWindow display = new DisplayWindow();
PointPix p = new PointPix(); // p is the “model”
BabyControlPanel4 b = new BabyControlPanel4(p);
display.add(b);
display.showFrame();
}
}
model (reference to model) passed to panel;
panel will invoke, manipulate model
import java.awt.*;
public class PointPix{
private Point[] points = new Point[100];
public void genPoints(){
for (int j = 0; j < 100; j++)
points[j] = genRanPoint();
}
public Point genRanPoint(){
return(new Point((int)(400*Math.random()),
(int)(400*Math.random())));
}
}
public Point[] getPoints(){return points;}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class BabyControlPanel4 extends JPanel
implements ActionListener{
JButton quit = new JButton("Quit");
JButton points = new JButton("Points");
JTextField count = new JTextField(5);
int pointCount = 0;
PointPix model; // the key model component
Point[] pts;
public BabyControlPanel4(PointPix p){
model = p; // assignment links model to panel
this.add(quit); // place button in panel
quit.addActionListener(this);
this.add(points); // place button in panel
points.addActionListener(this);
this.add(count);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
for(int j =0; j < Math.min(100,pointCount);
j++){
g.fillOval((int)pts[j].getX(),
(int)pts[j].getY(),8,8);
}
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == quit)
System.exit(0);
else
if(e.getSource() == points){
pointCount =
Integer.parseInt(count.getText());
model.genPoints();
pts = model.getPoints();
repaint();
}
}
Menus
Menus may well be the single signature
element of modern computing
•In some ways in Java they’re simple:
•You create a menu bar
•You add a menu to the bar
•You add menu items to the menu
•You treat menu items like buttons - that is,
you deal with them using the ActionListener
interface
One tricky part: they are part of the panel
and the JFrame
JMenuBar attached to frame
JFrame (frame)
contentPane
JPanel (panel - is
“affixed” to
contentPane)
When menu lives
Menus
Like a column of buttons for making choices
Hardware more complicated
MenuItems attach to the Menu
Menu attaches to MenuBar
Menu Bar (on frame)
item1
item2
item3
Menu
import javax.swing.*;
import java.awt.*;
public class MenuDemoDriver{
}
public static void main(String[] args){
DisplayWindow d = new DisplayWindow();
JMenuBar menuBar = new JMenuBar();
d.setJMenuBar(menuBar); // attach bar to frame
MenuColorPanel p = new MenuColorPanel(menuBar);
d.addPanel(p);
d.showFrame();
}
// pass (reference to) menuBar down to panel
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MenuColorPanel extends JPanel
implements ActionListener{
JMenuBar b;
JMenu menu = new JMenu("Colors");
JMenuItem red = new JMenuItem("red");
JMenuItem blue = new JMenuItem("blue");
JMenuItem quit = new JMenuItem("Quit");
public MenuColorPanel(JMenuBar bar){
b = bar; // menu bar passed from JFrame
b.add(menu); // attach menu to the bar
menu.add(red); // a menu choice
menu.add(blue); // a menu choice
menu.add(quit); // a menu choice
//panel: listener for menu items
red.addActionListener(this);
blue.addActionListener(this);
quit.addActionListener(this);
}
setBackground(Color.white);
public void actionPerformed(ActionEvent e){
if (e.getSource() == quit) System.exit(0);
if (e.getSource() == red) setBackground(Color.red);
else
if (e.getSource() == blue)
setBackground(Color.blue);
}
}
Java’s event model
What modern computing is like..
Your program needs to know:
1) What to listen for
2) Identify listener
3) Marry 1 and 2
4) Provide a mechanism for reacting properly
to events
import java.awt.*;
public class BabyButtonDriver{
}
public static void main(String[] args){
DisplayWindow d = new DisplayWindow();
BabyControlPanel p =
new BabyControlPanel();
d.addPanel(p);
d.showFrame();
}
import java.awt.*; import javax.swing.*;
import java.awt.event.*;
public class BabyControlPanel extends JPanel implements
ActionListener{
JButton quit = new JButton("Quit"); // make button object
public BabyControlPanel(){
setBackground(Color.red);
this.add(quit); // place button in panel
quit.addActionListener(this); // listener for button: panel
}
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == quit) System.exit(0);
}
So far we’ve seen several Swing
components for providing/displaying
input:
Jbutton, JTextField, JTextArea, Jlabel,
JMenu, etc.
One special component we haven’t talked
about: the mouse itself
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Locator extends JPanel
implements MouseListener{
int x,y;
String location = "";
public Locator(){
addMouseListener(this);//panel listens for mouse
}
public void paintComponent(Graphics g){
g.drawString(location,x,y);
}
public void mouseClicked(MouseEvent e){
x = e.getX(); y = e.getY();
location = "("+ x +"," + y + ")";
repaint();
}
public
public
public
public
}
void
void
void
void
mouseEntered(MouseEvent e){}
mouseExited(MouseEvent e){}
mousePressed(MouseEvent e){}
mouseReleased(MouseEvent e){}
The main points:
•MouseListener - not ActionListener
•The listener registration code is different
•There are five methods in the interface - but
here we’re only using 1!
•Another interface: MouseMotionListener
(deals with mouse motion, not just button
pressing..) coming soon!
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // needed for event handling
public class TargetPanel extends JPanel implements
MouseListener{
int x = 0; // x-y coordinate of click
int y = 0;
int ringCount = 1; // ring count part of panel state
public TargetPanel(){
addMouseListener(this);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
for(int i = 0; i < ringCount; i++)
drawCircle(x,y, (10+i*5),g);
}
public void drawCircle(int u, int v, int radius,
Graphics g){
g.drawOval(u-radius,v-radius,2*radius,2*radius);
}
public void mouseClicked(MouseEvent e){
ringCount++;
x = e.getX(); y = e.getY();
repaint();
}
public
public
public
public
void
void
void
void
mouseEntered(MouseEvent e){}
mouseExited(MouseEvent e){}
mousePressed(MouseEvent e){}
mouseReleased(MouseEvent e){}
(u-radius, v-radius)
radius
(u,v)
radius