220 likes | 232 Views
Learn how to implement fine-tuned undo/redo functions, save and restore states, and enhance user experience with customizable features in Java applications. Dive deep into event handling, persistency, and optimizing resource usage.
E N D
Lecture 3 • Chat: Assignments 2 and 3 • Undo Capability • Fine-tuning appearance • Adding Customizability • Save/Restore • Assignment 4
Undo/Redo • Expected by user • Apply consistently • Second undo = redo? • More depth is nice • What counts as an event? • Easily and non-easily reversible events • Warn user when taking irreversible actions • Persistency: can undo vector be saved?
1-step Undo • After each reversible action, save state (backend) • If Undo command issued: • Restore state. (backend, possibly frontend). • Save undone state in case of redo. • Disable undo, enable redo.
Multi-step undo/redo • Keep stack of recent states. • Undo pops back to previous state. New actions pushed onto the top. • Immediately after a series of undos, can redo actions. Enhanced stack. • More complex behavior possible • Emacs’ tree undo
Resource issues with undo • Saving/restoring state may cost too much. • Can store difference between before/after states. • Can store command itself. Need special undo code for each command. • May only want to support limited undo depth.
Supporting undo in Java • Vectors to store states/commands. Dynamically sized and untyped. • Need one vector for undoable events and one for redoable events. • Can just store ActionEvents generated by your UI, rather than state, if you are able to reverse them. Allows highly reusable code.
Images • “A picture is worth a thousand words, and uses less screen real estate.” • Attach to a JComponent: ImageIcon ii = new ImageIcon(“images/icon1.gif”); JButton b = new JButton(ii); JLabel l = new JLabel(“Hello”,ii); JMenuItem mi = new JMenuItem(“test”); mi.setIcon(b.getIcon()); • Manipulate using Graphics or Graphics2D object
What can I do in 1 line? • Can add images to any AbstractButton (button, checkbox, menu, menuitem), JLabel, JList, JComboBox • Only Icons (fixed-size images) supported so far. Use ImageIcon. • Dubious support for animated gifs, but these distract even when they do work.
Other Easy Graphic Effects • Buttons/Menus can have several icons to indicate status. • Change background color of any JComponent using setBackground. setForeground too. • Use JLayeredPane to superimpose text, components, on top of image. • Can also setFont().
Example: JButton icons ImageIcon ic1 = new ImageIcon(filenameOrURL); // … Get icons ic2 through ic6. JButton but = new Jbutton(“text”); but.setIcon(ic1); but.setRolloverIcon(ic2); but.setPressedIcon(ic3); but.setSelectedIcon(ic4); but.setDisabledIcon(ic5); but.setDisabledSelectedIcon(ic6); // etc.
Customization • “A happy user is a productive user.” • What should we allow the user to change? • Almost everything • Don’t let the user trap himself. e.g. no “hide Edit Preferences”, no “disable Quit”. • Session vs. Permanent prefs
Easy part first: • Cosmetic customization, such as colors, background screen, menu shortcuts, all easy. • Font also easy, except font size may cause problems. Same goes for Icons. • Examples
Hard parts (sort of) • Permanent prefs. Need to save everything relevant in a file. • Prioritized prefs. “I like blue text, except in buttons with icons, except for the Back button.” • Multiple preference settings. • Resizing/rearranging GUI components.
Save/Restore • A quick overview of stream I/O in Java. • Note: easy to write OS specific code here, because of path name conventions • Serialization
Streams InputStream OutputStream
Wrapping A technique for “borrowing methods” Vector.add() ObjectInputStream int Object FilterInputStream FileInputStream Integer int A wrapper class Stream wrapping
Example (SaveRestoreDemo.java) // In actionPerformed(ActionEvent e) method. // code handles “Save” menuitem by storing a // serialized object to file. if (e.getActionCommand().equals("Save")) { try { FileOutputStream out = new FileOutputStream(fname); ObjectOutputStream s = new ObjectOutputStream(out); s.writeObject(mySerializableObject); s.flush(); } catch (Exception ex) { System.out.println("Save exception." + ex); }
Object Serialization • Uniform way of converting objects to strings, for RMI and saving/restoring from files. • Thread-safe. Object cannot be modified during serialization. • Objects can only be serialized once by a given serializer. Further references are by handle. This is efficient, but somewhat limiting. • Compatibility issues.
Using Serialization • Use classes ObjectOutputStream, ObjectInputStream. Methods writeObject(ob), readObject() convert any Serializable object to a data stream. • Serializable interface is empty. • Only purpose is security. If you make a class Serializable, its private fields can be accessed. • Can override this by providing custom writeObject and readObject methods in Serializable class, or by declaring variables transient
Custom Serialization • Default serialization is inefficient • May want to serialize part of a field, but protect another part. • May wish to switch between allowing and disallowing serialization, or change methods.
Save/Restore • 1-step save: serialize everything, write it to file. Wasteful. • Better: save only as much as necessary, but serialize where handy. • Restore: Read from file in reverse order data was written.
Assignment 4 • Lots of work, start early. • Get totally familiar with SaveRestoreDemo before starting. The new functionality is mostly here.