Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Lecture Twelve – More on GUIs Java API Introduction to LibraryGUI LibraryGUI program LibraryGUI code LibraryGUI walkthrough LibraryGUI layout LibraryGUI listeners Drill Read Chapter 10-11 1 Java API Following is a treatment on API – this is very important. Good programmers don’t just write classes – they find classes. They find them in an API. When you learn to use the API effectively, it will greatly enhance your capability as a programmer in Java. 2 Java API The components we introduced in previous lessons (and the ones we will use in this lesson) are only a portion of the many components that are available for us to use. We can look up other helpful components by referencing the documentation provided on Java’s API (application programming interface) The most up-to-date version of Java’s API Specification can be found at http://java.sun.com/j2se/1.5.0/docs/api/index.html 3 Java API This is a helpful resource for Java programmers which allows us to look up the members variables and methods of the classes available for us to use. It also provides us with other helpful information about the inheritance structure of a class. We will take a quick detour to show you how to read and understand the API specification. Open up the link to the API specification in an internet browser and follow along. We will use the JButton as an example component that we want to learn more about. 4 Java API Once you open the specification you should see this screen. 5 Java API On the left we have a list of classes and above that, a list of packages 6 Java API Since JButton is in the javax.swing package we will choose that from the package list. This will update the class list to only include classes from that package 7 Java API We will then find JButton and click it to open up it’s specification. 8 Java API The first thing we see is the inheritance structure for JButton. We can see the superclasses that it inherits from, and we are even given a list of it’s subclasses. 9 Java API Scrolling down a little further and we can see the list of fields (i.e. static constants) that are defined for JButton. We can also see the constants that are inherited from it’s superclasses. 10 Java API Next we are given a list of available constructors for JButton. We typically have been using the fourth constructor in the list which “creates a button with text.” 11 Java API Right after that we have a list of methods followed by the methods inherited from superclasses. To the left we are given the return type. To the right we have the name of the method and its arguments. 12 Java API We can get more information on a method by clicking it’s link. Click the link for the setText method (which is inherited from AbstractButton). 13 Java API Now we are able to see the entire method header, a description of the method (and its arguments), and possibly a list of related methods. 14 Java API Over time you will learn to familiarize yourself with the API and will become more comfortable using it. The rest of this lesson will cover a few GUI components and their most commonly used methods. If you ever want to learn more about the capabilities of a certain component you can now teach yourself with the API specification! 15 Introduction to LibraryGUI The rest of this lesson is a demonstration and discussion of a more complex GUI It is quite long, compared to previous lessons But – just type in the code (carefully) and get it to run, then go through the LibraryGUI walkthrough slides. If you find some parts difficult to understand, mark it and move on. You can return to this example later, after you have developed more programming skills. Just going through this example should help you to make that transition from student to programmer. 16 Introduction to LibraryGUI Back in Lesson 6 you were introduced to GUIs, however, most of the concepts were not thoroughly explained You should already have a basic understanding of: how GUIs are constructed how we add components to content panes how we use layouts to organize our components how we use listeners to handle events This lesson is meant to dive a little deeper into GUIs and give examples of other components, layouts, and listeners that are available to us. 17 LibraryGUI program In Lesson 10 we wrote objects (in the form of classes) to emulate a library check out system. Now, we will write a GUI for our library check out system using some of the components and listeners found in Chapters 10 and 11 of your book We will modify our Book object slightly. We will call this modified Book class Book2.java This program will be a bit longer than previous programs, but as always be sure to type the code in yourself and get it working! 18 LibraryGUI code // this class is in a file named "Book2.java" public class Book2 { // constant values for book type static final String HARDCOVER = "Hardcover"; static final String PAPERBACK = "Paperback"; // private member variables private String title; private String author; private String type; private String publisher; private String summary; private int copyrightYear; private boolean checkedOut; 19 LibraryGUI code // default constructor public Book2() { title = ""; author = ""; type = ""; publisher = ""; summary = ""; copyrightYear = 0; checkedOut = false; } // example constructor public Book2(String title, String author, String type, String publisher, String summary, int copyrightYear) { setBook(title, author, type, publisher, summary, copyrightYear); } 20 LibraryGUI code // public member functions public void setBook(String title, String author, String type, String publisher, String summary, int copyrightYear) { this.title = title; this.author = author; this.type = type; this.publisher = publisher; this.summary = summary; this.copyrightYear = copyrightYear; checkedOut = false; } public void setTitle(String title) { this.title = title; } 21 LibraryGUI code public void setAuthor(String author) { this.author = author; } public void setType(String type) { this.type = type; } public void setPublisher(String publisher) { this.publisher = publisher; } public void setSummary(String summary) { this.summary = summary; } 22 LibraryGUI code public void setCopyright(int copyrightYear) { this.copyrightYear = copyrightYear; } public String getTitle() { return title; } public String getAuthor() { return author; } public String getType() { return type; } 23 LibraryGUI code public String getPublisher() { return publisher; } public String getSummary() { return summary; } public int getCopyright() { return copyrightYear; } public boolean getCheckedOut() { return checkedOut; } 24 LibraryGUI code public void checkOut() { checkedOut = true; } public void checkIn() { checkedOut = false; } } // end of Book2.java 25 LibraryGUI code // this is in a file names "LibraryGUI.java" import java.awt.*; import java.lang.*; import javax.swing.*; import java.awt.event.*; public class LibraryGUI extends JFrame implements KeyListener, ItemListener, WindowListener { // declare GUI components private JPanel selectPanel; private JLabel selectBookLabel; private JComboBox selectBookBox; private JPanel bookInfoPanel; private JLabel titleLabel; private JTextField titleField; private JLabel authorLabel; private JTextField authorField; 26 LibraryGUI code private JLabel publisherLabel; private JTextField publisherField; private JLabel copyrightLabel; private JTextField copyrightField; private JLabel summaryLabel; private JTextArea summaryArea; private JScrollPane summaryScroll; private JCheckBox hardcoverCheckBox; private JPanel checkInOutPanel; private ButtonGroup checkGroup; private JRadioButton checkedInButton; private JRadioButton checkedOutButton; // declare our book array private Book2[] books; // variable used to keep track of the current book private int currentBook; 27 LibraryGUI code // main method - simply constructs a Library GUI public static void main(String args[]) { LibraryGUI myGUI = new LibraryGUI(); myGUI.setVisible(true); } public LibraryGUI() { // set GUI properties super("Library Check Out System"); setSize(400, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // create our books books = new Book2[3]; // create book instances for (int i = 0; i < 3; i++) books[i] = new Book2(); 28 LibraryGUI code // set info for books books[0].setBook("Java in Easy Steps", "Mike McGrath", Book2.PAPERBACK, "Barnes & Noble Books", "Easily learn how to program in Java.", 2004); books[1].setBook("Gone With the Wind", "Margaret Mitchell", Book2.HARDCOVER, "Scribner", "A classic love story.", 1936); books[2].setBook("Rainbow Six", "Tom Clancy", Book2.PAPERBACK, "Putnam", "Action-packed counter-terrorism thriller.",1998); currentBook = 0; // create our GUI components // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); 29 LibraryGUI code // book information panel bookInfoPanel = new JPanel(); titleLabel = new JLabel("Title: "); titleField = new JTextField(books[currentBook].getTitle(), 21); titleField.setEnabled(false); authorLabel = new JLabel("Author: "); authorField = new JTextField(books[currentBook].getAuthor(), 21); publisherLabel = new JLabel("Publisher: "); publisherField = new JTextField(books[currentBook].getPublisher(), 21); copyrightLabel = new JLabel("Copyright: "); copyrightField = new JTextField(Integer.toString(books[currentBook].getCopyright()), 21); summaryLabel = new JLabel("Summary: "); summaryArea = new JTextArea(books[currentBook].getSummary(), 5, 20); summaryScroll = new JScrollPane(summaryArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); hardcoverCheckBox = new JCheckBox(Book2.HARDCOVER); 30 LibraryGUI code GridBagLayout bookInfoLayout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); bookInfoPanel.setLayout(bookInfoLayout); constraints.gridx = 0; constraints.gridy = 0; bookInfoPanel.add(titleLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(titleField, constraints); constraints.gridx = 0; constraints.gridy = 1; bookInfoPanel.add(authorLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(authorField, constraints); constraints.gridx = 0; constraints.gridy = 2; bookInfoPanel.add(publisherLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(publisherField, constraints); constraints.gridx = 0; constraints.gridy = 3; 31 LibraryGUI code bookInfoPanel.add(copyrightLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(copyrightField, constraints); constraints.gridx = 0; constraints.gridy = 4; bookInfoPanel.add(summaryLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(summaryScroll, constraints); constraints.gridx = 0; constraints.gridy = 5; bookInfoPanel.add(hardcoverCheckBox, constraints); // check in and out panel checkInOutPanel = new JPanel(); checkGroup = new ButtonGroup(); checkedInButton = new JRadioButton("Checked In"); checkedOutButton = new JRadioButton("Checked Out"); checkGroup.add(checkedInButton); checkGroup.add(checkedOutButton); checkedInButton.setSelected(true); checkInOutPanel.add(checkedInButton); checkInOutPanel.add(checkedOutButton); 32 LibraryGUI code // create content container and set layout BorderLayout layout = new BorderLayout(); Container window = getContentPane(); window.setLayout(layout); window.add(selectPanel, BorderLayout.NORTH); window.add(bookInfoPanel, BorderLayout.CENTER); window.add(checkInOutPanel, BorderLayout.SOUTH); // set listeners for GUI components selectBookBox.addItemListener(this); titleField.addKeyListener(this); authorField.addKeyListener(this); publisherField.addKeyListener(this); copyrightField.addKeyListener(this); summaryArea.addKeyListener(this); hardcoverCheckBox.addItemListener(this); checkedInButton.addItemListener(this); checkedOutButton.addItemListener(this); } 33 LibraryGUI code // item listener events public void itemStateChanged(ItemEvent e) { if (e.getSource() == selectBookBox) { currentBook = selectBookBox.getSelectedIndex(); titleField.setText(books[currentBook].getTitle()); authorField.setText(books[currentBook].getAuthor()); publisherField.setText(books[currentBook].getPublisher()); copyrightField.setText(Integer.toString( books[currentBook].getCopyright())); summaryArea.setText(books[currentBook].getSummary()); if (books[currentBook].getType() == Book2.HARDCOVER) hardcoverCheckBox.setSelected(true); else hardcoverCheckBox.setSelected(false); if (books[currentBook].getCheckedOut() == true) checkedOutButton.setSelected(true); else checkedInButton.setSelected(true); } 34 LibraryGUI code else if (e.getSource() == hardcoverCheckBox) { if (e.getStateChange() == ItemEvent.SELECTED) books[currentBook].setType(Book2.HARDCOVER); else books[currentBook].setType(Book2.PAPERBACK); } else if (e.getSource() == checkedInButton) books[currentBook].checkIn(); else if (e.getSource() == checkedOutButton) books[currentBook].checkOut(); } // key listener events public void keyPressed(KeyEvent e) {} 35 LibraryGUI code public void keyReleased(KeyEvent e) { if (e.getSource() == titleField) books[currentBook].setTitle(titleField.getText()); else if (e.getSource() == authorField) books[currentBook].setAuthor(authorField.getText()); else if (e.getSource() == publisherField) books[currentBook].setPublisher(publisherField.getText()); else if (e.getSource() == copyrightField) { try { books[currentBook].setCopyright( Integer.parseInt(copyrightField.getText())); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, "Copyright must be a numeric year!"); } } else if (e.getSource() == summaryArea) books[currentBook].setSummary(summaryArea.getText()); } 36 LibraryGUI code public void keyTyped(KeyEvent e) {} // window listener events public void windowClosing(WindowEvent e) { System.exit(0); } public void windowActivated(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowDeactivated(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowOpened(WindowEvent e){} } 37 LibraryGUI walkthrough Get the program to compile and run and play around with it for a bit. We will now walk you through the code line-byline and try to explain a little bit more in depth about why we do things the way we do. It may be helpful to keep a copy of the code open in another window as you follow along All of the code in Book2.java should be familiar to you so we will mainly concentrate on LibraryGUI.java 38 LibraryGUI walkthrough import java.awt.*; import java.lang.*; import javax.swing.*; import java.awt.event.*; import statements are used to add classes from the Java API to our program so we can use them. After the import keyword we give it a package name. The asterisk (*) is a shortcut that allows us to import all the classes in the package. 39 LibraryGUI walkthrough import java.awt.*; import java.lang.*; import javax.swing.*; import java.awt.event.*; java.awt (abstract windowing toolkit) contains the different layout classes that we use (GridLayout, BorderLayout, etc) and Container classes java.lang contains the classes we need for our NumberFormatException javax.swing contains the classes that are used for GUI components (JButton, JLabel, JFrame, etc) java.awt.event contains classes we need for our listeners 40 LibraryGUI walkthrough public class LibraryGUI extends JFrame implements KeyListener, ItemListener, WindowListener { Next we have our class header. In this header we extends JFrame – this means that our LibraryGUI is a subclass of JFrame and inherits its members (like setSize(), setVisible(), etc). implements KeyListener, ItemListener, WindowListener – these are the interfaces that we implement. By implementing these interfaces we are assuring the Java compiler that our class will contain the methods needed to handle these events (like itemStateChanged(), keyPressed(), windowClosing(), etc). 41 LibraryGUI walkthrough // declare GUI components private JPanel selectPanel; private JLabel selectBookLabel; private JComboBox selectBookBox; ... Now we declare all of the components we will need to construct our GUI. Remember that declaring components does not actually create them. They are created when you instantiate them (i.e. call the component’s constructor) with the new operator 42 LibraryGUI walkthrough // declare our book array private Book2[] books; // variable used to keep track of the current book private int currentBook; Here we declare an array to hold our books. We also created an int to keep track of the current index in that array. 43 LibraryGUI walkthrough // main method - simply constructs a Library GUI public static void main(String args[]) { LibraryGUI myGUI = new LibraryGUI(); myGUI.setVisible(true); } Our main() method simply constructs a LibraryGUI object and then calls the setVisible() method (which was inherited from JFrame) so the GUI is displayed to the screen. 44 LibraryGUI walkthrough public LibraryGUI() { // set GUI properties super("Library Check Out System"); setSize(400, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Next we enter our constructor. The first thing we do is call super() which is a special method that calls the superclass’ constructor (in our case, JFrame’s constructor). If we look up JFrame’s constructor in the API specification we see it takes a String that is used to set the title of our window We follow that up with a few more method calls to methods we inherited from JFrame. One sets the size of our window. The other specifies what the program should do if the user closes the window. 45 LibraryGUI walkthrough // create our books books = new Book2[3]; // create book instances for (int i = 0; i < 3; i++) books[i] = new Book2(); Next we create our book array. However, just because we created the array does not mean we created instances for each book in the array (a common mistake by many programmers) To actually create a Book2 instance for each book in our array, we must use a loop. If this step is skipped you may find yourself getting a NullPointerException! 46 LibraryGUI walkthrough // set info for books books[0].setBook("Java in Easy Steps", "Mike McGrath", Book2.PAPERBACK, "Barnes & Noble Books", "Easily learn how to program in Java.", 2004); books[1].setBook("Gone With the Wind", "Margaret Mitchell", Book2.HARDCOVER, "Scribner", "A classic love story.", 1936); books[2].setBook("Rainbow Six", "Tom Clancy", Book2.PAPERBACK, "Putnam", "Action-packed counter-terrorism thriller.", 1998); currentBook = 0; Now that we have created a Book2 instance for each book in our array, we can now set the information for the book by calling the setBook() method that we wrote in our Book2 class. We will also go ahead and initialize our index currentBook to zero (the first book in the array). 47 LibraryGUI walkthrough // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); The next part of our process is to create the GUI component that we declared earlier. We start by declaring a JPanel called selectPanel. 48 LibraryGUI walkthrough // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); JPanels are similar to JFrames except they do not contain a window with a title bar. Instead they provide us a way to divide our components into different groups (kind of like a sub-container). Dividing up components and adding them to panels makes it easier for us to display them in a desirable way because we can apply a separate layout to each panel (and then apply a layout across all our panels to create our final interface). 49 LibraryGUI walkthrough // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); If we do not specify a layout for the panel then it will default to a flow layout. After we create our panel, we create the components that we want to add to that panel, in this case a label and a combo box 50 LibraryGUI walkthrough // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); JLabel’s constructor is called with a String argument which is used to set the text of the label. We then call the default constructor for JComboBox. 51 LibraryGUI walkthrough // select panel selectPanel = new JPanel(); selectBookLabel = new JLabel("Select Book: "); selectBookBox = new JComboBox(); for (int i = 0; i < 3; i++) selectBookBox.addItem(books[i].getTitle()); selectPanel.add(selectBookLabel); selectPanel.add(selectBookBox); After that, we call the addItem() method for our JComboBox in a for loop. This loop is looping through our book array and adding the title of each book to the combo box. Remember we must call getTitle() because it is the public method that accesses the private member variable title in our book Finally, we add these new components to our panel. 52 LibraryGUI walkthrough // book information panel bookInfoPanel = new JPanel(); titleLabel = new JLabel("Title: "); titleField = new JTextField(books[currentBook].getTitle(), 21); titleField.setEnabled(false); ... Next we begin work on our bookInfoPanel which consists of various label and fields used to display the information about our book. Notice when we create a JTextField (like titleField) we call the constructor with two arguments: a String for the initial contents of the box and a length for the box. In this case, we initialize the text to display the title of our first book and give the box a length of 21. 53 LibraryGUI walkthrough // book information panel bookInfoPanel = new JPanel(); titleLabel = new JLabel("Title: "); titleField = new JTextField(books[currentBook].getTitle(), 21); titleField.setEnabled(false); ... In addition, we also call the setEnabled() method of titleField. This method allows us to enable and disable components. By disabling the component we prevent user interaction with it. In this example, we don’t ever want the user to change the title of our book so we disable the field. 54 LibraryGUI walkthrough ... summaryLabel = new JLabel("Summary: "); summaryArea = new JTextArea(books[currentBook].getSummary(), 5, 20); summaryScroll = new JScrollPane(summaryArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); ... We continue to create a series of labels and textfields until we get to summaryArea which is a JTextArea. We use a three-argument constructor for JTextArea that takes a String for initial text, an int for height, and an int for width. 55 LibraryGUI walkthrough ... summaryLabel = new JLabel("Summary: "); summaryArea = new JTextArea(books[currentBook].getSummary(), 5, 20); summaryScroll = new JScrollPane(summaryArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); ... Since our text may extend past the extents of the text area, we decide to put it in a scroll pane We construct our JScrollPane by calling a constructor that takes the component we want to add scrolling to, followed by two constants that determine how vertical and horizontal scrollbars need to be displayed. For a list of constants you could provide to this constructor, see page 111 of your book or consult the API specification for JScrollPane 56 LibraryGUI walkthrough ... hardcoverCheckBox = new JCheckBox(Book2.HARDCOVER); ... The final component we create that will be added to our book information panel is a check box that will be checked when the book is a hardcover book. To create a JCheckBox we call a constructor that takes a String to specify the text for the check box. In this case we pass it Book2.HARDCOVER which was a String constant we specified in our class. 57 LibraryGUI walkthrough GridBagLayout bookInfoLayout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); bookInfoPanel.setLayout(bookInfoLayout); constraints.gridx = 0; constraints.gridy = 0; bookInfoPanel.add(titleLabel, constraints); Next we create a layout for our book information panel. We decide to use GridBagLayout, which is a layout much like GridLayout but provides us with more flexibility and functionality. In addition to creating the layout, we must also create GridBagConstraints which will be used to tell the GridBagLayout how to layout our components. 58 LibraryGUI walkthrough GridBagLayout bookInfoLayout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); bookInfoPanel.setLayout(bookInfoLayout); constraints.gridx = 0; constraints.gridy = 0; bookInfoPanel.add(titleLabel, constraints); We use our constraints mainly to specify a specific cell of our grid (using gridx and gridy). There are other constraints you can set like gridwidth and gridheight. You can consult the API specification for more constraints. When we add a component to our container using a GridBagLayout, we must call our add() method with 2 arguments: the component to add and the name of our constraints. Since we are using the same constraints each time we add a component, we must modify the constraint values between each add() call. 59 LibraryGUI walkthrough ... constraints.gridx = 0; constraints.gridy = 4; bookInfoPanel.add(summaryLabel, constraints); constraints.gridx = 1; bookInfoPanel.add(summaryScroll, constraints); ... A final thing to note about our book information panel is that we add summaryScroll to our panel, not summaryArea. Remember that we added summaryArea to summaryScroll (by specifying it as the first agrument in summaryScroll’s constructor), therefore all we need to add summaryScroll to our panel. 60 LibraryGUI walkthrough // check in and out panel checkInOutPanel = new JPanel(); checkGroup = new ButtonGroup(); checkedInButton = new JRadioButton("Checked In"); checkedOutButton = new JRadioButton("Checked Out"); checkGroup.add(checkedInButton); checkGroup.add(checkedOutButton); checkedInButton.setSelected(true); checkInOutPanel.add(checkedInButton); checkInOutPanel.add(checkedOutButton); Our final sub-container that we created is the checkInOutPanel. For this panel we want to add two radio buttons. Before creating these buttons though, we create a ButtonGroup. 61 LibraryGUI walkthrough // check in and out panel checkInOutPanel = new JPanel(); checkGroup = new ButtonGroup(); checkedInButton = new JRadioButton("Checked In"); checkedOutButton = new JRadioButton("Checked Out"); checkGroup.add(checkedInButton); checkGroup.add(checkedOutButton); checkedInButton.setSelected(true); checkInOutPanel.add(checkedInButton); checkInOutPanel.add(checkedOutButton); We then create our JRadioButtons with a constructor that takes a single String to specify the button’s text, and we then add it to the ButtonGroup using the add() method. By adding these buttons to the same group, we will only allow one button to be selected at a time (since we don’t want a book to be checked in AND checked out at the same time!) 62 LibraryGUI walkthrough // check in and out panel checkInOutPanel = new JPanel(); checkGroup = new ButtonGroup(); checkedInButton = new JRadioButton("Checked In"); checkedOutButton = new JRadioButton("Checked Out"); checkGroup.add(checkedInButton); checkGroup.add(checkedOutButton); checkedInButton.setSelected(true); checkInOutPanel.add(checkedInButton); checkInOutPanel.add(checkedOutButton); We call the setSelected() method for checkInButton to select it as the default selection once the GUI is displayed. Finally, we add the radio buttons to our panel. 63 LibraryGUI walkthrough // create content container and set layout BorderLayout layout = new BorderLayout(); Container window = getContentPane(); window.setLayout(layout); window.add(selectPanel, BorderLayout.NORTH); window.add(bookInfoPanel, BorderLayout.CENTER); window.add(checkInOutPanel, BorderLayout.SOUTH); Now that we have added all our components into 3 panels (selectPanel, bookInfoPanel, checkInOutPanel) the task now is to add these panels to our main container – our window We decide to use a BorderLayout for this. A BorderLayout can be used to arrange components into 5 different sections: north, south, east, west, or center. 64 LibraryGUI walkthrough // create content container and set layout BorderLayout layout = new BorderLayout(); Container window = getContentPane(); window.setLayout(layout); window.add(selectPanel, BorderLayout.NORTH); window.add(bookInfoPanel, BorderLayout.CENTER); window.add(checkInOutPanel, BorderLayout.SOUTH); We first create our layout and then create our Container, named window. Notice we set our window equal to the result of the getContentPane() method (a method inherited from JFrame). This method returns the Container for our main frame. 65 LibraryGUI walkthrough // create content container and set layout BorderLayout layout = new BorderLayout(); Container window = getContentPane(); window.setLayout(layout); window.add(selectPanel, BorderLayout.NORTH); window.add(bookInfoPanel, BorderLayout.CENTER); window.add(checkInOutPanel, BorderLayout.SOUTH); After setting the layout, we then add the 3 panels to our window with the add() method. Like GridBagLayout, BorderLayout’s add() method requires two arguments: the component and a constant specifying which area to place the component. 66 LibraryGUI layout selectPanel located at NORTH position in our BorderLayout bookInfoPanel with internal GridBagLayout located at CENTER position in our BorderLayout checkInOutPanel located at SOUTH position in our BorderLayout Keep in mind that understanding and using layouts is typically the most challenging aspect of GUI programming. Here is a visual demonstrating how we used layouts to achieve the look of our GUI. 67 LibraryGUI listeners // set listeners for GUI components selectBookBox.addItemListener(this); titleField.addKeyListener(this); authorField.addKeyListener(this); publisherField.addKeyListener(this); copyrightField.addKeyListener(this); summaryArea.addKeyListener(this); hardcoverCheckBox.addItemListener(this); checkedInButton.addItemListener(this); checkedOutButton.addItemListener(this); } The final step in our constructor is to add listeners to our components. We will add KeyListeners to all of our textfields and ItemListeners to our radio buttons, combo boxes, and check boxes. 68 LibraryGUI listeners All that’s left for our program from this point is to write the methods that will be used to handle the listener events. In previous programs we used ActionListeners which require an actionPerformed() method. Even though we aren’t using ActionListeners for this GUI, the same approach is used for ItemListener and KeyListener. ItemListener requires an itemStateChanged() method while KeyListener requires a keyPressed(), keyReleased(), and keyTyped() method. 69 LibraryGUI listeners // item listener events public void itemStateChanged(ItemEvent e) { if (e.getSource() == selectBookBox) ... else if (e.getSource() == hardcoverCheckBox) ... else if (e.getSource() == checkedInButton) ... else if (e.getSource() == checkedOutButton) ... } We will start by looking at the itemStateChanged() method. The thing we should realize is that we have 4 different components that could create an ItemEvent. Therefore, the first thing we realize we need to do is to construct a series of if/else if statements to determine which component created the event We can get this component by calling the ItemEvent’s getSource() method. 70 LibraryGUI listeners if (e.getSource () == selectBookBox) (e.getSource() selectBookBox) { currentBook = selectBookBox.getSelectedIndex(); selectBookBox.getSelectedIndex(); titleField.setText(books[currentBook].getTitle()); titleField.setText(books[currentBook].getTitle()); authorField.setText(books[currentBook].getAuthor()); authorField.setText(books[currentBook].getAuthor()); publisherField.setText(books[currentBook].getPublisher()); publisherField.setText(books[currentBook].getPublisher()); copyrightField.setText(Integer.toString(books[currentBook].getCopyright ())); copyrightField.setText(Integer.toString(books[currentBook].getCopyright())); summaryArea.setText(books[currentBook].getSummary()); summaryArea.setText(books[currentBook].getSummary()); if (books[currentBook].getType () == Book2.HARDCOVER) (books[currentBook].getType() hardcoverCheckBox.setSelected(true); hardcoverCheckBox.setSelected(true); else hardcoverCheckBox.setSelected(false); hardcoverCheckBox.setSelected(false); if (books[currentBook].getCheckedOut () == true) (books[currentBook].getCheckedOut() checkedOutButton.setSelected(true); checkedOutButton.setSelected(true); else checkedInButton.setSelected(true); checkedInButton.setSelected(true); } The first case occurs when the combo box selectBookBox causes the event. The first thing we do in this case is determine which book was selected by using the getSelectedIndex() method. Alternatively, we could have used getItem() to return the actual String, but the index is better for us in this case because we can use it as the index for our book array. 71 LibraryGUI listeners if (e.getSource () == selectBookBox) (e.getSource() selectBookBox) { currentBook = selectBookBox.getSelectedIndex(); selectBookBox.getSelectedIndex(); titleField.setText(books[currentBook].getTitle()); titleField.setText(books[currentBook].getTitle()); authorField.setText(books[currentBook].getAuthor()); authorField.setText(books[currentBook].getAuthor()); publisherField.setText(books[currentBook].getPublisher()); publisherField.setText(books[currentBook].getPublisher()); copyrightField.setText(Integer.toString(books[currentBook].getCopyright ())); copyrightField.setText(Integer.toString(books[currentBook].getCopyright())); summaryArea.setText(books[currentBook].getSummary()); summaryArea.setText(books[currentBook].getSummary()); if (books[currentBook].getType () == Book2.HARDCOVER) (books[currentBook].getType() hardcoverCheckBox.setSelected(true); hardcoverCheckBox.setSelected(true); else hardcoverCheckBox.setSelected(false); hardcoverCheckBox.setSelected(false); if (books[currentBook].getCheckedOut () == true) (books[currentBook].getCheckedOut() checkedOutButton.setSelected(true); checkedOutButton.setSelected(true); else checkedInButton.setSelected(true); checkedInButton.setSelected(true); } We then call a series of setText() methods to update the text fields with the information of the selected book. Finally, we set our radio buttons and check boxes with the setSelected() method depending on the values of the current book 72 LibraryGUI listeners else if (e.getSource() == hardcoverCheckBox) { if (e.getStateChange() == ItemEvent.SELECTED) books[currentBook].setType(Book2.HARDCOVER); else books[currentBook].setType(Book2.PAPERBACK); } The next case occurs if the hardcoverCheckBox is selected. In this case, we first check to see if the check box was selected or de-selected. We use the getStateChange() method to determine this. If it was selected then we change the type for the current book to Hardcover, otherwise, we change it to Paperback. 73 LibraryGUI listeners else if (e.getSource() == checkedInButton) books[currentBook].checkIn(); else if (e.getSource() == checkedOutButton) books[currentBook].checkOut(); } Finally, if the checkInButton radio button is selected then we call the checkIn() method for the current book. Likewise, we call the checkOut() method if the checkOutButton is selected. 74 LibraryGUI listeners The next listener we need to take care of the KeyListener. Since we added KeyListeners to our textfields, we need to determine which of the 3 KeyListener methods is best to use in the event of a textfield change. keyPressed() is called when a key is pressed down keyReleased() is called when a key is de-pressed and released keyTyped() is called after the key has been released We decide keyReleased() is the best time to update our textfields so let’s take a look at that method. 75 LibraryGUI listeners public void keyReleased(KeyEvent e) { if (e.getSource() == titleField) books[currentBook].setTitle(titleField.getText()); ... Just like itemStateChanged(), we first need to determine which textfield caused the event so we use an if/else if structure If the titleField is changed then we update the title (using our setTitle() method we wrote in Book2) for our current book. We can retrieve the new text from our textbox by using the getText() method. 76 LibraryGUI listeners else if (e.getSource() == copyrightField) { try { books[currentBook].setCopyright( Integer.parseInt(copyrightField.getText())); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null, "Copyright must be a numeric year!"); } } All the other textfields essentially perform the same operations if they cause the event. The only one that differs slightly is copyrightField, which we put in a try/catch block that will catch an exception when the user attempts to enter a non-numeric value into the copyrightField. 77 LibraryGUI listeners // window listener events public void windowClosing(WindowEvent e) { System.exit(0); } public void windowActivated(WindowEvent e){} public void windowClosed(WindowEvent e){} public void windowDeactivated(WindowEvent e){} public void windowIconified(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowOpened(WindowEvent e){} } Finally, we end our program by writing the methods required for WindowListener. The only method we are concerned with is the windowClosing() method. However, we still need to write the other empty methods in order to satisfy the listener. 78 Drill 12 Recall back to a drill from Lesson 10 where you wrote a simple Payroll system that used Employee objects. First, extend your Employee object to also contain members that hold an employeeID number and a notes variable that can be used to leave notes and special requests about the employee. Then, create a GUI for your payroll system. You can use any combination of layouts that you desire (it should look nice though - be creative!). Your GUI should allow a user to select an employee from a list of employees and update information on that employee (name, salary, notes, number of years employed). They should also be able to change an employee’s status (active, terminated, on leave - inactive). The user should NOT be able to change the employee’s ID and should NOT be allowed to enter anything other than a numeric (float) salary. *BONUS* - try to use a JSlider for the number of years employed. You can find information on how to use a JSlider on page 126 of your book OR you could consult the Java API specification (which would be good practice :) As programmers, there are many times when we must teach ourselves how to use certain components that we may not have seen or used before – this is an opportunity for you to learn to develop this important skill! 79