{"id":513,"date":"2018-11-15T14:04:04","date_gmt":"2018-11-15T13:04:04","guid":{"rendered":"https:\/\/freizone.net\/java-einfach-lernen\/?p=513"},"modified":"2020-05-11T19:29:39","modified_gmt":"2020-05-11T17:29:39","slug":"dateimenue","status":"publish","type":"post","link":"https:\/\/freizone.net\/java-einfach-lernen\/2018\/11\/15\/dateimenue\/","title":{"rendered":"Dateimen\u00fc"},"content":{"rendered":"<p>Da der Quellcode mittlerweile recht lang ist, f\u00fchre ich zugunsten der \u00dcbersichtlichkeit zuerst nur den Quellcode an der neu ist.<br \/>\nGanz am Ende f\u00fcge ich dann den gesamten Quellcode hinzu.<\/p>\n<p>Um ein Men\u00fc hinzuzuf\u00fcgen stellt Swing uns die Klasse JMenuBar zur Verf\u00fcgung. Das Vorgehen ist \u00e4hnlich wie mit den anderen Swing Komponenten. Zuerst f\u00fcgen wir folgende Deklarationen unserem StartFenster hinzu:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">private JMenuBar menuBar;\r\nprivate JMenu menuDatei;\r\nprivate JMenuItem mneu, mladen, mspeichern, mBeenden;<\/pre>\n<p>Dann f\u00fcgen wir folgenden Quelltext in unserer initialisiereStartFenster() Methode des StartFensters ein:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">menuBar = new JMenuBar();\r\nthis.setJMenuBar( menuBar );\r\n\r\nmenuDatei = new JMenu();\r\nmenuDatei.setText( \"Datei\" );\r\nmenuDatei.setMnemonic( 'd' ); \/\/ setzt Tastaturk\u00fcrzel Alt+d\r\nmenuDatei.addActionListener( this );\r\nmenuBar.add( menuDatei );\r\n\r\nmneu = new JMenuItem();\r\nmneu.setText( \"Neu\" );\r\nmneu.setMnemonic( 'n' );\r\nmneu.setToolTipText( \"Neues Bild erstellen\" );\r\nmneu.addActionListener( this );\r\nmenuDatei.add( mneu );\r\n\r\nJSeparator sep1 = new JSeparator();\r\nmenuDatei.add( sep1 );\r\n\r\nmladen = new JMenuItem();\r\nmladen.setText( \"Laden\" );\r\nmladen.setMnemonic( 'l' );\r\nmladen.setToolTipText( \"Datei laden\" );\r\nmladen.addActionListener( this );\r\nmenuDatei.add( mladen );\r\n\r\nmspeichern = new JMenuItem();\r\nmspeichern.setText( \"Speichern\" );\r\nmspeichern.setMnemonic( 's' );\r\nmspeichern.setToolTipText( \"Bild speichern\" );\r\nmspeichern.addActionListener( this );\r\nmenuDatei.add( mspeichern );\r\n\r\nJSeparator sep2 = new JSeparator();\r\nmenuDatei.add( sep2 );\r\n\r\nmBeenden = new JMenuItem();\r\nmBeenden.setText( \"Beenden\" );\r\nmBeenden.setMnemonic( 'e' );\r\nmBeenden.setToolTipText( \"Programm beenden\" );\r\nmBeenden.addActionListener( this );\r\nmenuDatei.add( mBeenden );<\/pre>\n<p>Zuerst erstellen wir eine JMenuBar die dann unser Ausklappmen\u00fc aufnimmt, und setzen sie auf unser Fenster Zeile (1 und 2). In Zeile 4 &#8211; 8 f\u00fcgen modifizieren wir diese Men\u00fcBar.<\/p>\n<p>Danach definieren wir die einzelnen Men\u00fceintr\u00e4ge die alle dem gleichen Schema folgen: Zuerst wir ein neues JMenuItem gebildet (Zeile 10), dann wird der Text (Zeile 11), das Tastaturk\u00fcrzel (Mnemonic, (Zeile 12), sowie der ToolTip (Zeile 13, erscheint wenn den Mauspfeil ein paar Sekunden auf dem Eintrag ruhen l\u00e4\u00dft) hinzugef\u00fcgt. Dann wird noch der ActionListener hinzugef\u00fcgt (Zeile 14) und das ganze unserer JMenuBar namens menuDatei hinzugef\u00fcgt (Zeile 15).<\/p>\n<p>Der JSeparator den wir in Zeile 17 bilden und in Zeile 18 hinzuf\u00fcgen bildet eine horizontale Linie.<\/p>\n<p>Jetzt brauchen wir noch ein paar if-Abfragen in unserem StartFenster und die Methoden zum speichern, laden und l\u00f6schen des Bildschirms.<br \/>\nHierzu f\u00fcgen wir folgende Abfragen in unsere actionPerformed() Methode ein:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">if ( source == mneu )\r\n  tafel.neuesBild();\r\n\r\nif ( source == mladen )\r\n\tloadPicture();\r\n\r\nif ( source == mspeichern )\r\n  savePicture( erstelleIMG( tafel ) );\r\n\r\nif ( source == mBeenden )\r\n  this.dispose();<\/pre>\n<p>Die Methode f\u00fcr ein neues Bild (Zeile 2) bauen wir am besten in die Tafel ein, da der virtuelle Bildschirm auch zur Zeichenfl\u00e4che geh\u00f6rt.<br \/>\nWir rufen also Tafel.java auf und deklarieren zuerst wieder die Variablen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">boolean bildGeladen = false;\r\npublic BufferedImage image;<\/pre>\n<p>dann die schreiben wir die Methode:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">public void neuesBild()\r\n{\r\n  this.virtuellerBildschirm.clear();\r\n\r\n  bildGeladen = false;\r\n  image = null;\r\n\r\n  repaint();\r\n}<\/pre>\n<p>In dieser Methode leeren wir den virtuellenBildschirm indem wir den Inhalt der ArrayList mit clear() l\u00f6schen.<br \/>\nAnschlie\u00dfend setzen wir bildGeladen auf false und image auf null damit die paint-Methode kein Bild zeichnen kann. Dann rufen wir repaint() auf und lassen damit den Bildschirm neu zeichnen.<\/p>\n<p>Da wir nun eine Methode in der Tafel haben, die vom StartFenster aus aufgerufen wird,\u00a0brauchen wir im StartFenster nat\u00fcrlich noch eine Referenz auf die Tafel die wir zu den anderen Variablendeklarationen hinzuf\u00fcgen:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">private Tafel tafel;<\/pre>\n<p>Alle anderen Funktionen wollen wir dem Startfenster zuordnen.<\/p>\n<p>loadPicture() :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">private void loadPicture()\r\n{\r\n  JFileChooser chooser = new JFileChooser();\r\n  chooser.setDialogType( JFileChooser.OPEN_DIALOG );\r\n\r\n  int rueckgabeWert = chooser.showOpenDialog( this );\r\n\r\n  if ( rueckgabeWert == JFileChooser.APPROVE_OPTION )\r\n  {\r\n    File file = chooser.getSelectedFile();\r\n    try\r\n    {\r\n      tafel.image = ImageIO.read( file );\r\n    }\r\n    catch ( IOException e )\r\n    {\r\n      e.printStackTrace();\r\n    }\r\n    tafel.bildGeladen = true;\r\n    tafel.repaint();\r\n  }\r\n\r\n}<\/pre>\n<p>Da wir nicht wollen das eine andere Klasse auf die loadPicture-Funktion zugreift machen wir diese privat (Zeile 1).<\/p>\n<p>In Zeile 3 erstellen wir einen neuen JFileChooser mit Namen chooser. Dann setzen wir in Zeile 4 den Dialogtyp auf OPEN. D. h. wir teilen damit dem Compiler mit das wir den Dialog zum \u00f6ffnen einer Datei ben\u00f6tigen.<\/p>\n<p>In Zeile 6 weisen wir einer int-Variablen das \u00f6ffnen unseres FileChoosers zu.\u00a0<code>chooser.showOpenDialog( this );<\/code> bewirkt zun\u00e4chst nur das der Dialog ge\u00f6ffnet wird und zwar in <em>this<\/em> also in dem Objekt in dem der Aufruf stattfindet also unser Startfenster. Sobald eine Aktion &#8211; OK oder Abbrechen &#8211; get\u00e4tigt wird gibt der Dialog einen Wert zur\u00fcck. Dieser Wert wird in rueckgabeWert gespeichert.<\/p>\n<p>In Zeile 8 wird rueckgabeWert auf darauf \u00fcberpr\u00fcft ob eine Datei ausgew\u00e4hlt und Ok gedr\u00fcckt wurde. Ist das der Fall wird in Zeile 10\u00a0 die Dateiinformation in einem File-Objekt gespeichert.<\/p>\n<p>Jetzt wird in Zeile 11 &#8211; 14 versucht das Bild in die Variable image von tafel zu laden. Hierbei wird die Klasse ImageIO verwendet. Die read-Methode erwartet ein Objekt vom Typ File das wir ihr geben.<\/p>\n<p>In Zeile 15 &#8211; 18 werden evtl. auftretende Fehler behandelt. Hier lassen wir uns einfach den StackTrace also den Weg wie der Fehler aufgetreten ist in die Konsole schreiben.<\/p>\n<p>Anschlie\u00dfend setzen wir in Zeile 19 die Variable bildGeladen auf true damit die paint-Methode wei\u00df, das sie ein Bild laden muss. Dann wird repaint() ausgel\u00f6st (Zeile 20).<\/p>\n<p>savePicture (Zeile 8) ben\u00f6tigt ein Objekt vom Typ BufferedIMG. Dieses IMG erhalten wir durch eine Methode die wir ebenfalls schreiben. Die Methode lie\u00dft die Zeichenfl\u00e4che aus und gibt sie im IMG-Bildformat zur\u00fcck. Diese Methode k\u00f6nnte man nat\u00fcrlich auch als Getter in der Zeichenfl\u00e4che realisieren. Aber unsere Zeichenfl\u00e4che wollen wir am besten nur Zeichnen lassen.<\/p>\n<p>Zuerst die Unterfunktion erstelleIMG():<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">public BufferedImage erstelleIMG( Component bild ) \/\/ gibt ein img der zeichenfl\u00e4che an die Funktion savePicture zur\u00fcck\r\n{\r\n  BufferedImage img = new BufferedImage( bild.getWidth(), bild.getHeight(), BufferedImage.TYPE_INT_RGB );\r\n  Graphics2D g = img.createGraphics();\r\n  bild.paintAll( g );\r\n  g.dispose();\r\n  return img;\r\n}<\/pre>\n<p>Die Methode erwartet eine Komponente die &#8218;gescannt&#8216; werden soll. In unserem Fall also die Zeichenfl\u00e4che.<br \/>\nIn Zeile 3 erstellen wir ein neues leeres BufferedImage und geben ihm die Ma\u00dfe unserer Zeichenfl\u00e4che. Au\u00dferdem setzen wir das Farbmodell auf RGB mit Integerwerten.<br \/>\nZeile 4 bedeutet nicht das dort die Grafiken erstellt werden, es bedeutet vielmehr das das img in ein Graphics2D-Objekt eingebettet wird. Dies erm\u00f6glicht uns in das img Daten zu schreiben.<br \/>\nIn Zeile 5 wird schlie\u00dflich mit der paint-All Methode von bild, alle darin enthaltenen Grafiken in g und damit in das img geschrieben.<br \/>\nJenes wird dann in Zeile 7 zur\u00fcckgegeben.<\/p>\n<p>savePicture() :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">public void savePicture( BufferedImage img ) \t\/\/  \r\n{\r\n  JFileChooser chooser = new JFileChooser();\r\n  chooser.setDialogType( JFileChooser.SAVE_DIALOG );\r\n\r\n  int rueckgabeWert = chooser.showSaveDialog( this );\r\n\r\n  if ( rueckgabeWert == JFileChooser.APPROVE_OPTION )\r\n  {\r\n    File file = chooser.getSelectedFile();\r\n    try\r\n    {\r\n      ImageIO.write( img, \"png\", file );\r\n    }\r\n    catch ( IOException e )\r\n    {\r\n      e.printStackTrace();\r\n    }\r\n  }\r\n}<\/pre>\n<p>savePicture empf\u00e4ngt nun das img (Zeile 1).<br \/>\nWir erstellen in Zeile 3 einen JFileChooser und definieren ihn als SAVE_DIALOG (Zeile 4).<br \/>\nIn Zeile 6 bringen wir den Dialog auf den Bildschirm und weisen den R\u00fcckgabewert (OK oder Abbrechen) unserer Variablen rueckgabeWert zu.<br \/>\nIn Zeile 8 \u00fcberpr\u00fcfen wir rueckgabeWert darauf ob Ok geklickt wurde und erstellen ein File-Objekt in das wir die Dateiinformation schreiben (Zeile 10).<br \/>\nSchlie\u00dflich speichern wir das Bild in Zeile 13 unter zuhilfename der Klasse ImageIO mit der Methode write die drei Werte erwartet ( IMG, dateiendung, Dateipfad ).<br \/>\nIn den Zeilen 15 &#8211; 18 behandeln wir m\u00f6glicherweise auftretende Fehler indem wir uns in der Konsole genau ausgeben lassen wo der Fehler auftritt.<\/p>\n<p>Zeile 10, this.dispose() ist \u00e4hnlich wie this.exit() nur mit dem Unterschied das der Compiler das Programm nicht sofort beendet sondern erst die Funktion dispose() aufruft. Der Programmierer hat damit die M\u00f6glichkeit zus\u00e4tzliche Funktionen unterzubringen wenn das Programm beendet wird. Dies ist m\u00f6glich indem er dispose() \u00fcberschreibt um beispielsweise automatisch zu speichern oder \u00e4hnliches. Beispiel:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">public void dispose() {\r\n  System.out.println(\"Tsch\u00fc\u00df\");\r\n  System.exit(0);\r\n}<\/pre>\n<p>Die Variable <em>bildGeladen<\/em>\u00a0der Tafel, brauchen wir um in der paint das geladene Bild zu zeichnen falls etwas geladen wurde. In der Variablen <em>image<\/em> wird das Bild geladen. In der paint wird es dann folgenderma\u00dfen abgefragt:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">if ( bildGeladen == true ) {\r\n  if ( image != null )\r\n\t  g.drawImage( image, 0, 0, null ); \/\/ ( img-Bild, x-Position, y-position, observer\r\n  }<\/pre>\n<p>Sicherhaltshalber fragen wir noch ab ob in image auch wirklich etwas vorhanden ist (Zeile 2).<br \/>\nIn Zeile 3 verwenden wir null, da wir keinen observer haben (ein Observer k\u00f6nnte z.B. ein Fortschrittsbalken sein).<\/p>\n<p>Hier wie versprochen der gesamte neue Quellcode.<br \/>\nG\u00f6nnt euch einen Kaffee und seht ihn in aller Ruhe durch.<br \/>\nZuerst die StartFenster.java:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package miniMalprogramm;\r\n\r\nimport java.awt.BorderLayout;\r\nimport java.awt.Color;\r\nimport java.awt.Component;\r\nimport java.awt.Dimension;\r\nimport java.awt.Graphics;\r\nimport java.awt.Graphics2D;\r\nimport java.awt.Insets;\r\nimport java.awt.event.ActionEvent;\r\nimport java.awt.event.ActionListener;\r\nimport java.awt.image.BufferedImage;\r\nimport java.io.File;\r\nimport java.io.IOException;\r\nimport javax.imageio.ImageIO;\r\nimport javax.swing.BorderFactory;\r\nimport javax.swing.ButtonGroup;\r\nimport javax.swing.JButton;\r\nimport javax.swing.JCheckBox;\r\nimport javax.swing.JColorChooser;\r\nimport javax.swing.JFileChooser;\r\nimport javax.swing.JFrame;\r\nimport javax.swing.JMenu;\r\nimport javax.swing.JMenuBar;\r\nimport javax.swing.JMenuItem;\r\nimport javax.swing.JRadioButton;\r\nimport javax.swing.JSeparator;\r\nimport javax.swing.JSpinner;\r\nimport javax.swing.JToggleButton;\r\nimport javax.swing.JToolBar;\r\nimport javax.swing.SpinnerNumberModel;\r\n\r\npublic class StartFenster extends JFrame implements ActionListener {\r\n  public static void main(String[] s) {\r\n    new StartFenster();\r\n  }\r\n\r\n  Tafel tafel;\r\n  private JMenuBar menuBar;\r\n  private JMenu menuDatei;\r\n  private JMenuItem mneu, mladen, mspeichern, mBeenden;\r\n\r\n  private JToolBar auswahl;\r\n  private JToolBar seitenleiste;\r\n\r\n  JRadioButton kreisBtn;\r\n  JRadioButton quadratBtn;\r\n  JCheckBox fuellen;\r\n  JSpinner linienstaerke;\r\n  ButtonGroup werkzeugspitzen = new ButtonGroup();\r\n  JToggleButton pinselBtn;\r\n  JToggleButton radiererBtn;\r\n  private JButton farbwaehlerIcon;\r\n  private JButton farbwaehlerIconHG;\r\n\r\n  Color vgfarbe = Color.BLACK;\r\n  Color hgfarbe = Color.WHITE;\r\n  Color aktuelleFarbe = Color.BLACK;\r\n\r\n  public StartFenster() {\r\n    initialisiereStartFenster();\r\n  }\r\n\r\n  private void initialisiereStartFenster() {\r\n    this.setDefaultCloseOperation(EXIT_ON_CLOSE);\r\n    this.setBounds(0, 0, 500, 500);\r\n    this.setLocationRelativeTo(null);\r\n    this.setAlwaysOnTop(true);\r\n    this.setBackground(Color.white);\r\n    this.setTitle(\"Tafel\");\r\n    this.setLayout(new BorderLayout());\r\n\r\n    menuBar = new JMenuBar();\r\n    this.setJMenuBar(menuBar);\r\n    menuDatei = new JMenu();\r\n    menuDatei.setText(\"Datei\");\r\n    menuDatei.setMnemonic('d'); \/\/ setzt Tastaturk\u00fcrzel Alt+d\r\n    menuDatei.addActionListener(this);\r\n    menuBar.add(menuDatei);\r\n    mneu = new JMenuItem();\r\n    mneu.setText(\"Neu\");\r\n    mneu.setMnemonic('n');\r\n    mneu.setToolTipText(\"Neues Bild erstellen\");\r\n    mneu.addActionListener(this);\r\n    menuDatei.add(mneu);\r\n    JSeparator sep1 = new JSeparator();\r\n    menuDatei.add(sep1);\r\n    mladen = new JMenuItem();\r\n    mladen.setText(\"Laden\");\r\n    mladen.setMnemonic('l');\r\n    mladen.setToolTipText(\"Datei laden\");\r\n    mladen.addActionListener(this);\r\n    menuDatei.add(mladen);\r\n    mspeichern = new JMenuItem();\r\n    mspeichern.setText(\"Speichern\");\r\n    mspeichern.setMnemonic('s');\r\n    mspeichern.setToolTipText(\"Bild speichern\");\r\n    mspeichern.addActionListener(this);\r\n    menuDatei.add(mspeichern);\r\n    JSeparator sep2 = new JSeparator();\r\n    menuDatei.add(sep2);\r\n    mBeenden = new JMenuItem();\r\n    mBeenden.setText(\"Beenden\");\r\n    mBeenden.setMnemonic('e');\r\n    mBeenden.setToolTipText(\"Programm beenden\");\r\n    mBeenden.addActionListener(this);\r\n    menuDatei.add(mBeenden);\r\n\r\n    auswahl = new JToolBar();\r\n    auswahl.setPreferredSize(new Dimension(300, 30)); \/\/ PreferredSize = bevorzugte Gr\u00f6\u00dfe\r\n    auswahl.setFloatable(false);\r\n\r\n    kreisBtn = new JRadioButton(\"Kreis\");\r\n    kreisBtn.setSelected(true);\r\n    quadratBtn = new JRadioButton(\"Quadrat\");\r\n    werkzeugspitzen.add(kreisBtn);\r\n    werkzeugspitzen.add(quadratBtn);\r\n    auswahl.add(kreisBtn);\r\n    auswahl.add(quadratBtn);\r\n\r\n    fuellen = new JCheckBox(\"F\u00fcllen\");\r\n    auswahl.add(fuellen);\r\n\r\n    seitenleiste = new JToolBar();\r\n    seitenleiste.setPreferredSize(new Dimension(30, 200)); \/\/ PreferredSize = bevorzugte Gr\u00f6\u00dfe\r\n    seitenleiste.setFloatable(false);\r\n    seitenleiste.setOrientation(JToolBar.VERTICAL);\r\n    Insets nullMargin = new Insets(5, 7, 5, 5);\r\n    seitenleiste.setMargin(nullMargin);\r\n\r\n    pinselBtn = new JToggleButton(\"P\");\r\n    pinselBtn.setPreferredSize(new Dimension(20, 20));\r\n    pinselBtn.setSelected(true);\r\n    pinselBtn.setAlignmentX(CENTER_ALIGNMENT);\r\n    pinselBtn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));\r\n    pinselBtn.setSelected(true);\r\n    pinselBtn.addActionListener(this);\r\n    radiererBtn = new JToggleButton(\"R\");\r\n    radiererBtn.setPreferredSize(new Dimension(20, 20));\r\n    radiererBtn.setSelected(false);\r\n    radiererBtn.setAlignmentX(CENTER_ALIGNMENT);\r\n    radiererBtn.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));\r\n    radiererBtn.addActionListener(this);\r\n\r\n    farbwaehlerIcon = new JButton() {\r\n      public void paintComponent(Graphics g) {\r\n        super.paintComponent(g);\r\n        g.setColor(vgfarbe);\r\n        g.fillRect(20, 20, 20, 20);\r\n      }\r\n    };\r\n    farbwaehlerIcon.setPreferredSize(new Dimension(20, 20));\r\n    farbwaehlerIcon.addActionListener(this);\r\n    farbwaehlerIcon.setBackground(vgfarbe);\r\n    farbwaehlerIcon.setForeground(vgfarbe);\r\n    farbwaehlerIcon.setAlignmentX(CENTER_ALIGNMENT);\r\n\r\n    farbwaehlerIconHG = new JButton() {\r\n      public void paintComponent(Graphics g) {\r\n        super.paintComponent(g);\r\n        g.setColor(hgfarbe);\r\n        g.fillRect(20, 20, 20, 20);\r\n      }\r\n    };\r\n    farbwaehlerIconHG.setPreferredSize(new Dimension(20, 20));\r\n    farbwaehlerIconHG.addActionListener(this);\r\n    farbwaehlerIconHG.setBackground(hgfarbe);\r\n    farbwaehlerIconHG.setForeground(hgfarbe);\r\n    farbwaehlerIconHG.setAlignmentX(CENTER_ALIGNMENT);\r\n    seitenleiste.add(pinselBtn);\r\n    seitenleiste.add(radiererBtn);\r\n    seitenleiste.addSeparator();\r\n    seitenleiste.add(farbwaehlerIcon);\r\n    seitenleiste.add(farbwaehlerIconHG);\r\n    SpinnerNumberModel nummern = new SpinnerNumberModel(10.0, 1.0, 99.0, 1.0); \/\/ default, Minimum, Maximum,\r\n                                          \/\/ Schrittweite\r\n    linienstaerke = new JSpinner(nummern);\r\n    linienstaerke.setMinimumSize(new Dimension(50, 30)); \/\/ setzt die Mindestgr\u00f6\u00dfe ( Breite, H\u00f6he )\r\n    linienstaerke.setMaximumSize(new Dimension(50, 30)); \/\/ setzt die Maximalgr\u00f6\u00dfe\r\n    auswahl.add(linienstaerke);\r\n    this.add(auswahl, BorderLayout.PAGE_START);\r\n    this.add(seitenleiste, BorderLayout.WEST);\r\n\r\n    tafel = new Tafel(this);\r\n    this.add(tafel);\r\n    sichtbar();\r\n  }\r\n\r\n  private void sichtbar() {\r\n    this.setVisible(true);\r\n  }\r\n\r\n  public double getLinienstaerke() {\r\n    double staerke = (double) this.linienstaerke.getValue();\r\n    return staerke;\r\n  }\r\n\r\n  public Color getFarbe() {\r\n    return this.aktuelleFarbe;\r\n  }\r\n\r\n  @Override\r\n  public void actionPerformed(ActionEvent e) {\r\n    Object source = e.getSource();\r\n    if (source == farbwaehlerIcon) {\r\n      vgfarbe = JColorChooser.showDialog(this, \"Vordergrundfarbe w\u00e4hlen\", vgfarbe);\r\n      farbwaehlerIcon.setBackground(vgfarbe);\r\n      aktuelleFarbe = vgfarbe;\r\n      farbwaehlerIcon.repaint();\r\n    } else if (source == farbwaehlerIconHG) {\r\n      hgfarbe = JColorChooser.showDialog(this, \"Hintergrundfarbe w\u00e4hlen\", vgfarbe);\r\n      farbwaehlerIconHG.setBackground(hgfarbe);\r\n      aktuelleFarbe = hgfarbe;\r\n      farbwaehlerIconHG.repaint();\r\n    }\r\n    if (source == pinselBtn) {\r\n      pinselBtn.setSelected(true);\r\n      radiererBtn.setSelected(false);\r\n      aktuelleFarbe = vgfarbe;\r\n    }\r\n    if (source == radiererBtn) {\r\n      radiererBtn.setSelected(true);\r\n      pinselBtn.setSelected(false);\r\n      aktuelleFarbe = hgfarbe;\r\n    }\r\n    if (source == mneu)\r\n      tafel.neuesBild();\r\n\r\n    if (source == mladen)\r\n      loadPicture();\r\n\r\n    if (source == mspeichern)\r\n      savePicture(erstelleIMG(tafel));\r\n\r\n    if (source == mBeenden)\r\n      this.dispose();\r\n\r\n  }\r\n\r\n  public BufferedImage erstelleIMG(Component bild) \/\/ gibt ein img der zeichenfl\u00e4che an die Funktion savePicture\r\n                            \/\/ zur\u00fcck\r\n  {\r\n    BufferedImage img = new BufferedImage(bild.getWidth(), bild.getHeight(), BufferedImage.TYPE_INT_RGB);\r\n    Graphics2D g = img.createGraphics();\r\n    bild.paintAll(g);\r\n    g.dispose();\r\n    return img;\r\n  }\r\n\r\n  private void loadPicture() {\r\n    JFileChooser chooser = new JFileChooser();\r\n    chooser.setDialogType(JFileChooser.OPEN_DIALOG);\r\n\r\n    int rueckgabeWert = chooser.showOpenDialog(this);\r\n\r\n    if (rueckgabeWert == JFileChooser.APPROVE_OPTION) {\r\n      File file = chooser.getSelectedFile();\r\n      try {\r\n        tafel.image = ImageIO.read(file);\r\n      } catch (IOException e) {\r\n        e.printStackTrace();\r\n      }\r\n      tafel.bildGeladen = true;\r\n      tafel.repaint();\r\n    }\r\n\r\n  }\r\n\r\n  public void savePicture(BufferedImage img) \/\/\r\n  {\r\n    JFileChooser chooser = new JFileChooser();\r\n    chooser.setDialogType(JFileChooser.SAVE_DIALOG);\r\n\r\n    int rueckgabeWert = chooser.showSaveDialog(this);\r\n\r\n    if (rueckgabeWert == JFileChooser.APPROVE_OPTION) {\r\n      File file = chooser.getSelectedFile();\r\n      try {\r\n        ImageIO.write(img, \"png\", file);\r\n      } catch (IOException e) {\r\n        e.printStackTrace();\r\n      }\r\n    }\r\n  }\r\n\r\n  public void dispose() {\r\n    System.out.println(\"Tsch\u00fc\u00df\");\r\n    System.exit(0);\r\n  }\r\n}<\/pre>\n<p>Dann die Tafel.java<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package miniMalprogramm;\r\n\r\nimport java.awt.Color;\r\nimport java.awt.Graphics;\r\nimport java.awt.Graphics2D;\r\nimport java.awt.Point;\r\nimport java.awt.Shape;\r\nimport java.awt.event.MouseEvent;\r\nimport java.awt.event.MouseListener;\r\nimport java.awt.event.MouseMotionListener;\r\nimport java.awt.geom.Ellipse2D;\r\nimport java.awt.geom.Rectangle2D;\r\nimport java.awt.image.BufferedImage;\r\nimport java.util.ArrayList;\r\nimport javax.swing.JPanel;\r\n\r\npublic class Tafel extends JPanel implements MouseListener, MouseMotionListener {\r\n  private ArrayList&lt;Grafikobjekt&gt; virtuellerBildschirm = new ArrayList&lt;Grafikobjekt&gt;();\r\n  private int x = -10;\r\n  private int y = -10;\r\n  private StartFenster auswahl;\r\n\r\n  boolean bildGeladen = false;\r\n  public BufferedImage image;\r\n\r\n  public Tafel(StartFenster auswahl) {\r\n    this.auswahl = auswahl;\r\n    this.setBackground(Color.WHITE);\r\n    this.addMouseListener(this);\r\n    this.addMouseMotionListener(this);\r\n  }\r\n\r\n  public void paintComponent(Graphics g0) {\r\n    Graphics2D g = (Graphics2D) g0;\r\n    super.paintComponent(g);\r\n    if (bildGeladen == true) {\r\n      if (image != null)\r\n        g.drawImage(image, 0, 0, null); \/\/ ( img-Bild, x-Position, y-position, observer\r\n    }\r\n\r\n    for (int z = 0; z &lt; virtuellerBildschirm.size(); z++) {\r\n      Grafikobjekt go = virtuellerBildschirm.get(z);\r\n      g.setColor(go.getFarbe());\r\n      if (go.isGefuellt()) {\r\n        g.fill(go.getForm());\r\n      } else {\r\n        g.draw(go.getForm());\r\n      }\r\n    }\r\n  }\r\n\r\n  public void zeichneAufVirtuellenBildschirm(double dx, double dy) {\r\n    Shape werkzeug;\r\n\r\n    if (auswahl.quadratBtn.isSelected()) {\r\n      werkzeug = new Rectangle2D.Double(dx, dy, auswahl.getLinienstaerke(), auswahl.getLinienstaerke());\r\n    } else {\r\n      werkzeug = new Ellipse2D.Double(dx, dy, auswahl.getLinienstaerke(), auswahl.getLinienstaerke());\r\n    }\r\n    virtuellerBildschirm\r\n        .add(new Grafikobjekt(new Point(x, y), werkzeug, auswahl.fuellen.isSelected(), auswahl.getFarbe()));\r\n    this.repaint();\r\n  }\r\n\r\n  @Override\r\n  public void mouseDragged(MouseEvent e) {\r\n    System.out.println(\"Dragged\");\r\n    x = e.getX();\r\n    y = e.getY();\r\n\r\n    zeichneAufVirtuellenBildschirm(x, y);\r\n  }\r\n\r\n  @Override\r\n  public void mousePressed(MouseEvent e) {\r\n    System.out.println(\"Pressed\");\r\n    x = e.getX();\r\n    y = e.getY();\r\n\r\n    zeichneAufVirtuellenBildschirm(x, y);\r\n  }\r\n\r\n  @Override\r\n  public void mouseMoved(MouseEvent arg0) {\r\n    \/\/ TODO Automatisch generierter Methodenstub\r\n\r\n  }\r\n\r\n  @Override\r\n  public void mouseClicked(MouseEvent arg0) {\r\n    \/\/ TODO Automatisch generierter Methodenstub\r\n\r\n  }\r\n\r\n  @Override\r\n  public void mouseEntered(MouseEvent arg0) {\r\n    \/\/ TODO Automatisch generierter Methodenstub\r\n\r\n  }\r\n\r\n  @Override\r\n  public void mouseExited(MouseEvent arg0) {\r\n    \/\/ TODO Automatisch generierter Methodenstub\r\n\r\n  }\r\n\r\n  @Override\r\n  public void mouseReleased(MouseEvent arg0) {\r\n    \/\/ TODO Automatisch generierter Methodenstub\r\n\r\n  }\r\n\r\n  public void neuesBild() {\r\n    this.virtuellerBildschirm.clear();\r\n\r\n    bildGeladen = false;\r\n    image = null;\r\n\r\n    repaint();\r\n  }\r\n}\r\n<\/pre>\n<p>In der Grafikobjekt.java wurde nichts ver\u00e4ndert. Aber der Vollst\u00e4ndigkeit halber:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">package miniMalprogramm;\r\n\r\nimport java.awt.Color;\r\nimport java.awt.Point;\r\nimport java.awt.Shape;\r\n\r\nclass Grafikobjekt {\r\n  private Point koordinaten;\r\n  private Shape form;\r\n  private Color farbe;\r\n  private boolean gefuellt;\r\n\r\n  public Grafikobjekt(Point p, Shape st, boolean cb, Color f) {\r\n    this.koordinaten = p;\r\n    this.form = st;\r\n    this.gefuellt = cb;\r\n    this.farbe = f;\r\n  }\r\n\r\n  public Point getKoordinaten() {\r\n    return this.koordinaten;\r\n  }\r\n\r\n  public void setKoordinaten(Point koordinaten) {\r\n    this.koordinaten = koordinaten;\r\n  }\r\n\r\n  public Shape getForm() {\r\n    return this.form;\r\n  }\r\n\r\n  public boolean isGefuellt() {\r\n    return this.gefuellt;\r\n  }\r\n\r\n  public Color getFarbe() {\r\n    return this.farbe;\r\n  }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Da der Quellcode mittlerweile recht lang ist, f\u00fchre ich zugunsten der \u00dcbersichtlichkeit zuerst nur den Quellcode an der neu ist. Ganz am Ende f\u00fcge ich dann den gesamten Quellcode hinzu. Um ein Men\u00fc hinzuzuf\u00fcgen stellt Swing uns die Klasse JMenuBar zur Verf\u00fcgung. Das Vorgehen ist \u00e4hnlich wie mit den anderen Swing Komponenten. Zuerst f\u00fcgen wir [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/posts\/513"}],"collection":[{"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/comments?post=513"}],"version-history":[{"count":10,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/posts\/513\/revisions"}],"predecessor-version":[{"id":886,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/posts\/513\/revisions\/886"}],"wp:attachment":[{"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/media?parent=513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/categories?post=513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/freizone.net\/java-einfach-lernen\/wp-json\/wp\/v2\/tags?post=513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}