Download presentation
Presentation is loading. Please wait.
Published byAnnabelle Gardner Modified over 8 years ago
1
1 Object-Oriented Programming (Java), Unit 17 Kirk Scott
2
2 Components, Containers, and Painting 17.1 Components and Containers 17.2 Painting 17.3 Dialog Boxes and String Output to a Panel
3
3 17.1 Components and Containers
4
4 17.1.1 System Classes for Components and Containers Some of the classes in the API for creating graphical user interfaces:
5
5
6
6 17.1.2 Top Level Containers The JFrame, JDialog, and JApplet classes are known as top level containers. They are the basic building blocks for graphical applications. All of the components of a graphical application or applet have to be contained in a top level container.
7
For the graphical applications of this and the following unit, the top level container will be the JFrame. The JPanel class will be used as a sub- container for organizing the elements in a frame. If you have not encountered applets before, the use of the JApplet class will be introduced in Unit 21. 7
8
8 17.1.3 The Structure of Top Level Containers A top level container such as a JFrame has a root pane. The root pane manages a layered pane. The layered pane contains a content pane and the menu bar, if there is one. The layered pane has functionality associated with keeping graphical components in order when painting them.
9
The root pane also manages a glass pane. The glass pane “covers” the whole top level container. It has functionality associated with receiving mouse clicks and painting over multiple components. 9
10
Knowing all of these relationships isn’t critically important. However, having a rough idea of them may help you visualize what’s involved when you write graphical code A diagram of these relationships is shown on the following overhead. 10
11
11 Here is a diagram of this structure:
12
12 17.1.4 Simple Graphical Applications and Containment Simple graphical applications make use of a JFrame and its content pane: Each top level container has a content pane which is the container for the visible components. Calling getContentPane() on a frame returns a reference to the pane. Every visible component of an application has to be in a containment hierarchy descending from the content pane.
13
The JFrame of an application will contain a content pane. The content pane will then contain one or more instances of JPanel. Then the rest of the containment hierarchy descends from those panels A component is put into a container by calling the add() method on the container and passing the component as a parameter. 13
14
Menus are also important parts of many graphical applications. They are added to the JFrame object of the application, not to the content pane. 14
15
15 17.1.5 The Model-View-Controller Design Pattern A more advanced course, like CS 304, would cover the topic of design patterns in detail. The design pattern most closely associated with graphical user applications is the model-view-controller pattern. This pattern relates to how the functionality of an application is divided up and implemented in classes.
16
The state of an object is contained in its instance variables. This is the model. The representation of an object on the screen is its view. An object may be enabled to respond to user actions like mouse clicks. This functionality is the controller. 16
17
The idea is that a general, flexible implementation of an application will separate the implementation of these three components of the application. The techniques that will be given do not make full-fledged use of all model-view- controller characteristics, but they are a start on the way. 17
18
18 17.2 Painting
19
19 17.2.1 System Painting Painting refers to the generation of graphical output by an application and its presentation on the screen. As you will soon see, applications can do painting explicitly. Graphical applications rely on characteristics of painting that the system supplies.
20
System triggered painting occurs under these three conditions: When the component is first made visible on the screen. When the component is resized. When a component which was wholly or partly covered by another component is uncovered and needs to be repainted. For system supplied components, painting is largely taken care of. 20
21
21 17.2.2 Painting Methods The JComponent class has several painting methods, which include paint() and paintComponent(). Beginning with the example programs of this unit, the JPanel class will be extended. Graphical applications will be implemented by overriding the paintComponent() method in this subclass. This is how and where applications will explicitly be coded to do their own painting.
22
Practical considerations when overriding the paintComponent() method: paintComponent() is defined to take a graphics parameter. The parameter is declared Graphics g. Cast it parameter to Graphics2D. At the top of the overridden method call super.paintComponent(g2). At the end of paintComponent() add the application specific code. 22
23
Casting to Graphics2D is just housekeeping. This is the result of historical changes in Java. Older versions of Java didn’t have a Graphics2D class, so applications used Graphics. The parameter was left Graphics for backwards compatibility reasons Newer code should use Graphics2D, but has to cast to agree with the old parameter type. 23
24
Calling super.paintComponent() is also a form of housekeeping, but this is something deeper. You have seen calls to super before. The idea is that the inherited version of the method, supplied by the system, includes a bunch of useful functionality that you don’t want to have to re-code. You want all of that existing functionality, and to it you want to add those painting features which are specific to your application. 24
25
25 17.2.3 The Callback Mechanism A callback sequence turns out to be a recurring way of doing things in Java. Painting is based on a callback mechanism. This is probably your first exposure to the callback mechanism.
26
The fundamental idea is this: In your own code, you implement a required method. However, you never call that method in your code. You call another, inherited method. The inherited method contains a call to the method you implemented. 26
27
The callback sequence doesn’t involve a call to super, but it has some similarities with that approach. The idea is that the inherited method that you call has some useful functionality in it that you would like to use without having to re-code it. Then the application specific functionality appears in the method that you implemented which that inherited method calls. 27
28
Your application will contain a panel class. Your panel class will extend the JPanel class. In your class, you will override the paintComponent() method. 28
29
In particular, when implementing painting in your application, you have to implement the paintComponent() method. However, painting isn’t accomplished by direct calls to paintComponent(). A call is made to repaint() on the object in question. 29
30
repaint() makes a call to update(). This method takes care of housekeeping. repaint() makes a call to the paintComponent() method of the object in question. paintComponent() causes the whole panel to be repainted—doing what was specified in the paintComponent() method. 30
31
The callback sequence is initiated when the call to repaint() is made. The reason for calling repaint() is that the state of some object in the program has been changed or update. In other words, the model has been change. When the model is changed, the visual representation of the model needs to be updated to reflect that change. The sequence diagram given on the following overhead outlines the callback sequence for painting: 31
32
32
33
33 In summary, these are the things that have to be done to support painting in a simple graphical application: Implement a paintComponent() method in a special purpose subclass of the JPanel class. Cast the graphics parameter in paintComponent() to Graphics2D and include a call to super.paintComponent(). Put in the painting code appropriate to the application. Place calls to repaint() in the application at points where the state of the application has changed.
34
34 17.3 Dialog Boxes and String Output to a Panel The rest of this unit consists of three example programs, Echo1.java through Echo3.java. The purpose of the examples is to show how to move an application from non-graphical text I/O to graphical text I/O. The idea is this: Up to this point, you have done I/O through MyTerminalIO or the Command Prompt (the black screen of death) Step-by-step, graphical features are introduced in Echo1 through Echo3.
35
The information on the examples is organized as follows: A brief introductory statement summarizing what the application does. Screen shots illustrating what is seen when the application runs. UML diagrams showing the components and structure of the application. Remarks on the contents of the code. The Java code for the application, without comments. 35
36
36 Echo1 This program shows the use of the system supplied input dialog box. Output is done through a MyTerminalIO object.
37
37
38
38 Only one object is created in the application, myterminal:
39
39 When using the dialog boxes, no object is created. A static method is called on the system supplied JOptionPane class. The showInputDialog() method always brings in a String, so if a numeric type is expected it is necessary to parse the String. The call to exit(0) is not related to the use of the dialog boxes. It is included to illustrate coding an explicit end to a program.
40
40 import javax.swing.*; public class Echo1 { public static void main(String[] args) { String inputString; int inputInt; double inputDouble; double result; MyTerminalIO myterminal = new MyTerminalIO(); inputString = JOptionPane.showInputDialog("Enter a string."); myterminal.println("Here is your string: " + inputString); inputString = JOptionPane.showInputDialog("This time enter an integer."); inputInt = Integer.parseInt(inputString); inputString = JOptionPane.showInputDialog("This time enter a double."); inputDouble = Double.parseDouble(inputString); result = inputInt + inputDouble; myterminal.println("Here is the sum of the values: " + result); inputString = JOptionPane.showInputDialog("Enter anything to quit."); System.exit(0); }
41
41 Echo2 This program shows how to do hardcoded String output into a panel belonging to a frame in an application. It does not literally echo.
42
42 The application has a special purpose frame, Echo2Frame. The frame has a content pane. The application also has a special purpose panel, Echo2Panel, which is a subclass of the JPanel class. An instance of this is added to the frame’s content pane.
43
Note the following, which will continue throughout all of the examples in this course: In the UML diagram, the content pane of the panel is labeled “ContentPane”. This is incorrect. There is no ContentPane class. 43
44
The content pane is an instance of the Container class. It is simply a convenient reminder to always label the diagram with what role the instance of the container class plays in the application. 44
45
45
46
46 Here is an outline of the code: In the main() method: An instance of the frame class is constructed. A method is called which sets the default close operation so the application will exit when its frame is closed. The visible property of the frame is set to true.
47
47 In the Echo2Frame class: The frame is given a title. The frame is given a size. An instance of the panel class is constructed. A reference to the content pane of the frame is obtained. The panel is added to the content pane.
48
48 In the Echo2Panel class: The paintComponent() method has a graphics parameter, and this parameter is cast to Graphics2D. A call is made to super.paintComponent(). There is one line of code which calls the graphics method drawstring(), which places a string in the panel, specifying its location by the x and y coordinates of its basepoint. Because the application simply does one thing, there is no chance for its state to change, and there is no call to repaint() in the code.
49
49 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Echo2 { public static void main(String[] args) { Echo2Frame myframe = new Echo2Frame(); myframe.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); myframe.setVisible(true); }
50
50 class Echo2Frame extends JFrame { public Echo2Frame() { setTitle("Echo2 Frame"); setSize(500, 500); Echo2Panel mypanel = new Echo2Panel(); Container frameContentPane = getContentPane(); frameContentPane.add(mypanel); }
51
51 class Echo2Panel extends JPanel { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; super.paintComponent(g2); g2.drawString("This is hardcoded, not echoed.", 140, 240); }
52
52 Echo3 This is a genuine echoing program. It combines the dialog box input of Echo1 with the panel output of Echo2. The user can repeatedly enter strings into the dialog box as shown, and they are echoed in the panel.
53
53
54
54 The UML diagram shows that the panel has a graphics object in paintComponent(). It also shows that the panel class now has a String instance variable. This is the object which holds the input and allows it to be transferred to output. For the sake of completeness, attributes and operations are shown in the diagram. Remember that in general you do not have to show attributes and operations in your diagrams.
55
55
56
56 The program loops in order to continue accepting input. In the main() method the input string is taken in. The setPanelString() method is called on the frame to pass the string to the panel. Inside the setPanelString() method the method setStringToShow() is called on the panel.
57
setStringToShow() does two things: It completes the change of the application’s state by assigning the string to the panel's instance variable. It calls repaint(). The callback mechanism causes paintComponent() to be called. paintComponent() contains a call to drawString(), which puts the output in the panel. 57
58
58 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Echo3 { public static void main(String[] args) { String localString = "go"; Echo3Frame myframe = new Echo3Frame(); myframe.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); myframe.setVisible(true); while(!(localString.equals("quit"))) { localString = OptionPane.showInputDialog ("Enter a string. Enter 'quit' to stop."); myframe.setPanelString(localString); }
59
59 class Echo3Frame extends JFrame { private Echo3Panel mypanel; public Echo3Frame() { setTitle("Echo3 Frame"); setSize(500, 500); mypanel = new Echo3Panel(); Container frameContentPane = getContentPane(); frameContentPane.add(mypanel); } public void setPanelString(String stringIn) { mypanel.setStringToShow(stringIn); }
60
60 class Echo3Panel extends JPanel { private String stringToShow = “”; public void setStringToShow(String stringIn) { stringToShow = stringIn; repaint(); } public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; super.paintComponent(g2); g2.drawString(stringToShow, 140, 240); }
61
61 WariV23 The code for WariV23 is given next. This version of Wari incorporates the graphical elements of Echo1 through Echo3. In other words, WariV23 has graphical I/O integrated into it. After the code the assignment will be given. In short, the assignment is to do the same thing for Togiz Kumalak.
62
62
63
63 import java.awt.Container; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.Ellipse2D; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.JOptionPane;
64
64 /** This version of Wari goes up through the features illustrated in Echo1 to Echo3. */ public class WariV23 { public static void main(String[] args) { String inputString = "go"; int playCup = 1; WariFrame myFrame = new WariFrame(); myFrame.setTitle("Wari, Version 2.3"); myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); myFrame.setVisible(true); while(!(inputString.equals("quit"))) { inputString = JOptionPane.showInputDialog("Please enter the number, from 1 to 6,\nof the cup you want to play: "); playCup = Integer.parseInt(inputString); myFrame.playGame(playCup); inputString = JOptionPane.showInputDialog("Enter a string. Enter 'quit' to stop."); }
65
65 class WariFrame extends JFrame { private WariPanel myPanel; private final int FRAMEW = 500; private final int FRAMEH = 500; public WariFrame() { setSize(FRAMEW, FRAMEH); myPanel = new WariPanel(); Container contentPane = getContentPane(); contentPane.add(myPanel, "Center"); } public void playGame(int whichCup) { myPanel.setWhichCup(whichCup); myPanel.playGame(); }
66
66 class WariPanel extends JPanel { private BoardV23 playBoard; private int playTurn; private int whichCupInPanel; public WariPanel() { super(); playTurn = 1; playBoard = new BoardV23(); } public void setWhichCup(int whichCupFromFrame) { whichCupInPanel = whichCupFromFrame; } public void playGame() { playBoard.moveBoard(playTurn, whichCupInPanel); if(playTurn == 1) playTurn = 2; else playTurn = 1; repaint(); }
67
67 public void paintComponent(Graphics g) { BoardLineV23 line1 = new BoardLineV23(); BoardLineV23 line2 = new BoardLineV23(); BoardLineV23 line3 = new BoardLineV23(); BoardLineV23 line4 = new BoardLineV23(); BoardLineV23 line5 = new BoardLineV23(); super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; String whoseTurnString = "It's " + playTurn + "'s turn. Enter the cup number in the text box."; g2.drawString(whoseTurnString, 10, 150); playBoard.showBoard(line1, line2, line3, line4, line5); g2.drawString(line1.getLine(), 10, 200); g2.drawString(line2.getLine(), 10, 230); g2.drawString(line3.getLine(), 10, 250); g2.drawString(line4.getLine(), 10, 270); g2.drawString(line5.getLine(), 10, 300); }
68
68 /** This class implements the game board for playing wari. */ public class BoardV23 { private CupV23[][] gameBoard = new CupV23[3][7]; private CupV23[] captured = new CupV23[3];
69
69 /** This constructor sets up the cups in the board, initializing the number of seeds in each to 4, and correctly labelling them as belonging to player 1 or player 2. It also creates the captured cups, initializing the number of seeds in each to 0 and labelling them as belonging to player 1 and player 2 respectively. */ public BoardV23() { captured[1] = new CupV23(0, 1); captured[2] = new CupV23(0, 2); gameBoard[1][6] = new CupV23(4, 1); gameBoard[2][6] = new CupV23(4, 2); for(int i = 5; i > 0; i--) { gameBoard[1][i] = new CupV23(4, 1, gameBoard[1][i + 1]); gameBoard[2][i] = new CupV23(4, 2, gameBoard[2][i + 1]); } gameBoard[1][6].setNextCup(gameBoard[2][1]); gameBoard[2][6].setNextCup(gameBoard[1][1]); }
70
70 /** This method is part of the play. It prints out the the game board in a formatted way, showing the number of seeds in each cup. */ public void showBoard(BoardLineV23 bLine1, BoardLineV23 bLine2, BoardLineV23 bLine3, BoardLineV23 bLine4, BoardLineV23 bLine5) { CupV23 tempReference; int tempSeedCount; bLine1.setLine("Player 1, captured " + captured[1].getSeedCount()); for(int i = 1; i <= 6; i++) { tempReference = gameBoard[2][6]; for(int j = 0; j <= 6 - i; j++) { tempReference = tempReference.getNextCup(); } tempSeedCount = tempReference.getSeedCount(); bLine2.setLine(bLine2.getLine() + " " + tempSeedCount); if(tempSeedCount < 10) bLine2.setLine(bLine2.getLine() + " "); if(i < 6) bLine2.setLine(bLine2.getLine() + " |"); }
71
71 bLine3.setLine("-----------------------------"); tempReference = gameBoard[1][6]; for(int i = 1; i <= 6; i++) { tempReference = tempReference.getNextCup(); tempSeedCount = tempReference.getSeedCount(); bLine4.setLine(bLine4.getLine() + " " + tempSeedCount); if(tempSeedCount < 10) bLine4.setLine(bLine4.getLine() + " "); if(i < 6) bLine4.setLine(bLine4.getLine() + " |"); } bLine5.setLine("Player 2, captured " + captured[2].getSeedCount()); }
72
72 /** This method implements the actual playing of a move in wari. @param whoseTurn tells which player's turn it is who is playing. @param whichCup tells which cup the player has chosen to play. */ public void moveBoard(int whoseTurn, int whichCup) { int handfull = gameBoard[whoseTurn][whichCup].removeSeeds(); CupV23 tempReference = gameBoard[whoseTurn][whichCup].getNextCup(); while(handfull != 0) { tempReference.addOneSeed(); handfull--; if(tempReference.getWhoseCup() != whoseTurn) { if(tempReference.getSeedCount() == 2 || tempReference.getSeedCount() == 3) { captured[whoseTurn].addSomeSeeds(tempReference.removeSeeds()); } tempReference = tempReference.getNextCup(); }
73
73 public class BoardLineV23 { private String theLine; public BoardLineV23() { theLine = ""; } public void setLine(String lineIn) { theLine = lineIn; } public String getLine() { return theLine; }
74
74 /** The Cup class is used to create the 12 cups of the wari Board, as well as the two additional cups for keeping a count of the number of seeds captured, one for each player. */ public class CupV23 { private int seedCount; private int whoseCup; private CupV23 nextCup; /** This constructor is used for creating the captured cups. There are no links between these cups. @param seedCountin is an integer that initializes the number of seeds in the cup. @param whoseCupin is an integer that identifies which player the cup belongs to, player 1 or player 2. */ public CupV23(int seedCountin, int whoseCupin) { seedCount = seedCountin; whoseCup = whoseCupin; nextCup = null; }
75
75 /** This constructor is used for creating the 12 cups that are part of the wari Board. @param seedCountin is an integer that initializes the number of seeds in the cup. @param whoseCupin is an integer that identifies which player the cup belongs to, player 1 or player 2. @param nextCupin contains a reference to another cup on the board. Not only are the cups related by their position in an array, for good measure they are linked together in their order of play. */ public CupV23(int seedCountin, int whoseCupin, CupV23 nextCupin) { seedCount = seedCountin; whoseCup = whoseCupin; nextCup = nextCupin; }
76
76 /** This method is an incomplete implementation of the standard toString() method. It is incomplete because only the count of the number of seeds and who the cup belongs to are printed out. No information on the next cup in the board is printed out. @return String is a String containing the count of the number of seeds and a number indicating who the cup belonged to. */ public String toString() { return "Cup[seedCount = " + seedCount + ", whoseCup = " + whoseCup + "]"; }
77
77 /** This method simply returns the count of the number of seeds in the cup. @return this is the count of the seeds. */ public int getSeedCount() { return seedCount; } /** This method adds one to the count of seeds in a cup. This is used as play progresses and seeds are dropped around the board one by one. */ public void addOneSeed() { seedCount++; }
78
78 /** This method adds the amount given as a parameter to the number of seeds in a cup. It is used when a player captures some seeds and they are put into that player's captured cup. @param seedsin is the number of seeds to add to the cup. */ public void addSomeSeeds(int seedsin) { seedCount += seedsin; } /** This method simply returns the integer, 1 or 2, telling which player the cup belongs to. @return the player the cup belongs to. */ public int getWhoseCup() { return whoseCup; }
79
79 /** This method returns a reference to the next cup in the game board. @return the next game cup in the board. */ public CupV23 getNextCup() { return nextCup; } /** This method sets the value of the instance variable that holds the reference to the next cup in the game board. It is called when the Board class constructor is creating the cups and arranging them in an instance of the board. @param nextCupin is the reference to the next cup in the board. */ public void setNextCup(CupV23 nextCupin) { nextCup = nextCupin; }
80
80 /** This method zeros out the count of the number of seeds in a cup and returns that number. It is used in play when a capture occurs. @return the number of seeds that were in the cup. */ public int removeSeeds() { int temp = seedCount; seedCount = 0; return temp; }
81
Java Unit 17 Assignment Grading check-off checklist: This checklist is largely a repetition of the assignment. It is given here because this is the summary, in words, which I refer to when checking off assignments. You should have a version of Togiz Kumalak which compiles and runs. 81
82
1. This version of Togiz Kumalak should take in input through a separate, non- integrated text box. 2. It should display output in an integrated graphical panel. 3. The seed counts should be represented by digits. 4. For full credit, you should also have a UML diagram for your program. 82
83
83 1. Write a version of Togiz Kumalak that includes the graphical features that are illustrated in example programs Echo1.java through Echo3.java. Your application should take input from an input dialog box and produce a Unicode oriented representation of the game board, with numbers for the seed counts in the cups.
84
The presentation of the game board should be similar to its appearance in the non-graphical version you wrote as part of the assignment for Unit 15. The difference is that it no longer uses MyTerminalIO. It takes in input through its own dialog box, and presents the board and its contents in its own graphical frame and panel. Draw a UML diagram for your solution. 84
85
85 You can do this assignment by modifying WariV23. You can also do this assignment by modifying the code you wrote for assignment 15. Your program should play the Togiz Kumalak rules and have the same graphical features that WariV23 has.
86
86 The End
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.