There is another benefit to these widget sets besides saving the programmer some work. Programs using a particular Widget set will all tend to have similar "look-and-feel"-s and behave similarly. This is a great benefit to the user who can count on things to look the same and act the same between programs.
There are really no new paradigms or technologies involved in using widgets. They are created and added using the same methods we used for JPanels when discussing graphics. The event handling follows that used for the mouse events. The additional complexities introduced by GUI components are really to their variety, functionality, and sheer number per program. In particular, the issues are:
Much of the effort of GUI programming is combing the books and on-line documentation. There are around 20 component types in Java, we will only give a small sampling in this lecture, chosen to illustrate the basic points above. We are also going to postpone a discussion of layout for another time.
We are also going to ignore the whole issue of what makes a good GUI design. This is far beyond the scope of this course and is a field in itself ( there are many books on this subject, along with several journals and conferences).
JButton toggle = new JButton("Toggle");
// Random stuff we just have to do (the book explains, kind of)
Container contentPane = myframe.getContentPane();
// add panel
contentPane.add(mypanel);
// add button to panel
mypanel.add(toggle);
ActionEvent, the
handling method is the actionPerformed, method of the
ActionListener interface. So we make our listener class:
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("Toggle pressed");
}
}
and add it to our button
toggle.addActionListener(new ButtonHandler()); mypanel.add(toggle);
// Now an inner class so we can access data.
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
if(current.equals(Color.red))
current = Color.blue;
else
current = Color.red;
repaint();
}
}
MyPanel(){
JButton toggle = new JButton("Toggle");
// add listener
toggle.addActionListener(new ButtonHandler());
// add button
add(toggle);
}
We now have the same application as in lecture 9, but the toggling only
occurs when the mouse clicks in the button.
The actionPerformed method, if shared, needs to be able to tell which
button was pressed. It can do that based on information on the ActionEvent.
It can get a string associated with the event through
getActionCommand() or the source object (the button) through
getSource(). The ActionCommand string for buttons defaults to
the label string.
To use the getSource method, we have to have the button variables in scope to compare against. So we will now make them instance variables on myclass (rather than local to the constructor).
Color current = Color.red;
String msg = "Hello World";
// button variables now instace vars.
// May as well init here.
JButton toggle = new JButton("Toggle");
JButton green = new JButton("Green");
JTextField text = new JTextField(10);
// Button listener. Now an inner class so we
// can access mypanel data.
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
// check source, if green button, set color
if(e.getSource() == green){
current = Color.green;
}
else if(e.getSource() == text){
String s = text.getText();
if(s != null) msg = s; // install as new msg
repaint();
}
else{ // do toggle stuff
if(current.equals(Color.red))
current = Color.blue;
else
current = Color.red;
}
repaint();
}
}
MyPanel(){
// add listeners
ButtonHandler b = new ButtonHandler();
toggle.addActionListener(b);
green.addActionListener(b);
text.addActionListener(b);
// add buttons (and text field)
add(toggle);
add(green);
add(text);
}
class MyPanel extends JPanel{
// Color and string are now instance vars so we can change them
Color current = Color.red;
String msg = "Hello World";
// button variables now instace vars.
// May as well init here.
JTextField text = new JTextField(10);
// Menu items created by menu.add(), still need to keep them for handler
JMenuItem toggle;
JMenuItem green;
// We are using button Listener verbatim. Only difference
// is that we changed our buttons above to JMenuItems
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
// check source, if green button, set color
if(e.getSource() == green){
current = Color.green;
}
else if(e.getSource() == text){
String s = text.getText();
if(s != null) msg = s; // install as new msg
repaint();
}
else{ // do toggle stuff
if(current.equals(Color.red))
current = Color.blue;
else
current = Color.red;
}
repaint();
}
}
// Need myframe so we can add menubar
// (could do in main and pass in menubar instead)
MyPanel(JFrame myframe){
// Need to add menu stuff and add to frame (not panel)
JMenuBar mb = new JMenuBar();
myframe.setJMenuBar(mb);
// create menu and add to menuber
JMenu cmenu = new JMenu("Colors");
// Note: book is in error here, calls non-existant addMenu()
mb.add(cmenu);
// add() method on menu creates and adds menu items
toggle = cmenu.add("Toggle");
// add a horiz line to look cool
cmenu.addSeparator();
green = cmenu.add("Green");
// make one instance of listener and add to all
// works exactly the same as for buttons
ButtonHandler b = new ButtonHandler();
toggle.addActionListener(b);
green.addActionListener(b);
text.addActionListener(b);
// add text field
add(text);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
// System.out.println("paintComponent");
g.setColor(current);
g.drawString(msg,50,100);
}
}
// new ButtonHandler that calls dialog from menu item rather
// than toggling color directly
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
// check source, if green button, set color
if(e.getSource() == ditem){
// We do not seem to be able to create and re-use a
// dialog the way the book does! Must create new every time???
MyDialog dialog = new MyDialog(null);
dialog.show(); // popup dialog
// get data out
current = dialog.getCurrent();
}
else if(e.getSource() == text){
String s = text.getText();
if(s != null) msg = s; // install as new msg
}
repaint();
}
}
public class MyDialog extends JDialog{
// must make instance var since we need it to access panel data.
DialogPanel dialogPanel;
public MyDialog(JFrame parent){
// must call JDialog constructor,
// final arg true makes show() blocking.
super(parent,"Color Dialog",true);
setSize(200,200); // size in pixels
// new default close action -- DISPOSE rather then EXIT
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// Add panel
dialogPanel= new DialogPanel(this);
getContentPane().add(dialogPanel);
}
public Color getCurrent(){
// just forward request
return(dialogPanel.getCurrent());
}
}
// DialogPanel hold buttons. Class has listener as inner class
class DialogPanel extends JPanel{
// the dialog that contains me, needed to call isVisible(false)
JDialog dialog;
// This color is not used to draw, it is just the 'model' that
// this dialog alters. This data is retrieved by the main app
// through the getCurrent9) method
Color current = Color.black;
// Handler for Mouse presses and clicks
// Extends MouseAdapator
// (which implements MouseListener with empty methods)
// We use an inner class so we can access to data on JPanel
JButton toggle = new JButton("Toggle");
JButton green = new JButton("Green");
JButton ok = new JButton("OK");
// Button listener. Now an inner class so we
// can access mypanel data.
class ButtonHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
// check source, if green button, set color
if(e.getSource() == green){
current = Color.green;
}
else if(e.getSource() == toggle){ // do toggle stuff
if(current.equals(Color.red))
current = Color.blue;
else
current = Color.red;
}
else{ // OK
// setVisible(false) close dialog and causes show() to return!
dialog.hide();
}
}
}
DialogPanel(JDialog dialog){
// make one instance of listener and add to all
this.dialog = dialog;
ButtonHandler b = new ButtonHandler();
toggle.addActionListener(b);
green.addActionListener(b);
ok.addActionListener(b);
// add buttons (and text field)
add(toggle);
add(green);
add(ok);
}
public Color getCurrent(){
return(current);
}
}
class MyFrame extends JFrame{
public MyFrame(){
// set up UI
setTitle("MyFrame");
setSize(200,200); // size in pixels
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// make model
MyTableModel model = new MyTableModel(31);
// make table
JTable table = new JTable(model);
// Random stuff we just have to do (the book explains, kind of)
Container contentPane = getContentPane();
// add panel with scroller
JScrollPane scroll = new JScrollPane(table);
contentPane.add(scroll);
}
}
class MyTableModel extends AbstractTableModel{
int rows = 2;
int cols = 2;
String[] colnames = {"Day","Hours"};
Integer[] hours;
MyTableModel(int rows){
this.rows = rows;
hours = new Integer[rows];
for(int i=0;i 0) return(true);
return(false);
}
}
public class TableTest{
// OK let's have our main() create a frame.
public static void main(String[] args){
MyFrame myframe = new MyFrame();
myframe.show();
}
}