700 likes | 830 Views
Object-Oriented Programming (Java), Unit 26. Kirk Scott. More on Layout. 26.1 Background Information 26.2 Switching from Cups to Registers 26.3 Using Text Fields as Application Components 26.4 Adding Labels and Using the GridLayout.
E N D
Object-Oriented Programming (Java), Unit 26 Kirk Scott
More on Layout • 26.1 Background Information • 26.2 Switching from Cups to Registers • 26.3 Using Text Fields as Application Components • 26.4 Adding Labels and Using the GridLayout
The final project assignment is built on a continuation of Wari. • The example programs in the units starting with this one will be based on something else. • This makes these examples somewhat less helpful than the earlier examples.
Hard as it may be to believe, there is an educational logic to this. • The point is that you will need to figure out how to adapt code from a different problem domain into code that will work for your problem domain. • All software development ultimately stems from inspired code theft…
The examples of the previous unit used simplified cups. • The examples of this unit show how to use text boxes to store certain kinds of information and text areas to store other kinds of information. • The names of the components in this application and the values placed in them are intended to suggest the registers and memory of a simple CPU.
These registers can be adapted to represent the cups of a Wari game. • Keep in mind that the functionality of the game is not in the cup components themselves. • The game functionality is implemented in other classes which make use of these components. • This is what makes it possible for the components to be adapted for use in different applications.
In order to introduce the examples, it is helpful to review what registers and memory are and how they’re used in the simulation of a simple computer chip. • A register is a small block of storage space on a computer chip. • It can be used to hold the value of a single variable or the address of an instruction, for example. • In a register, values are stored in binary form.
In a real chip the registers may be up to 32 or 64 bits long and the bits store the electronic equivalent of binary 1’s and 0’s. • In the example programs in this and the following units the registers will be 8 bits long. • Their contents will be represented by a String of length 8 containing the characters 1 and 0.
A CPU has an assembly language consisting of a set of human-readable mnemonics for the hardware instructions. • It is possible to access the general purpose registers of the chip using assembly language. • Suppose the chip in question has general purpose registers named A through D.
This is an example of the form of an assembly language statement for storing the value 1 in register D: • MOVE D, X01 • The name of the instruction comes first, followed by the destination operand, followed by the source operand. • The X in X01 signifies that the value is given in hexadecimal notation, and the 01 is a two digit hexadecimal number with a decimal value of 1.
Assembly language statements can be translated into machine language statements, which the chip can execute. • The MOVE given above might translate as follows: • 10000101 00000100 00000001 • The first eight bits would be the machine code for the MOVE instruction. • The second eight bits, 00000100, would be the code for the register D. • This value is decimal 4, which would match with D if the registers were numbered 1 through 4. • The last 8 bits, 00000001, is an eight digit binary number with a decimal value of 1.
D 00000001 You can visualize the outcome of the execution of this instruction inside the chip in this way. The value 00000001 is moved to register D.
C 00001010 D 00000001 Suppose that the decimal value 10, binary 00001010, were moved to register C. The results of the two moves together could be visualized as follows:
The instruction set for a chip would also include arithmetic operations like addition and subtraction. • The assembly language for subtracting the contents of register D from the contents of register C might look like this: • SUB C, D
This might translate into machine language as follows: • 10001011 00000011 00000100 • The first eight bits would be the code for the subtraction instruction. • The second 8 bits would be the code for register C. • The third eight bits would be the code for register D. • The contents of register D would be unchanged by the operation • The value in register C, decimal 10, would have 1 subtracted from it.
C 00001001 D 00000001 After execution of the instruction, the decimal value 9, binary 00001001, is in register C. The results can be visualized as shown below:
The example programs of this unit implement 8 bit registers where the bits are represented by a String of 8 characters. • It is possible to move the contents of one register to another. • It will also become possible to move the contents of a register to and from a representation of memory.
MiscRegister • The designation Misc, which will appear in the following examples, is an acronym of the phrase “Minimal instruction set computer” • The examples to come will be based on the idea of registers in a machine • You will have to adapt the register examples to represent cups in your version of Wari/TogizKumalak
In the first example, MiscRegister, registers contain strings of characters representing binary digits. • Action is triggered in the application by clicking a button. • The code implements a swap of register contents, not a jump as in the previous Wari examples.
Because swapping replaces jumping, there is no need to keep track of an active register in the code. • Both registers are affected reciprocally by clicking the button. • Here is a screenshot of the application:
The UML diagram for MiscRegister is given on the following overhead. • The change from the last example of the previous unit is the replacement of the two cups by two registers, each having a rectangle and byte.
The code for MiscRegister is much the same as the code for MiscButton3 except for the MiscRegister and MiscRegisterByteclasses. • The implementation of the register class will change in future examples, but the basic idea is that a register encapsulates a machine byte. • The register provides a graphical representation of the byte as well as other methods that affect it.
The complete code for this example is given beginning on the next overhead. • The following examples build on it • For them it will only be necessary to show those places where there are significant changes.
import java.awt.*; • import java.awt.event.*; • import javax.swing.*; • import java.awt.Graphics2D; • import java.lang.*; • import java.awt.Rectangle; • public class MiscRegisterOneFile • { • public static void main(String[] args) • { • MiscRegisterFramemyframe = new MiscRegisterFrame(); • myframe.setVisible(true); • } • }
class MiscRegisterFrame extends JFrame • { • private MiscRegisterPanelmyPanel; • private final int FRAMEW = 500; • private final int FRAMEH = 500; • public MiscRegisterFrame() • { • setTitle("MiscRegister Frame"); • setSize(FRAMEW, FRAMEH); • setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); • myPanel = new MiscRegisterPanel(); • Container contentPane = getContentPane(); • contentPane.add(myPanel, "Center"); • } • }
class MiscRegisterPanel extends JPanel • { • private MiscRegisterRegisterregisterA; • private MiscRegisterRegisterregisterB; • public MiscRegisterPanel() • { • registerA = new MiscRegisterRegister("11110000", 160, 200); • registerB = new MiscRegisterRegister("00001111", 260, 200); • JButtonmyButton = new JButton("Swap"); • MiscButtonListenermyButtonListener = new MiscButtonListener(); • myButton.addActionListener(myButtonListener); • JPanelbuttonPanel = new JPanel(); • buttonPanel.add(myButton); • setLayout(new BorderLayout()); • add(buttonPanel, BorderLayout.SOUTH); • }
public void paintComponent(Graphics g) • { • Graphics2D g2 = (Graphics2D) g; • super.paintComponent(g2); • registerA.drawRegister(g2); • registerB.drawRegister(g2); • } • private class MiscButtonListener implements ActionListener • { • public void actionPerformed(ActionEvent event) • { • registerA.swapRegisterContents(registerB); • repaint(); • } • } • }
class MiscRegisterRegister • { • private MiscRegisterByteregisterByte; • private Rectangle registerRectangle; • private static intregW = 80; • private static intregH = 20; • private inttextX; • private inttextY; • public MiscRegisterRegister() • { • } • public MiscRegisterRegister(String stringIn, intregX, intregY) • { • registerByte = new MiscRegisterByte(stringIn); • registerRectangle = new Rectangle(regX, regY, regW, regH); • textX = regX + (int) (.16 * regW); • textY = regY + (int) (.75 * regH); • }
public void setRegisterByte(MiscRegisterBytebyteIn) • { • registerByte = byteIn; • } • public MiscRegisterBytegetRegisterByte() • { • return registerByte; • } • public void swapRegisterContents(MiscRegisterRegister source) • { • MiscRegisterBytetempByte; • tempByte = source.getRegisterByte(); • source.setRegisterByte(this.getRegisterByte()); • this.setRegisterByte(tempByte); • }
public void drawRegister(Graphics2D g2) • { • g2.draw(registerRectangle); • g2.drawString(registerByte.getStringFromByte(), textX, textY); • } • }
class MiscRegisterByte • { • public static final intbitsinbyte = 8; • private static final String junk = "00000000"; • private char bytearray[] = new char[bitsinbyte]; • public MiscRegisterByte() • { • /* This looks a little weird. • getChars() is a String class method. • The 4 parameters are the beginning and • ending indexes of the String to copy, • a character array to copy into, and a • beginning index in the character array • to copy into. This accomplishes • initializing the character array • containing the value of a byte to the • junk string. */ • junk.getChars(0, bitsinbyte, bytearray, 0); • }
public MiscRegisterByte(String stringIn) • { • /* The preliminary lines in this code • are designed to deal with an input • String which is either shorter or • longer than 8 characters. */ • junk.getChars(0, bitsinbyte, bytearray, 0); • intstringlength = stringIn.length(); • if(stringlength > bitsinbyte) • stringlength = bitsinbyte; • stringIn.getChars(0, stringlength, bytearray, 0); • }
public void setByteToThisString(String astring) • { • junk.getChars(0, bitsinbyte, bytearray, 0); • intstringlength = astring.length(); • if(stringlength > bitsinbyte) • stringlength = bitsinbyte; • astring.getChars(0, stringlength, bytearray, 0); • } • public String getStringFromByte() • { • return String.copyValueOf(bytearray); • } • }
MiscText • In this program each register is represented by a text field. • The text fields have listeners, so it is possible to enter new values into the registers. • There is also a button with a listener. • The button causes a swap of the values between the registers.
From this point on the graphical components of the example applications are instances of system supplied classes, like JTextField. • They are not instances of classes which are written from scratch, such as Cup or MiscRegister of the previous examples. • The key point is that a register is represented by a text field on the screen • There is still a register class that has that text field
The progression of Echo and Wari examples went from things like text fields to clickable cups. • In a sense, this new progression of examples is going in the opposite direction. • It turns out to be much simpler to use system supplied classes for graphical components than homemade classes. • A screenshot of MiscText is given on the next overhead.
The UML diagram for the application brings out several important points. • The relationships among the classes representing the registers and the panels in the application are somewhat complex. • The MiscTextPanel has two MiscTextRegister objects as instance variables. • These registers have instances of MiscTextByte and JTextField.
The MiscTextRegister class has an inner class, TextFieldListener. • The MiscTextPanel class has a JPanel for displaying the registers’ contents. • The registers’ text fields are added to this JPanel. • This JPanel has the default FlowLayout, so the text fields are displayed from left to right.
The MiscTextPanel also has a JPanel to hold the application’s button. • The button has a listener which is implemented as an inner class of the MiscTextPanel. • The MiscTextPanel has BorderLayout and the JPanel containing the text fields is added to it at the top, and the JPanel containing the button is added to it at the bottom. • The UML diagram is given on the following overhead.
Selections of code from the MiscTextPanel and the MiscTextRegister classes follow. • These two classes contain elements which are significantly different from previous application classes.
The constructor for the MiscTextPanel begins with the six lines of code shown on the next overhead. • The two registers are constructed, the layout is set, and a panel to hold the graphical representations of the registers is constructed. • This panel has added to it the text fields belonging to the registers. • Note the calls to the getMyField() method. • The text fields are instance variables inside the MiscTextRegister class.
registerA = new MiscTextRegister("11110000"); • registerB = new MiscTextRegister("00001111"); • setLayout(new BorderLayout()); • JPanelregisterPanel = new JPanel(); • registerPanel.add(registerA.getMyField()); • registerPanel.add(registerB.getMyField());
The code for the button listener, which is an inner class of the MiscTextPanel, contains only one change. • The call to repaint(), which has appeared in all previous listeners, is commented out. • This is a small, but important step in the right direction. • One of the purposes of moving from hand-made components to system components is that the code will be simplified.
The graphical representations of the registers are instances of JTextFields. • These are system supplied classes, and the system takes care of repainting them when necessary. • The run time appearance of the application is the same with or without calls to repaint(). • The listener code is shown on the next overhead.