© m. winter cosc 3p91 – advanced object-oriented programming 4.14.1 gui programming graphical...
TRANSCRIPT
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.1
GUI Programming
• graphical user interface– human-computer interface– replaces command-line interface– interface builders
• Java AWT/Swing– behavior is platform independent
• event-driven programming– user in control– user actions events– program responds to events
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.2
AWT and Swing
• AWT components are heavyweight– associated with native components created by the
underlying window system– appearance determined by the window system– different platforms = different look
• Swing components are lightweight– created by the JVM– appearance determined by the JVM– different platforms = same look
• Composite design pattern
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.3
Component
Container
Panel Window
Frame Dialog
Button
Canvas
Checkbox
Choice
Label
List
Scrollbar
TextComponent
TextArea TextField
AWT classes
ScrollPane
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.4
JComponent
Container
JPanel Window
Frame Dialog
JButton
JCombobox
JCheckbox
JLabel
JList
JScrollbar
JTextComponent
JTextArea JTextField
Swing classesComponent
JFrame JDialog
JWindow
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.5
Component• abstract class• methods
– paint(Graphics g)– repaint() calls paint– setSize(int width, int height)– setVisible(boolean b)– requestFocus()– validate()
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.6
Container• abstract class• widget containers
– can contain containers• layout
– LayoutManager• methods
– add(Component comp)– add(String name, Component comp)– remove(Component comp)– removeAll()– setLayout(LayoutManager mgr)– paint(Graphics g) // from Component
should be overridden in order to draw
all components of the container
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.7
JComponent• Swing version of Component• abstract class• adds additional functionality• new methods
– Dimension getPreferredSize() – Dimension getSize(Dimension rv) – setPreferredSize(Dimension preferredSize)– setEnabled(boolean enabled)
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.8
JFrame
• top level window– components– menu bar
• content pane– all layout etc.
• constructors– JFrame()– JFrame(String title)
• methods– Container getContentPane()– dispose() // from Window– pack() // from Window– setJMenuBar(JMenuBar menuBar)– setResizable(boolean b) // from Frame– setTitle(String title) // from Frame– setDefaultCloseOperation(int operation)
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.9
Layout managers
• each container has a layout manager– handles the layout of the components contained in the
container
setLayout(lm) sets lm as the layout manager of this container
Container LayoutManager
BorderLayout
CardLayout
FlowLayout
GridLayout
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.10
Layout managers• BorderLayout manager can manage five components,
– default layout manager for Frame, JFrame– locations: North, East, South, West, Centeradd(“North“, new Jbutton(“Button 1“);
• GridLayout manager creates a rectangular array of components– each component occupies the same size portion of the
screennew GridLayout(4,4,3,3)
• FlowLayout manager places components in rows left to right, top to bottom– components need not to have the same size– default manager for Panel
• CardLayout manager stacks components vertically– only one component is visible at one time– components can be namedCardLayout lm = new CardLayout();Panel p = new Panel(lm);p.add(“One“, new Label(“Number One“));lm.show(p,“One“);
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.11
Reaction Model• reactive
– react to event as soon as it happens– usually for buttons and menu selections– write Listener and handle event– used when view must change immediately
• completed data entry• doing input validation• reactive selections
• passive– don’t react to event when it happens– wait until significant event (e.g. button press)– access widget to get its state/contents– usually for information entry
• text boxes• selections
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.12
Events
• caused by user actions• event objects
– represent particular events– carry further information
• event source objects– register listeners– send listeners events– GUI widgets
• listeners– receive/handle events– listener interfaces
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.13
Example - ActionEvent
• button presses cause ActionEvents• ActionListeners handle ActionEvents
– actionPerformed– getActionCommand
• JButton– constructor– addActionListener– setActionCommand
• creating a button on the fly
JButton button = new JButton("Button");
button.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
//do something
}});
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.14
Example (cont.)
• using a private listener class
JButton button = new JButton("Button");
button.addActionListener(new MyActionListener());
private class MyActionListener implements ActionListener public void actionPerformed (ActionEvent e) {
//do something
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.15
Example (cont.)
• combining the button and the listener in a new class
JButton button = new MyButton();
private class MyButton extends JButton
implements ActionListener {
public MyButton() {
super("Button");
addActionListener(this);
}
public void actionPerformed (ActionEvent e) {
//do something
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.16
Example (cont.)• a button to make a window invisibleprivate class MyOKButton extends JButton
implements ActionListener {
private JDialog parent;
public MyOKButton(JDialog parent) {
super("Ok");
this.parent = parent;
addActionListener(this);
}
public void actionPerformed (ActionEvent e) {
parent.setVisible(false);
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.17
Example (cont.)• generic ButtonAdapter class
abstract class ButtonAdapter extends JButton
implements ActionListener {
public ButtonAdapter(String name) {
super(name);
addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
pressed();
}
public abstract void pressed();
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.18
Listeners / Events /Adapters• listener classes
– ActionListener– ItemListener– ListSelectionListener– AdjustmentListener– KeyListener– MouseListener– MouseWheelListener– WindowListener– ComponentListener– ContainerListener
• event classes– ActionEvent– ItemEvent– ListSelectionEvent– AdjustmentEvent
– KeyEvent– MouseEvent– MouseWheelEvent– WindowEvent– ComponentEvent– ContainerEvent
• adapter classes– KeyAdapter– MouseAdapter– MouseMotionAdapter– MouseInputAdapter– WindowAdapter– ComponentAdapter– ContainerAdapter
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.19
Event Hierarchy
• semantic events– ActionEvent
• button click (incl. checkbox and radio button), menu selection combo box selection, enter in text area
– ItemEvent• change of the state of an item, e.g., checkbox and radio
box– ListSelectionEvent
• list selections– AdjustmentEvent
• scroll bar changes• low level events
– KeyEvent– MouseEvent– MouseWheelEvent– WindowEvent
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.20
Listeners (cont.)• handling window closing
– JFrame• top level window• window events
– WindowListener• windowClosing
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
System.exit(0);
}});
– WindowAdapter• null methods
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.21
Listeners (cont.)private class MyMouseListener extends MouseAdapter {
public void mouseClicked (MouseEvent me) {int x = me.getX();int y = me.getY();if (me.getButton() == MouseEvent.BUTTON1) {
// action for left mouse button};if (me.getButton() == MouseEvent.BUTTON2) {
// action for middle mouse button};
if (me.getButton() == MouseEvent.BUTTON3) {// action for right mouse button
};}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.22
JPanel
• contained container– lightweight– typically used as top level container in content pane– also for controlling layout– default layout manager: FlowLayoutManager
• constructor– JPanel()
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.23
JButton
• button widget• button with label• press generates ActionEvent• constructor
– JButton ( String label )• methods
– addActionListener ( ActionListener l )– setActionCommand ( String actionCommand )– setEnabled ( boolean b )– setText ( String text )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.24
JMenuBar• associated with a JFrame
– frame.setJMenuBar ( JMenuBar mBar )• constructor
– JMenuBar ( )• methods
– add ( JMenu menu )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.25
JMenu
• menu in a JMenuBar• constructor
– JMenu ( String label )• methods
– add ( JMenuItem item )– addSeparator ( )– insert ( JMenuItem item, int pos)– insertSeparator ( int pos )– remove ( JMenuItem item )– remove ( int pos )– removeAll ( )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.26
JMenuItem• selectable item in a JMenu• constructors
– JMenuItem ( String text )• methods
– addActionListener ( ActionListener listener )– setActionCommand ( String command )– setEnabled ( boolean b )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.27
Examplepublic MyFrame() {
JMenuBar myBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem startItem = new JMenuItem("Start Game");
startItem.setEnabled(false);
fileMenu.add(startItem);
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}});
fileMenu.add(quitItem);
myBar.add(fileMenu);
setJMenuBar(myBar);
setSize(500,300);
setLocation(200,200);
setVisible(true);
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.28
JRadioButton• buttons that can be grouped• ButtonGroup
– constructor• ButtonGroup ( )
– methods• add ( AbstractButton b )• ButtonModel getSelection ( )
• constructors– JRadioButton ( String label )– JRadioButton ( String label, boolean state )
• methods– addActionListener ( Actionlistener listener )– setActionCommand ( String actionCommand )– setEnabled ( boolean b )– boolean isSelected ( )– setSelected ( boolean state )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.29
JDialog• dialog window
– has a parent (owner)– modal or non-modal
• content pane• constructors
– JDialog ( )– JDialog ( Dialog owner )– JDialog ( Frame owner )– JDialog ( Dialog owner, boolean modal )– JDialog ( Frame owner, boolean modal )
• methods– Container getContentPane ( )– dispose ( ) // from Window– pack ( ) // from Window– setResizable ( boolean b ) // from Dialog– setTitle ( String title ) // from Dialog– setDefaultCloseOperation ( int operation )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.30
Examplepublic MyDialog(JFrame parent) {
super(parent,true);
setSize(220,160);
setTitle("Select number of players");
ButtonGroup group = new ButtonGroup();
JRadioButton one = new JRadioButton("One",true);
JRadioButton two = new JRadioButton("Two",false);
JRadioButton three = new JRadioButton("Three",false);
JRadioButton four = new JRadioButton("Four",false);
group.add(one); group.add(two); group.add(three); group.add(four);
JPanel selectPanel = new JPanel();
selectPanel.setLayout(new GridLayout(4,1));
selectPanel.add(one); selectPanel.add(two);
selectPanel.add(three); selectPanel.add(four);
getContentPane().add(selectPanel,BorderLayout.NORTH);
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.31
Example (cont’d)JPanel buttonPanel = new JPanel();
JButton ok = new JButton("OK");
ok.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}});
buttonPanel.add(ok,BorderLayout.CENTER);
getContentPane().add(buttonPanel,BorderLayout.SOUTH);
setVisible(false);
}
In MyFrame: private MyDialog dialog = new MyDialog(this);...
startItem.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}});
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.32
JScrollBar
• constructors– JScrollBar (int orientation, int value, int extent,
int min, int max )• methods
– addAdjustmentListener( AdjustmentListener listener )– getOrientation( )– getValue( )– setValue( int value )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.33
JLabel
• text label• constructors
– JLabel ( String text )– JLabel ( String text, int align )– JLabel ( Icon icon )– JLabel ( String text, Icon icon, int align )
• alignment– JLabel.LEFT– JLabel.RIGHT– JLabel.CENTER
• methods– setText ( String text )– setIcon ( Icon icon )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.34
Example
private JLabel widthLabel = new JLabel(" Width: 5000");private JLabel heightLabel = new JLabel(" Height: 5000");
private JScrollBar widthScrollbar = new JScrollBar(JScrollBar.HORIZONTAL,5000,0,0,32000);
private JScrollBar heightScrollbar = new JScrollBar(JScrollBar.HORIZONTAL,5000,0,0,32000);
widthScrollbar.addAdjustmentListener(new AdjustmentListener() {public void adjustmentValueChanged(AdjustmentEvent e) {
widthLabel.setText(" Width: " + widthScrollbar.getValue());
}});heightScrollbar.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {heightLabel.setText(" Height: " +
heightScrollbar.getValue());}});
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.35
JOptionPane
• easy pop-up of standard dialogs– modal
• methods (static)– int showMessageDialog ( Component parent, Object msg)– int showMessageDialog ( Component parent, Object msg,
String title, int type ) – int showOptionDialog ( … )– int showConfirmDialog ( … )– String showInputDialog ( … )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.36
JFileChooser• file selection dialog• can specify subdirectory and file filter• constructor
– JFileChooser ( )– JFileChooser ( File currentDirectory )
• methods– File getSelectedFile– setCurrentDirectory ( File dir )– setFileFilter ( FileFilter filter )– showOpenDialog ( Component Parent )– showSaveDialog ( Component Parent )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.37
JTextComponent
• text entry areas• new lines (\n)• JTextField
– editable single-line text– JTextField ( int cols )
• JTextArea– editable multi-line text– JTextArea ( int rows, int cols )
• methods– setText ( String text )– String getText ( )– setEditable ( boolean b )
• JPasswordField– setEchoChar ( char echo )– char [ ] getPassword ( )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.38
JCheckbox
• a checkbox• generates ActionEvent• constructors
– JCheckbox ( String label )– JCheckbox ( String label, boolean state )
• methods– addActionListener ( Actoinlistener listener )– setActionCommand ( String actionCommand )– setEnabled ( boolean b )– boolean isSelected ( )– setSelected ( boolean state )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.39
JList
• list selector• generates ListSelectionEvent• constructor
– JList ( Object[] items )– JList ( ListModel dataModel )
• methods– setVisibleRowCount ( int rows )– setFixedCellWidth ( int width)– setSelectionMode ( int mode )
• JList.SINGLE_SELECTION, JList.SINGLE_INTERVAL_SELECTION, JList.MULTIPLE_INTERVAL_SELECTION
– addListSelectionListener ( ListSelectionListener l )– Object[] getSelectedValues ( )– Object getSelectedValue ( )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.40
ListSelectionListener
• javax.swing.event• method
– valueChanged ( ListSelectionEvent e )• ListSelectionEvent
– boolean getValueIsAdjusting ( )– Object getSource ( )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.41
JScrollPane• scrolling for other components• place component in JScrollPane and then add scroll pane to
container• constructor
– JScrollPane ( Component c )
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.42
2D Graphics and Animation
Requirements: Java 1.4.1 or newer.
Some basic notions:• Resolution: Typical resolutions are 640x480, 800x600,
1024x768 and 1280x1024.• Bit depth: The number of colors a monitor can display depends
on the bit depth. Common bit depth are 8, 15, 16, 24 and 32 bits.– human eye can see about 10 million colors 16,777,216 =
224, 24-bit is optimal.• Refresh rate: The monitor continuously refreshes the display.
How fast it refreshes is known as the refresh rate, and is measured in Hertz (Hz), i.e., cycles per second. A refresh rate between 75Hz and 85Hz is usually suitable for the human eye.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.43
Images - Transparency
Three types of image transparency:• Opaque: Every pixel in the image is visible.• Transparent: Every pixel in the image is either completely
visible or completely see-through.• Translucent: Pixels can be partially transparent, to create a
ghostlike, partially see-through effect.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.44
Images – File Formats
Three formats are supported:• GIF:
– opaque or transparent– 8-bit color or less
• PNG: – any type of transparency– up to 24-bit color– PNG supercedes GIF
• JPEG: – opaque– 24-bit color– high compression (lossy compression)– for photographic images
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.45
Images – Reading
Using the Toolkit’s getImage() method:
Toolkit toolkit = Toolkit.getDefaultToolkit();Image image = toolkit.getImage(filename);
The code above does not actually load the image (The image begins loading
in another thread).
ImageIcon icon = new ImageIcon(filename);Image image = icon.getImage();
or
ImageIO.read(new File(filename));
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.46
Hardware-Accelerated Images
Hardware-accelerated images are images that are stored in video memory
rather than system memory.
Java tries to hardware-accelerate any image you load.
Issues that will keep images from being accelerated:• constantly changing the contents of the image• translucent images are not accelerated (Java 1.4.1)• system has no accelerated images capability
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.47
Benchmark
The differences in speed are:
System:• Program ImageSpeedTest.java (Listing 2.4)• 600MHz Athlon• GeForce-256 video card• display resolution 800x600• bit depth: 16
Result:• Opaque: 5550.599 images/sec• Transparent: 5478.6953 images/sec• Translucent: 85.2197 images/sec • Translucent (Anti-Aliased): 113.18243 images/sec
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.48
Animation
Animation = Displaying a sequence of images
Image A Image B Image C Image BImages
0ms 200ms 275ms 300msTime
(milliseconds)
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.49
import java.awt.Image;import java.util.ArrayList;
/** The Animation class manages a series of images (frames) and the amount of time to display each frame.*/public class Animation {
private List<Pair<Image,Long>> frames; private int currFrameIndex; private long animTime; private long totalDuration;
private boolean repeating; private boolean running;
/** Creates a new, empty Animation. */ public Animation(boolean repeating) { frames = new ArrayList<Pair<Image,Long>>(); totalDuration = 0; this.repeating = repeating; running = false; }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.50
/** Adds an image to the animation with the specified duration (time to display the image). */ public synchronized void addFrame(Image image, long duration) { totalDuration += duration; frames.add(new Pair<Image,Long>(image, totalDuration)); }
/** Starts this animation over from the beginning. */ public synchronized void start() { reset(); running = true; }
public synchronized void reset() { animTime = 0; currFrameIndex = 0; }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.51
/** Updates this animation's current image (frame), if
necessary.
*/
public synchronized void update(long elapsedTime) {
if (running && frames.size() > 1) {
animTime += elapsedTime;
if (animTime >= totalDuration) {
if (repeating) {
currFrameIndex = 0;
animTime = animTime % totalDuration;
} else {
animTime = totalDuration;
running = false;
};
}
while (animTime > frames.get(currFrameIndex).getSecond()) {
currFrameIndex++;
}
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.52
public synchronized boolean isRunning() {
return running;
}
/** Gets this Animation's current image. Returns null
if this animation has no images.
*/
public synchronized Image getImage() {
if (frames.size() == 0) {
return null;
}
else {
return frames.get(currFrameIndex).getFirst();
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.53
Active Rendering
Animation = continuously updating the screen
1. rely on paint()– override paint(), call repaint()– disadvantage: can cause delay, because the AWT thread
might be busy doing other things2. active rendering
Graphics g = frame.getGraphics();
draw(g); // here draw to the component
g.dispose();
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.54
Animation Loop
The animation loop follows these steps:1. Updates any animation2. Draws to the screen3. Sleeps for a short period (optional)4. Starts over with step 1.
while (true) {updateAnimations();Graphics g = frame.getGraphics();draw(g);g.dispose();try {
Thread.sleep(20);}catch (InterruptedException ex) {}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.55
Double Buffering
A buffer is simply an off-screen area of memory used for drawing.1. Draw to the buffer2. Copy buffer to screen
private Image doubleBuffer;
…
public void update(Graphics g) {
Dimension size = getSize();
if doubleBuffer == null ||
doubleBuffer.getWidth(this) != size.width ||
doubleBuffer.getHeight(this) != size.height)
{
doubleBuffer = createImage(size.width,size.height);
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.56
if (doubleBuffer != null) {// paint to double bufferGraphics g2 = doubleBuffer.getGraphics();paint(g2);g2.dispose();// copy double buffer to screeng.drawImage(doubleBuffer,0,0,null);
}else {
// couldn’t create double buffer, just paint on screenpaint(g);
}}
public void paint(Graphics g) {// do drawing here…
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.57
Page Flipping
One drawback to using double buffering is the amount of time it takes to
copy the buffer to the screen.
Buffer 1: Display Buffer
Buffer 2: Back Buffer
Screen
Display Pointer
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.58
Page Flipping (cont.)
Buffer 1: Back Buffer
Buffer 2: Display Buffer
Screen
Display Pointer
After flipping the page, the display pointer points to buffer 2, and buffer 1 is used as the back buffer.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.59
Monitor Refresh and TearingWhat happens when the page flipping occurs or a buffer is copied in the middle of a monitor refresh?
A part of the old buffer will be displayed at the same time as a part of the new buffer. This effect is called tearing.
Flip at just the right moment, using the BufferStrategy class.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.60
The BufferStrategy class
Double buffering, page flipping, and waiting for the monitor refresh all are
handled by the BufferStrategy class. First, it tries page flipping. If that
is not possible, it tries double buffering.
Both Canvas and Window objects can have a BufferStrategy.
Creating a new BufferStrategy. Example:frame.createBufferStrategy(2);
Using the BufferStrategy. Example:BufferStrategy strategy = frame.getBufferStrategy();Graphics g = strategy.getDrawGraphics();draw(g);g.dispose();strategy.show();
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.61
Full-Screen Mode
Objects needed to switch to full-screen mode:
• A Window object. The examples use a JFrame.• A DisplayMode object. The DisplayMode object
specifies the resolution, bit depth, and the refresh rate to switch the display to.
• A GraphicsDevice object. The GraphicsDevice object enables you to change the display mode and inspect display properties (interface to the video card).
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.62
An example
JFrame window = new JFrame();
DisplayMode displayMode = new DisplayMode(800,600,16,75);
// get the GraphicsDevice
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = environment.getDefaultScreenDevice();
// use the JFrame as the full screen window
device.setFullScreenWindow(window);
// change the display mode
device.setDisplayMode(displayMode);
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.63
Example (cont.)
Afterward, to switch back to the previous display mode, set the full-screen
Window to null.
device.setFullScreenWindow(null);
This code is not complete. Problems are:• setDisplayMode() may throw an IllegalArgumentException
(if the required mode is not available on the system).• JFrames still show their borders and title bars.
a wrapper class SimpleScreenManager to deal with these issues and to simplify the functions.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.64
SimpleScreenManager
import java.awt.*;
import javax.swing.JFrame;
/**
The SimpleScreenManager class manages initializing and
displaying full screen graphics modes.
*/
public class SimpleScreenManager {
private GraphicsDevice device;
public SimpleScreenManager() {
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.65
/**
Enters full screen mode and changes the display mode.
*/
public void setFullScreen(DisplayMode displayMode, JFrame window)
{
window.setUndecorated(true);
window.setResizable(false);
device.setFullScreenWindow(window);
if (displayMode != null && device.isDisplayChangeSupported())
{
try {
device.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex) {
// ignore - illegal mode for this device
}
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.66
/** Returns the window currently used in full screen mode. */ public Window getFullScreenWindow() { return device.getFullScreenWindow(); }
/** Restores the screen's display mode. */ public void restoreScreen() { Window window = device.getFullScreenWindow(); if (window != null) { window.dispose(); } device.setFullScreenWindow(null); }
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.67
FullScreenTestimport java.awt.*;import javax.swing.JFrame;
public class FullScreenTest extends JFrame {
public static void main(String[] args) {
DisplayMode displayMode;
if (args.length == 3) { displayMode = new DisplayMode( Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2]), DisplayMode.REFRESH_RATE_UNKNOWN); } else { displayMode = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN); }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.68
FullScreenTest test = new FullScreenTest(); test.run(displayMode); }
private static final long DEMO_TIME = 5000;
public void run(DisplayMode displayMode) { setBackground(Color.blue); setForeground(Color.white); setFont(new Font("Dialog", 0, 24));
SimpleScreenManager screen = new SimpleScreenManager(); try { screen.setFullScreen(displayMode, this); try { Thread.sleep(DEMO_TIME); } catch (InterruptedException ex) { } } finally { screen.restoreScreen(); } }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.69
public void paint(Graphics g) {
g.drawString("Hello World!", 20, 50);
}
}
Smoother look using anti-aliasing
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.70
Anti-Aliasing
public void paint(Graphics g) {
if ( g instanceOf Graphics2D) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
g.drawString("Hello World!", 20, 50);
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.71
ImageTestimport java.awt.*;import javax.swing.ImageIcon;import javax.swing.JFrame;
public class ImageTest extends JFrame {
public static void main(String[] args) {// see FullScreenTest
ImageTest test = new ImageTest(); test.run(displayMode); }
private static final int FONT_SIZE = 24; private static final long DEMO_TIME = 10000;
private SimpleScreenManager screen; private Image bgImage; private Image opaqueImage; private Image transparentImage; private Image translucentImage; private Image antiAliasedImage; private boolean imagesLoaded;
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.72
public void run(DisplayMode displayMode) { setBackground(Color.blue); setForeground(Color.white); setFont(new Font("Dialog", Font.PLAIN, FONT_SIZE)); imagesLoaded = false;
screen = new SimpleScreenManager(); try { screen.setFullScreen(displayMode, this); loadImages(); try { Thread.sleep(DEMO_TIME); } catch (InterruptedException ex) { } } finally { screen.restoreScreen(); } }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.73
public void loadImages() {
bgImage = loadImage("images/background.jpg");
opaqueImage = loadImage("images/opaque.png");
transparentImage = loadImage("images/transparent.png");
translucentImage = loadImage("images/translucent.png");
antiAliasedImage = loadImage("images/antialiased.png");
imagesLoaded = true;
// signal to AWT to repaint this window
repaint();
}
private Image loadImage(String fileName) {
return new ImageIcon(fileName).getImage();
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.74
public void paint(Graphics g) { // set text anti-aliasing if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); }
// draw images if (imagesLoaded) { g.drawImage(bgImage, 0, 0, null); drawImage(g, opaqueImage, 0, 0, "Opaque"); drawImage(g, transparentImage, 320, 0, "Transparent"); drawImage(g, translucentImage, 0, 300, "Translucent"); drawImage(g, antiAliasedImage, 320, 300, "Translucent (Anti-Aliased)"); } else { g.drawString("Loading Images...", 5, FONT_SIZE); } }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.75
public void drawImage(Graphics g, Image image, int x, int y, String caption)
{
g.drawImage(image, x, y, null);
g.drawString(caption, x + 5, y + FONT_SIZE +
image.getHeight(null));
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.76
import java.awt.*;import javax.swing.ImageIcon;import javax.swing.JFrame;
public class AnimationTest1 {
public static void main(String args[]) { DisplayMode displayMode; if (args.length == 3) { displayMode = new DisplayMode( Integer.parseInt(args[0]), Integer.parseInt(args[1]), Integer.parseInt(args[2]), DisplayMode.REFRESH_RATE_UNKNOWN); } else { displayMode = new DisplayMode(800, 600, 16,
DisplayMode.REFRESH_RATE_UNKNOWN); } AnimationTest1 test = new AnimationTest1(); test.run(displayMode); }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.77
private static final long DEMO_TIME = 5000; private SimpleScreenManager screen; private Image bgImage; private Animation anim;
public void loadImages() { // load images bgImage = loadImage("background.jpg"); Image player1 = loadImage("player1.png"); Image player2 = loadImage("player2.png"); Image player3 = loadImage("player3.png");
// create animation anim = new Animation(); anim.addFrame(player1, 250); anim.addFrame(player2, 150); anim.addFrame(player1, 150); anim.addFrame(player2, 150); anim.addFrame(player3, 200); anim.addFrame(player2, 150); }
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.78
private Image loadImage(String fileName) { return new ImageIcon(fileName).getImage();
}
public void run(DisplayMode displayMode) {
screen = new SimpleScreenManager();
try {
screen.setFullScreen(displayMode, new JFrame());
loadImages();
animationLoop();
}
finally {
screen.restoreScreen();
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.79
public void animationLoop() { long startTime = System.currentTimeMillis(); long currTime = startTime; while (currTime - startTime < DEMO_TIME) { long elapsedTime = System.currentTimeMillis() - currTime; currTime += elapsedTime; // update animation anim.update(elapsedTime); // draw to screen Graphics g = screen.getFullScreenWindow().getGraphics(); draw(g); g.dispose(); // take a nap try { Thread.sleep(20); } catch (InterruptedException ex) { } }
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.80
public void draw(Graphics g) { // draw background
g.drawImage(bgImage, 0, 0, null);
// draw image
g.drawImage(anim.getImage(), 0, 0, null);
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.81
ScreenManager
Update of the SimpleScreenManager with these new features:1. Double buffering and page flipping by creating a
BufferStrategy.2. getGraphics(), which gets the graphic context for the
display.3. update(), which updates the display.4. getCompatibleDisplayModes(), which gets a list of the
compatible display modes.5. getCurrentDisplayMode(), which gets the current display
mode.6. findFirstCompatibleMode(), which gets the first compatible
mode from a list of modes.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.82
Sprites
A sprite is a graphic that moves independently around the screen.
Besides an animation, the sprites will be composed of• a position
– float attributes• a velocity (a speed and a direction)
– horizontal and vertical component– pixels per millisecond
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.83
import java.awt.Image;
public class Sprite {
private Animation anim;
// position (pixels)
private float x;
private float y;
// velocity (pixels per millisecond)
private float dx;
private float dy;
/**
Creates a new Sprite object with the specified Animation.
*/
public Sprite(Animation anim) {
this.anim = anim;
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.84
/**
Updates this Sprite's Animation and its position based
on the velocity.
*/
public void update(long elapsedTime) {
x += dx * elapsedTime;
y += dy * elapsedTime;
anim.update(elapsedTime);
}
… // Various access methods
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.85
Image Transforms
Image transforms enable you to translate, flip, scale, shear, and rotate
images, even on the fly.
An AffineTransform object describes a transform (strategy designpattern).
The transformation itself is stored in a 3x3 matrix. The class provides several easy methods that do the calculation:• rotate(double theta, double x, double y)
Concatenates this transform with a transform that rotates coordinates around an anchor point.
• scale(double sx, double sy) Concatenates this transform with a scaling transformation.
• translate(double tx, double ty) Concatenates this transform with a translation transformation.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.86
Example
The character normally faces right. Using a transformation we make the
character face left when it is moving left.
AffineTransform transform = new AffineTransform();
transform.scale(-1,1);
transform.translate(-sprite.getWidth(),0);
g.drawImage(sprite.getImage(),transform,null);
Problem with transformations:Transforming images does not take advantage of hardware
acceleration. use transformations sparingly.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.87
Interactivity and User Interfaces
The AWT event model (for keyboard events):1. The user presses a key.2. The operating system sends the key event to the Java
runtime.3. The Java runtime posts the event to the AWT’s event queue.4. The AWT event dispatch thread dispatches the event to any
KeyListener.5. The KeyListener receives the key event and does whatever it
wants with it.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.88
KeyListener
The KeyListener interface has three methods:1. keyPressed(KeyEvent e)
2. keyReleased(KeyEvent e)
3. keyTyped(KeyEvent e)
Virtual key codes in the KeyEvent class: VK_xxx
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.89
KeyTest
window.setFocusTraversalKeyEnabled(false);
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_ESCAPE) {
stop();
} else {
addMessage(“Pressed: “ +KeyEvent.getKeyText(keyCode));
e.consume();
};
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.90
Mouse Input
Three different types of mouse events:1. Mouse button clicks MouseListener
2. Mouse motion MouseMotionListener
3. Mouse wheel scrolls MouseWheelListener
1. MouseListener– mousePressed(MouseEvent e)– mouseReleased(MouseEvent e)– mouseClicked(MouseEvent e)– mouseEntered(MouseEvent e)– mouseExited(MouseEvent e)
2. MouseMotionListener– mouseDragged(MouseEvent e)– mouseMoved(MouseEvent e)
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.91
3. MouseWheelListener– mouseWheelMoved(MouseWheelEvent e)
4. MouseEvent– getButton() -- BUTTON1, BUTTON2, BUTTON3– getPoint()– getX()– getY()
5. MouseWheelEvent– getWheelRotation()
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.92
Relative Motion
The Java API doesn’t support relative motion of the mouse.
Idea:1. The mouse starts at the center of the screen.2. The user moves the mouse, and you calculate how much it
moved.3. You send an event to reposition the mouse to the center of the
screen.4. When you detect that the mouse was recentered, you ignore
the event.
The java.awt.Robot can be used for reposition the mouse.mouseMove(x, y)
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.93
MouselookTest
private synchronized void recenterMouse() {
Window window = screen.getFullScreenWindow();
if (robot != null && window.isShowing()) {
centerLocation.x = window.getWidth() / 2;
centerLocation.y = window.getHeight() / 2;
SwingUtilities.convertPointToScreen(centerLocation,
window);
isRecentering = true;
robot.mouseMove(centerLocation.x,centerLocation.y);
}
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.94
public synchronized void mouseMoved(MouseEvent e) {
if (isRecentering &&
centerLocation.x == e.getX() &&
centerLocation.y == e.getY())
{
isRecentering = false;
}
else {
if (relativeMouseMode) {
recenterMouse();
}
}}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.95
Mouse CursorSome mouse cursors (java.awt.Cursor class):• CROSSHAIR_CURSOR A cursor in the shape of a plus sign• DEFAULT_CURSOR The normal arrow cursor• HAND_CURSOR The hand cursor (hyperlink)• TEXT_CURSOR The text cursor, normally I-shaped• WAIT_CURSOR The wait cursor, normally an hourglass
Unfortunately, there is no invisible cursor. Create your own cursor that has a
blank image.
Cursor invisibleCursor = Toolkit.getDefaultToolkit().createCustomCursor(
Toolkit.getDefaultToolkit().getImage(””);new Point(0,0),”invisible”);
Window window = screen.getFullScreenWindow();window.setCursor(invisibleCursor);
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.96
InputManager
The InputManager provides the following features:1. Handle all key and mouse events, including relative mouse
movements.2. Save the events so you can query them precisely when you want
to, instead of changing game state in the AWT event dispatch thread.
3. Detect the initial press for some keys and detect whether the key is held down for others.
4. Map keys to generic game actions (GameAction), such as mapping the spacebar to a jump action.
5. Change the key mapping on the fly, so the user can configure the keyboard.
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.97
Using Swing Components
Drawing all the Swing components in the animation loop:
// draw our graphics
draw(g)
// draw Swing components
JFrame frame = screen.getFullScreenWindow();
frame.getLayeredPane().paintComponents(g);
Transparent content pane:
if (contentPane instanceof JComponent) {
((JComponent) contentPane).setOpaque(false);
}
© M. Winter
COSC 3P91 – Advanced Object-Oriented Programming
4.98
Swing does all its rendering automatically in the AWT event dispatch thread.
To avoid conflicts with our own rendering we turn off this functionality.
RepaintManager repaintManager = new NullRepaintManager();
repaintManager.setDoubleBufferingEnabled(false);
RepaintManager.setCurrentManager(repaintManager);