Verschönerungen I

Nun haben wir die erste Version unseres Zeichenprogramm fast fertig. Was noch fehlt sind ein paar Optimierungen die das ganze professioneller aussehen lassen.

Anfangen wollen wir mit den beiden Radio-Buttons kreisBtn und quadratBtn. Aus diesen können wir, ähnlich wie pinselBtn und radiererBtn jeweils JToggleButtons daraus machen und in der actionPerformed dafür sorgen das sie sich wie Radiobuttons verhalten.
Zuerst deklarieren wir die JRadioButtons in JToggleButtons um:

JToggleButton kreisBtn;
JToggleButton quadratBtn;

dann löschen wir die JButtonGroup werkzeugspitzen da wir sie nicht mehr benötigen.

danach setzen wir als Text in den JToggleButtons das entsprechende Unicodezeichen für Kreis (\u25cf) und leerer Kreis (\u25cf) ein und fügen den ActionListener hinzu:

kreisBtn = new JToggleButton("\u25cf");
kreisBtn.addActionListener( this );
kreisBtn.setSelected(true);
kreisBtn.setFocusPainted(false);
quadratBtn = new JToggleButton("\u25a0");
quadratBtn.addActionListener( this );
quadratBtn.setFocusPainted(false);

setFocusPainted() bewirkt das der Kreis bzw. das Quadrat nicht von einer gepunkteten grauen „Focus-Linie“ umrandet ist.
Bei den Variablen fügen wir noch ein  static Charset UTF_8; ein, damit die Unicodezeichen auch auf allen Systemen korrekt dargestellt werden.

Und schließlich erweitern wir die actionPerformed um folgenden Code:

if ( source == kreisBtn ) {
	kreisBtn.setSelected(true);
	quadratBtn.setSelected( false );
}

if ( source == quadratBtn ) {
	quadratBtn.setSelected(true);
	kreisBtn.setSelected( false );
}

Als nächstes wollen wir richtige Icons verwenden.

Die neue StartFenster.java würde also so aussehen:

package miniMalprogramm;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;

public class StartFenster extends JFrame implements ActionListener {
  public static void main(String[] s) {
    new StartFenster();
  }

  static Charset UTF_8;

  Tafel tafel;
  private JMenuBar menuBar;
  private JMenu menuDatei;
  private JMenuItem mneu, mladen, mspeichern, mBeenden;

  private JToolBar auswahl;
  private JToolBar seitenleiste;

  JToggleButton kreisBtn;
  JToggleButton quadratBtn;
  JCheckBox fuellen;
  JSpinner linienstaerke;
  JToggleButton pinselBtn;
  JToggleButton radiererBtn;
  private JButton farbwaehlerIcon;
  private JButton farbwaehlerIconHG;

  Color vgfarbe = Color.BLACK;
  Color hgfarbe = Color.WHITE;
  Color aktuelleFarbe = Color.BLACK;

  public StartFenster() {
    initialisiereStartFenster();
  }

  private void initialisiereStartFenster() {
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setBounds(0, 0, 500, 500);
    this.setLocationRelativeTo(null);
    this.setAlwaysOnTop(true);
    this.setBackground(Color.white);
    this.setTitle("Tafel");
    this.setLayout(new BorderLayout());

    menuBar = new JMenuBar();
    this.setJMenuBar(menuBar);
    menuDatei = new JMenu();
    menuDatei.setText("Datei");
    menuDatei.setMnemonic('d'); // setzt Tastaturkürzel Alt+d
    menuDatei.addActionListener(this);
    menuBar.add(menuDatei);
    mneu = new JMenuItem();
    mneu.setText("Neu");
    mneu.setMnemonic('n');
    mneu.setToolTipText("Neues Bild erstellen");
    mneu.addActionListener(this);
    menuDatei.add(mneu);
    JSeparator sep1 = new JSeparator();
    menuDatei.add(sep1);
    mladen = new JMenuItem();
    mladen.setText("Laden");
    mladen.setMnemonic('l');
    mladen.setToolTipText("Datei laden");
    mladen.addActionListener(this);
    menuDatei.add(mladen);
    mspeichern = new JMenuItem();
    mspeichern.setText("Speichern");
    mspeichern.setMnemonic('s');
    mspeichern.setToolTipText("Bild speichern");
    mspeichern.addActionListener(this);
    menuDatei.add(mspeichern);
    JSeparator sep2 = new JSeparator();
    menuDatei.add(sep2);
    mBeenden = new JMenuItem();
    mBeenden.setText("Beenden");
    mBeenden.setMnemonic('e');
    mBeenden.setToolTipText("Programm beenden");
    mBeenden.addActionListener(this);
    menuDatei.add(mBeenden);

    auswahl = new JToolBar();
    auswahl.setPreferredSize(new Dimension(300, 30)); // PreferredSize = bevorzugte Größe
    auswahl.setFloatable(false);

    kreisBtn = new JToggleButton("\u25cf");
    kreisBtn.addActionListener(this);
    kreisBtn.setSelected(true);
    kreisBtn.setFocusPainted(false);
    quadratBtn = new JToggleButton("\u25a0");
    quadratBtn.addActionListener(this);
    quadratBtn.setFocusPainted(false);

    auswahl.add(kreisBtn);
    auswahl.add(quadratBtn);

    fuellen = new JCheckBox("Füllen");
    auswahl.add(fuellen);

    seitenleiste = new JToolBar();
    seitenleiste.setPreferredSize(new Dimension(30, 200)); // PreferredSize = bevorzugte Größe
    seitenleiste.setFloatable(false);
    seitenleiste.setOrientation(JToolBar.VERTICAL);
    Insets nullMargin = new Insets(5, 7, 5, 5);
    seitenleiste.setMargin(nullMargin);

    pinselBtn = new JToggleButton("P");
    pinselBtn.setPreferredSize(new Dimension(20, 20));
    pinselBtn.setSelected(true);
    pinselBtn.setAlignmentX(CENTER_ALIGNMENT);
    pinselBtn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
    pinselBtn.setSelected(true);
    pinselBtn.addActionListener(this);
    radiererBtn = new JToggleButton("R");
    radiererBtn.setPreferredSize(new Dimension(20, 20));
    radiererBtn.setSelected(false);
    radiererBtn.setAlignmentX(CENTER_ALIGNMENT);
    radiererBtn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
    radiererBtn.addActionListener(this);

    farbwaehlerIcon = new JButton() {
      public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(vgfarbe);
        g.fillRect(20, 20, 20, 20);
      }
    };
    farbwaehlerIcon.setPreferredSize(new Dimension(20, 20));
    farbwaehlerIcon.addActionListener(this);
    farbwaehlerIcon.setBackground(vgfarbe);
    farbwaehlerIcon.setForeground(vgfarbe);
    farbwaehlerIcon.setAlignmentX(CENTER_ALIGNMENT);

    farbwaehlerIconHG = new JButton() {
      public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(hgfarbe);
        g.fillRect(20, 20, 20, 20);
      }
    };
    farbwaehlerIconHG.setPreferredSize(new Dimension(20, 20));
    farbwaehlerIconHG.addActionListener(this);
    farbwaehlerIconHG.setBackground(hgfarbe);
    farbwaehlerIconHG.setForeground(hgfarbe);
    farbwaehlerIconHG.setAlignmentX(CENTER_ALIGNMENT);
    seitenleiste.add(pinselBtn);
    seitenleiste.add(radiererBtn);
    seitenleiste.addSeparator();
    seitenleiste.add(farbwaehlerIcon);
    seitenleiste.add(farbwaehlerIconHG);
    SpinnerNumberModel nummern = new SpinnerNumberModel(10.0, 1.0, 99.0, 1.0); // default, Minimum, Maximum,
                                          // Schrittweite
    linienstaerke = new JSpinner(nummern);
    linienstaerke.setMinimumSize(new Dimension(50, 30)); // setzt die Mindestgröße ( Breite, Höhe )
    linienstaerke.setMaximumSize(new Dimension(50, 30)); // setzt die Maximalgröße
    auswahl.add(linienstaerke);
    this.add(auswahl, BorderLayout.PAGE_START);
    this.add(seitenleiste, BorderLayout.WEST);

    tafel = new Tafel(this);
    this.add(tafel);
    sichtbar();
  }

  private void sichtbar() {
    this.setVisible(true);
  }

  public double getLinienstaerke() {
    double staerke = (double) this.linienstaerke.getValue();
    return staerke;
  }

  public Color getFarbe() {
    return this.aktuelleFarbe;
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    if (source == kreisBtn) {
      kreisBtn.setSelected(true);
      quadratBtn.setSelected(false);
    }

    if (source == quadratBtn) {
      quadratBtn.setSelected(true);
      kreisBtn.setSelected(false);
    }

    if (source == farbwaehlerIcon) {
      vgfarbe = JColorChooser.showDialog(this, "Vordergrundfarbe wählen", vgfarbe);
      farbwaehlerIcon.setBackground(vgfarbe);
      aktuelleFarbe = vgfarbe;
      farbwaehlerIcon.repaint();
    } else if (source == farbwaehlerIconHG) {
      hgfarbe = JColorChooser.showDialog(this, "Hintergrundfarbe wählen", vgfarbe);
      farbwaehlerIconHG.setBackground(hgfarbe);
      aktuelleFarbe = hgfarbe;
      farbwaehlerIconHG.repaint();
    }
    if (source == pinselBtn) {
      pinselBtn.setSelected(true);
      radiererBtn.setSelected(false);
      aktuelleFarbe = vgfarbe;
    }
    if (source == radiererBtn) {
      radiererBtn.setSelected(true);
      pinselBtn.setSelected(false);
      aktuelleFarbe = hgfarbe;
    }
    if (source == mneu)
      tafel.neuesBild();

    if (source == mladen)
      loadPicture();

    if (source == mspeichern)
      savePicture(erstelleIMG(tafel));

    if (source == mBeenden)
      this.dispose();

  }

  public BufferedImage erstelleIMG(Component bild) // gibt ein img der zeichenfläche an die Funktion savePicture
                            // zurück
  {
    BufferedImage img = new BufferedImage(bild.getWidth(), bild.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics2D g = img.createGraphics();
    bild.paintAll(g);
    g.dispose();
    return img;
  }

  private void loadPicture() {
    JFileChooser chooser = new JFileChooser();
    chooser.setDialogType(JFileChooser.OPEN_DIALOG);

    int rueckgabeWert = chooser.showOpenDialog(this);

    if (rueckgabeWert == JFileChooser.APPROVE_OPTION) {
      File file = chooser.getSelectedFile();
      try {
        tafel.image = ImageIO.read(file);
      } catch (IOException e) {
        e.printStackTrace();
      }
      tafel.bildGeladen = true;
      tafel.repaint();
    }

  }

  public void savePicture(BufferedImage img) //
  {
    JFileChooser chooser = new JFileChooser();
    chooser.setDialogType(JFileChooser.SAVE_DIALOG);

    int rueckgabeWert = chooser.showSaveDialog(this);

    if (rueckgabeWert == JFileChooser.APPROVE_OPTION) {
      File file = chooser.getSelectedFile();
      try {
        ImageIO.write(img, "png", file);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  public void dispose() {
    System.out.println("Tschüß");
    System.exit(0);
  }
}