Java tutorial
/* Java Swing, 2nd Edition By Marc Loy, Robert Eckstein, Dave Wood, James Elliott, Brian Cole ISBN: 0-596-00408-7 Publisher: O'Reilly */ // MixerTest2.java //A test of the MixerModel and sliders for rendering volume values. //This version also includes adjustable sliders for editing the //volume values. // import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.GridLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.EventObject; import java.util.Vector; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; import javax.swing.JTable; import javax.swing.JWindow; import javax.swing.SwingConstants; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; public class MixerTest2 extends JFrame { public MixerTest2() { super("Customer Editor Test"); setSize(600, 160); setDefaultCloseOperation(EXIT_ON_CLOSE); MixerModel test = new MixerModel(); test.dump(); JTable jt = new JTable(test); jt.setDefaultRenderer(Volume.class, new VolumeRenderer()); jt.setDefaultEditor(Volume.class, new VolumeEditor()); JScrollPane jsp = new JScrollPane(jt); getContentPane().add(jsp, BorderLayout.CENTER); } public static void main(String args[]) { MixerTest2 mt = new MixerTest2(); mt.setVisible(true); } } //MixerModel.java //An audio mixer table data model. This model contains the following columns: //<br> + Track name (String) //<br> + Track start time (String) //<br> + Track stop time (String) //<br> + Left channel volume (Volume, 0 . . 100) //<br> + Right channel volume (Volume, 0 . . 100) // class MixerModel extends AbstractTableModel { String headers[] = { "Track", "Start", "Stop", "Left Volume", "Right Volume" }; Class columnClasses[] = { String.class, String.class, String.class, Volume.class, Volume.class }; Object data[][] = { { "Bass", "0:00:000", "1:00:000", new Volume(56), new Volume(56) }, { "Strings", "0:00:000", "0:52:010", new Volume(72), new Volume(52) }, { "Brass", "0:08:000", "1:00:000", new Volume(99), new Volume(0) }, { "Wind", "0:08:000", "1:00:000", new Volume(0), new Volume(99) }, }; public int getRowCount() { return data.length; } public int getColumnCount() { return headers.length; } public Class getColumnClass(int c) { return columnClasses[c]; } public String getColumnName(int c) { return headers[c]; } public boolean isCellEditable(int r, int c) { return true; } public Object getValueAt(int r, int c) { return data[r][c]; } // Ok, do something extra here so that if we get a String object back (from // a // text field editor) we can still store that as a valid Volume object. If // it's just a string, then stick it directly into our data array. public void setValueAt(Object value, int r, int c) { if (c >= 3) { ((Volume) data[r][c]).setVolume(value); } else { data[r][c] = value; } } // A quick debugging utility to dump out the contents of our data structure public void dump() { for (int i = 0; i < data.length; i++) { System.out.print("|"); for (int j = 0; j < data[0].length; j++) { System.out.print(data[i][j] + "|"); } System.out.println(); } } } //Volume.java //A simple data structure for track volumes on a mixer. // class Volume { private int volume; public Volume(int v) { setVolume(v); } public Volume() { this(50); } public void setVolume(int v) { volume = (v < 0 ? 0 : v > 100 ? 100 : v); } public void setVolume(Object v) { if (v instanceof String) { setVolume(Integer.parseInt((String) v)); } else if (v instanceof Number) { setVolume(((Number) v).intValue()); } else if (v instanceof Volume) { setVolume(((Volume) v).getVolume()); } } public int getVolume() { return volume; } public String toString() { return String.valueOf(volume); } } //VolumeRenderer.java //A slider renderer for volume values in a table. // class VolumeRenderer extends JSlider implements TableCellRenderer { public VolumeRenderer() { super(SwingConstants.HORIZONTAL); // set a starting size...some 1.2/1.3 systems need this setSize(115, 15); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value == null) { return this; } if (value instanceof Volume) { setValue(((Volume) value).getVolume()); } else { setValue(0); } return this; } } //VolumeEditor.java //A slider Editor for volume values in a table. // class VolumeEditor extends JSlider implements TableCellEditor { public OkCancel helper = new OkCancel(); protected transient Vector listeners; protected transient int originalValue; protected transient boolean editing; public VolumeEditor() { super(SwingConstants.HORIZONTAL); listeners = new Vector(); } // Inner class for the ok/cancel popup window that displays below the // active scrollbar. It's position will have to be determined by the // editor when getTableCellEditorComponent() is called. public class OkCancel extends JWindow { private JButton okB = new JButton(new ImageIcon("accept.gif")); private JButton cancelB = new JButton(new ImageIcon("decline.gif")); private int w = 50; private int h = 24; public OkCancel() { setSize(w, h); setBackground(Color.yellow); JPanel p = new JPanel(new GridLayout(0, 2)); //p.setBorder(BorderFactory.createLineBorder(Color.gray)); //okB.setBorder(null); //cancelB.setBorder(null); p.add(okB); p.add(cancelB); setContentPane(p); okB.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { stopCellEditing(); } }); cancelB.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { cancelCellEditing(); } }); } } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { if (value == null) { return this; } if (value instanceof Volume) { setValue(((Volume) value).getVolume()); } else { setValue(0); } table.setRowSelectionInterval(row, row); table.setColumnSelectionInterval(column, column); originalValue = getValue(); editing = true; Point p = table.getLocationOnScreen(); Rectangle r = table.getCellRect(row, column, true); helper.setLocation(r.x + p.x + getWidth() - 50, r.y + p.y + getHeight()); helper.setVisible(true); return this; } // CellEditor methods public void cancelCellEditing() { fireEditingCanceled(); editing = false; helper.setVisible(false); } public Object getCellEditorValue() { return new Integer(getValue()); } public boolean isCellEditable(EventObject eo) { return true; } public boolean shouldSelectCell(EventObject eo) { return true; } public boolean stopCellEditing() { fireEditingStopped(); editing = false; helper.setVisible(false); return true; } public void addCellEditorListener(CellEditorListener cel) { listeners.addElement(cel); } public void removeCellEditorListener(CellEditorListener cel) { listeners.removeElement(cel); } protected void fireEditingCanceled() { setValue(originalValue); ChangeEvent ce = new ChangeEvent(this); for (int i = listeners.size() - 1; i >= 0; i--) { ((CellEditorListener) listeners.elementAt(i)).editingCanceled(ce); } } protected void fireEditingStopped() { ChangeEvent ce = new ChangeEvent(this); for (int i = listeners.size() - 1; i >= 0; i--) { ((CellEditorListener) listeners.elementAt(i)).editingStopped(ce); } } }