420 likes | 547 Views
Das EMMA-GUI. Aufteilung des Bildes (Applikation). Windows - Titel. Menü - Balken. Dateiwerkzeuge. Bild. Bild. Bild. Zeichenwerkzeuge. Gruppenwerkzeuge. Meldungen, Informationen, Fehler. Aufteilung des Bildes (Applet). Menü - Balken. Dateiwerkzeuge. Bild. Bild. Bild.
E N D
Das EMMA-GUI 06-EMMA-GUI
Aufteilung des Bildes (Applikation) Windows - Titel Menü - Balken Dateiwerkzeuge Bild Bild Bild Zeichenwerkzeuge Gruppenwerkzeuge Meldungen, Informationen, Fehler 06-EMMA-GUI
Aufteilung des Bildes (Applet) Menü - Balken Dateiwerkzeuge Bild Bild Bild Zeichenwerkzeuge Gruppenwerkzeuge Meldungen, Informationen, Fehler 06-EMMA-GUI
Aufteilung des Bildes (int. Appli.) Menü - Balken Dateiwerkzeuge Bild Bild Bild Zeichenwerkzeuge Gruppenwerkzeuge Meldungen, Informationen, Fehler 06-EMMA-GUI
Menübalken ist extra, da er ggf. an eine umfassendere Applikation andocken muss. • Die restlichen Komponenten werden innerhalb des contentFrames (JComponent) angeordnet. • BorderLayout ist für EMMA gut geeignet. • Im Zentrum muss ein JDesktopPane den virtuellen Desktop für die zu bearbeitenden Bilder bereitstellen. • Die einzelnen Bilder werden in JInternalFrame‘s geöffnet. 06-EMMA-GUI
Konstruktor private JDesktopPane desktopPane = new JDesktopPane(); public EMMA301Paint (Container parent, boolean createExitButton) { setLayout(new BorderLayout()); add(desktopPane, BorderLayout.CENTER); makeActions(parent, createExitButton); add(makeFileBar(createExitButton), BorderLayout.NORTH); add(makeToolsBar(), BorderLayout.WEST); add(makeStructurBar(), BorderLayout.EAST); add(makeMessageBar(), BorderLayout.SOUTH); makeMenuBar(parent, createExitButton); makePopupMenu(parent, createExitButton); } 06-EMMA-GUI
Parameter • parent : Elternobjekt für die Komponente, die das Paint-Programm enthält. Bei dieser Komponente wird versucht. das Menü zu platzieren. Wenn null übergeben wird kann kein Menü erzeugt werden. • createExitButton : gibt an, ob ein exit-Button erzeugt wird, der bei Betätigung das gesamte Programm beendet(System.exit(0)); • Layout : BorderLayout ist gut geeignet für die Platzierung der Arbeitsfläche, sowie der Button-Leisten. • DesktopPane wird in der Definition des Attributs desktopPane erzeugt und dem zentralen Feld der Komponente zugewiesen. • Zur Definition der erforderlichen Actions wird die Methode createActions aufgerufen. • Die benötigten Leisten werden mit entsprechenden Methoden erzeugt und den Randbereichen des Feldes zugeordnet. • Das Menü und das Popupmenü werden erzeugt und platziert. 06-EMMA-GUI
makeActions private Action exitAction; private void makeActions (Container parent, boolean createExitButton) { if (createExitButton) { exitAction = new AbstractAction ("exit", EMMA301Utils.getImageIcon(parent, "pictures/exit.gif")) { { putValue(Action.SHORT_DESCRIPTION, "Beendet das Programm"); putValue(Action.MNEMONIC_KEY, new Integer('x')); } public void actionPerformed(ActionEvent e) { System.exit(0); } }; } } 06-EMMA-GUI
Die Actions werden als private globale Objekte definiert und in der Methode makeActions erzeugt. • Zum Laden der Icons wird die Methode EMMA301Utils.getImageIcon benutzt. • Innerhalb des Objektinitialisierungsblockes werden den Eigenschaften SHORT_DESCRIPTION und MNEMONIC_KEY passende Werte zugewiesen. • Der Konstruktor weist die Eigenschaften NAME und SMALL_ICON zu. • Die Methode actionPerformed wird implementiert. 06-EMMA-GUI
EMMA301Utils public final class EMMA301Utils { private EMMA301Utils() {} public static ImageIcon getImageIcon(Container parent, String fileName){ try { Class parentClass = parent.getClass(); Method getCodeBase = parentClass.getMethod("getCodeBase", new Class[]{}); URL url = (URL)(getCodeBase.invoke(parent, new Object[]{})); return new ImageIcon(new URL(url, fileName)); } catch (NoSuchMethodException nsme){return new ImageIcon(fileName); } catch (IllegalAccessException iae){} catch (InvocationTargetException ite){} catch (MalformedURLException mue){} catch (NullPointerException npe){ return new ImageIcon(fileName); } catch (Exception ex) {} return null; } } 06-EMMA-GUI
Die Klasse EMMA301Util besitzt einen private-Konstruktor und ist als final definiert, damit kein Objekt davon erzeugt und keine Klasse von ihr abgeleitet werden kann. • Die Methode getImageIcon dient dem Laden von ImageIcon‘s. Dabei wird unterschieden, ob die Applikation als Applet läuft (besitzt die Methode getCodeBase) oder als Applikation. • Falls ein Fehler beim Laden auftritt, wird null zurückgegeben. 06-EMMA-GUI
createButton private JButton createButton(Action action) { JButton button = new JButton(action); if ( ((ImageIcon)(action.getValue(Action.SMALL_ICON))) .getIconHeight()>0) button.setText(null); button.setMargin(new Insets(0,0,0,0)); return button; } 06-EMMA-GUI
createButton ist eine Hilfsmethode zur Erzeugung von Buttons mit bestimmten Eigenschaften. • Es wird ein Button mit zugeordneter Action erzeugt. • Wenn zu der Action ein Icon gehört, soll der Button keinen Text enthalten. • Die Abstände zwischen dem Inhalt des Buttons und den Rändern werden auf 0 gesetzt. 06-EMMA-GUI
makeFileBar private JPanel makeFileBar(boolean createExitButton) { JPanel fileBar = new JPanel(); fileBar.setLayout (new BoxLayout(fileBar, BoxLayout.X_AXIS)); if (createExitButton) fileBar.add(createButton(exitAction)); return fileBar; } 06-EMMA-GUI
makeFileBar erzeugt die Button-Leiste an der Nord-Seite der Arbeitsfläche. • Üblicherweise sind dort Buttons für Dateiarbeit, Drucken, Formate u.s.w. platziert. • Da mehrere Buttons enthalten sein sollen empfiehlt sich ein JPanel mit BoxLayout in horizontaler Ausrichtung. • Der exit-Button wird nur erzeugt, wenn der Schalter createExitButton true ist. 06-EMMA-GUI
makeMenuBar private void makeMenuBar(Container parent, boolean createExitButton) { try { Class parentClass = parent.getClass(); Method getJMenuBar = parentClass.getMethod("getJMenuBar", new Class[]{}); JMenuBar menuBar = (JMenuBar)(getJMenuBar.invoke(parent, new Object[]{})); if (menuBar==null) { menuBar = new JMenuBar(); Method setJMenuBar = parentClass.getMethod("setJMenuBar", new Class[]{JMenuBar.class}); setJMenuBar.invoke(parent, new Object[]{menuBar}); } 06-EMMA-GUI
JMenu fileMenu = new JMenu("file"); fileMenu.setMnemonic('f'); menuBar.add(fileMenu); if (createExitButton) fileMenu.add(new JMenuItem(exitAction)); } catch (NoSuchMethodException nsme){} catch (NullPointerException npe){} catch (IllegalAccessException iae){} catch (InvocationTargetException ite){} } 06-EMMA-GUI
makeMenuBar erzeugt den Menübalken. • Zunächst wird die Klasse bestimmt zu der das Elternobjekt gehört. • Es wird das Method-Objekt bestimmt das zu der Methode getJMenuBar gehört. • Existiert diese Methode nicht, so wird die Ausnahme NoSuchMethodException ausgeworfen. • Die Methode getJMenuBar wird aufgerufen um das aktuelle JMenuBar-Objekt des Elternobjektes bestimmt. • Ist das JMenuBar-Objekt null, so existiert beim Elternobjekt noch kein JMenuBar und es wird ein neues erzeugt und dem Elternobjekt als JMenuBar zugeordnet. • Es wird ein neues Menü erzeugt und dem JMenuBar hinzugefügt. • Danach werden alle JMenuItem‘s erzeugt und JMenu‘s zugeordnet. • Falls Ausnahmen auftreten, da z.B. das Elternobjekt die Methoden getJMenuBar bzw. setJMenuBar nicht besitzt wird kein Menü erzeugt und die Methode ohne Aktion verlassen. 06-EMMA-GUI
makePopupMenu private JPopupMenu popupMenu = new JPopupMenu(); private void makePopupMenu (Container parent, boolean createExitButton) { if (createExitButton) popupMenu.add( new JMenuItem(exitAction)); addMouseListener(new MouseAdapter(){ public void mousePressed(MouseEvent e) { maybeShowPopup(e); } public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { if (e.isPopupTrigger()) popupMenu.show(e.getComponent(), e.getX(), e.getY()); } }); } 06-EMMA-GUI
makePopupMenu erzeugt das Popup-Menü. • Popup-Menüs sind sehr ähnlich zu normalen Menüs. • Sie werden von der Klasse JPopupMenu abgeleitet und enthalten durch die add-Methode hinzugefügt JMenuItem‘s. • Das Öffnen des Popup-Menüs wird über den MousListener gesteuert. • Beim Drücken bzw. beim Loslassen einer Mouse-Taste kann mit der Methode isPopupTrigger des MouseEvents festgestellt werden, ob das Popup-Menü geöffnet werden soll. • Welche Taste bei welcher Betätigung das Popup-Menü öffnen soll, hängt von der Oberfläche (Motif, CDE, Metal) ab. 06-EMMA-GUI
JInternalFrame‘s für Graphiken • Es sollen mehrere Graphiken gleichzeitig geladen und bearbeitet werden können.Graphiken werden in JInternalFrame-Objekten bearbeitet. • Ein derartiges Frame beherbergt genau ein (ggf. komplexes) graphisches Objekt.Die paintComponent-Methode des ContentPanes muss das graphische Objekte darstellen. 06-EMMA-GUI
EMMA301PaintFrame class EMMA301PaintFrame extends JInternalFrame { private static final int deltx = 20; private static final int delty = 20; private static int internalFrameNumber = 0; private GraphicalObject graphicalObject = null; public EMMA301PaintFrame(JDesktopPane desktop) { this(desktop, "Noname #"+(++internalFrameNumber)); } public EMMA301PaintFrame(JDesktopPane desktop, String title) { super(title); setPreferredSize(new Dimension(200,200)); setClosable(true); setIconifiable(true); setMaximizable(true); setResizable(true); int posx = deltx*((internalFrameNumber-1)/20+ (internalFrameNumber-1)%20); int posy = delty*((internalFrameNumber-1)%20); setLocation(posx, posy); 06-EMMA-GUI
setContentPane(new JPanel() { public void paintComponent(Graphics g) { super.paintComponent(g); paintGraphics((Graphics2D)g); } }); getContentPane().setBackground(Color.yellow); pack(); desktop.add(this); setVisible(true); } public void paintGraphics (Graphics2D g) { if (graphicalObject != null) graphicalObject.paint(g); } } 06-EMMA-GUI
posx und posy enthalten die Koordinaten der linken oberen Ecke des zu öffnenden Frames. • deltx und delty die Änderungen von posx bzw. posy zwischen zwei Fenstern. • internalFrameNumber zählt die geöffneten internen Frames. • graphicalObject speichert das graphische Objekt, das in diesem Frame bearbeitet werden soll. 06-EMMA-GUI
Datei öffnen • Beim Öffnen einer Datei muss zunächst die Datei mit einem FileChooser ausgewählt werden. • Für den FileChooser muss ein geeigneter Filter definiert werden. • FileFilter vergleichen meistens ein Muster (Pattern) mit dem Filenamen um zu entscheiden ob das File akzeptiert werden soll. Dabei werden „?“ als ein beliebiges Zeichen und „*“ als eine beliebige Zahl beliebiger Zeichen interpretiert. 06-EMMA-GUI
public static boolean searchPattern (String pattern, String text) { return searchPattern(pattern, 0, text, 0); } public static boolean searchPattern (String pattern, int ip, String text, int it) { if (ip>=pattern.length() && it>=text.length()) return true; if (ip>=pattern.length()) return false; if (it>=text.length()) { if (pattern.charAt(ip)=='*') return searchPattern(pattern, ip+1, text, it); return false; } 06-EMMA-GUI
if (pattern.charAt(ip)=='?') return searchPattern(pattern, ip+1, text, it+1); if (pattern.charAt(ip)=='*') { for (int i=it;i<=text.length();i++) if (searchPattern(pattern, ip+1, text, i)) return true; return false; } if (pattern.charAt(ip)!=text.charAt(it)) return false; return searchPattern(pattern, ip+1, text, it+1); } 06-EMMA-GUI
makeFileFilter public static javax.swing.filechooser.FileFilter makeFileFilter(String description, String [] pattern) { final String [] p = pattern; final String d = description; return new javax.swing.filechooser.FileFilter() { private String [] pat = p; public boolean accept(File file) { if (file.isDirectory()) return true; for (int i=0;i<pat.length;i++) if (searchPattern (pat[i].toUpperCase(), file.getName().toUpperCase())) return true; return false; } public String getDescription() { String des=d+" ("+pat[0]; for (int i=1;i<pat.length;i++) des+=", "+pat[i]; return des+")"; } }; } 06-EMMA-GUI
openAction openAction = new AbstractAction ("open", EMMA301Utils.getImageIcon(parent, "pictures/open.gif")){ { putValue(Action.SHORT_DESCRIPTION, "Öffnet eine Datei in einem neuen Fester"); putValue(Action.MNEMONIC_KEY, new Integer('o')); } public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(currentDirectory); fileChooser.setAcceptAllFileFilterUsed(false); javax.swing.filechooser.FileFilter ff = EMMA301Utils.makeFileFilter( "EMMA301 Paint", new String[]{"*.emp"}); fileChooser.addChoosableFileFilter(ff); fileChooser.addChoosableFileFilter( EMMA301Utils.makeFileFilter( "EMMA301", new String[]{"*.em*"})); 06-EMMA-GUI
fileChooser.addChoosableFileFilter( EMMA301Utils.makeFileFilter( "Pictures", new String[]{"*.jpg", "*.gif", "*.png"})); fileChooser.setAcceptAllFileFilterUsed(true); fileChooser.setFileFilter(ff); if (fileChooser.showOpenDialog(emmaComponent) == JFileChooser.APPROVE_OPTION ) { File openFile = fileChooser.getSelectedFile(); currentDirectory = fileChooser.getCurrentDirectory(); new EMMA301PaintFrame(desktopPane, openFile.getName()); } }}; 06-EMMA-GUI
Farbe auswählen • Zur Auswahl von Farben gibt es die Klasse JColorChooser. 06-EMMA-GUI
colorAction colorAction = new AbstractAction( "color", EMMA301Utils.getImageIcon( parent, "pictures/color.gif")){ { putValue(Action.SHORT_DESCRIPTION, "Farbauswahl"); putValue(Action.MNEMONIC_KEY, new Integer('c')); } public void actionPerformed(ActionEvent e) { JColorChooser colorChooser = new JColorChooser(); Color newColor = colorChooser.showDialog( desktopPane, "Farbauswahl", activeColor); if (newColor != null) activeColor=newColor; }}; 06-EMMA-GUI
Allgemeine Action Klasse private class Action extends AbstractAction { private int typ; Action(Container parent, int typ, String name, String iconFile, String description, char mnemonic) { putValue(NAME, name); putValue(SMALL_ICON, EMMA301Utils.getImageIcon(parent, iconFile)); putValue(SHORT_DESCRIPTION, description); putValue(MNEMONIC_KEY, new Integer(mnemonic)); this.typ=typ; } public void actionPerformed(ActionEvent e) { switch (typ) { case 1: System.exit(0); case 2: new EMMA301PaintFrame(desktopPane); break; 06-EMMA-GUI
case 3: JFileChooser fileChooser = new JFileChooser(currentDirectory); fileChooser.setAcceptAllFileFilterUsed(false); javax.swing.filechooser.FileFilter ff = EMMA301Utils.makeFileFilter("EMMA301 Paint", new String[]{"*.emp"}); fileChooser.addChoosableFileFilter(ff); fileChooser.addChoosableFileFilter( EMMA301Utils.makeFileFilter("EMMA301", new String[]{"*.em*"})); fileChooser.addChoosableFileFilter(EMMA301Utils.makeFileFilter ("Pictures", new String[]{"*.jpg", "*.gif", "*.png"})); fileChooser.setAcceptAllFileFilterUsed(true); fileChooser.setFileFilter(ff); if (fileChooser.showOpenDialog(emmaComponent)==JFileChooser.APPROVE_OPTION ) { File openFile = fileChooser.getSelectedFile(); currentDirectory = fileChooser.getCurrentDirectory(); new EMMA301PaintFrame(desktopPane, openFile.getName()); } break; case 4: Color newColor = new JColorChooser().showDialog(emmaComponent, "Farbauswahl", activeColor); if (newColor != null) activeColor=newColor; break; 06-EMMA-GUI
case 5: JOptionPane.showMessageDialog (emmaComponent, EMMA301Utils.getInfos(), EMMA301Paint.DESCRIPTION, JOptionPane.PLAIN_MESSAGE); break; case 6: activeFont=FontChooser.showDialog(emmaComponent, activeFont); break; case 7: activeStroke= BasicStrokeChooser.showDialog(emmaComponent, activeStroke); break; case 8: activePaint=PaintChooser.showDialog(emmaComponent, activePaint); break; default: JOptionPane.showMessageDialog(emmaComponent, "Action Nr. "+typ+" unknown!", "Error", OptionPane.ERROR_MESSAGE); } } } 06-EMMA-GUI
FontChooser 06-EMMA-GUI
public static Font showDialog(Component parent, Font font) { ChooserPanel cp = new ChooserPanel(font); int ret = JOptionPane.showConfirmDialog(parent, cp, "FontChooser", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null); if (ret==JOptionPane.OK_OPTION) return cp.getNewFont(); return font; } • Problem: Vorschaufenster • Wird als interne Klasse ChooserPanel extends JPanel implementiert. 06-EMMA-GUI
Layout : GridBagLayout • Fontauswahl: JComboBox private JComboBox fontCB; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); String [] fn = ge.getAvailableFontFamilyNames(); fontCB = new JComboBox(fn); fontCB.setSelectedItem(fontName); fontCB.addActionListener(this); fontCB.setEditable(false); 06-EMMA-GUI
Verknüpfung zwischen dem JTextField und JScrollBar für die Auswahl der Größe. private JTextField sizeTF; private JScrollBar sizeSB; sizeTF = new JTextField(""+font.getSize()); sizeTF.addActionListener(this); sizeSB = new JScrollBar(JScrollBar.HORIZONTAL, font.getSize(), 1, 1, 201); sizeSB.addAdjustmentListener(this); 06-EMMA-GUI
public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == sizeTF ) { int s=Integer.parseInt(sizeTF.getText()); sizeSB.setValue(s); makeFont(fontName, style, s); } } public void adjustmentValueChanged(AdjustmentEvent e) { int s = sizeSB.getValue(); sizeTF.setText(""+s); makeFont(fontName, style, s); } 06-EMMA-GUI
Vorschaubild als in ein JScrollPane eingebettetes JPanel JScrollPane sp = new JScrollPane(new JPanel(){ { setPreferredSize(new Dimension(8000,2000)); setBackground(Color.white); } public void paintComponent(Graphics g) { super.paintComponent(g); p(g); } }); sp.setPreferredSize(new Dimension(600,400)); 06-EMMA-GUI
public void p(Graphics g) { g.setFont(font); g.drawString(fontName, 20, 2*size); for (int i=0;i<8;i++) for (int j=0;j<32;j++) g.drawString (""+(char)(i*32+j),20+j*size,(i+4)*(size+5)); } 06-EMMA-GUI