Zeichnen in Swing - Frage

GUI-Programmer

Top Contributor
Gutes Tutorial. Ich habe grundsätlich nichts daran auszusetzen. Ich persönlich habe bis jetzt noch nicht mit Shapes programmiert. Vielleicht könntet ihr folgenden Code mal kritisch beurteilen, und mir sagen, was ich verbessern sollte:

Java:
package MVC;


import javax.swing.*;
import java.awt.*;

/**
 * Klasse Grafik
 * 
 * Hier befinden sich alle grafischen Komponenten.
 * 
 * @author GUI-Programmer
 * @version 10.07.2011 02:17
 */
public class Grafik extends JPanel {
    // Attribute
    private Programm prog;
    private Steuerung strg;
    
    protected String
        status;
        
    protected JButton
        button$1, button$2, button$3;
        
    protected Zeichnung
        zeichnung;
        
    protected JLabel
        label$unsichtbar;
    
    
    // Konstruktor
    public Grafik(Programm p) {
        // Attribute initialisieren
        attributeInitialisieren(p);
        
        // Grafik einstellen
        setSize(500,500);
        setBackground(Color.blue);
        setLayout(null);
        
        // Grafikkomponenten einstellen und Hinzufügen
        komponentenEinstellenUndHinzufuegen();
    }
    
    
    // Methoden
    /** 
     * Die Attribute werden initialisiert.
     */
    private void attributeInitialisieren(Programm p) {
        // Objekte der MVC-Klassen
        prog = p;
        strg = new Steuerung(this, prog);
        
        // "Normale" Attriute
        status = "Mein Programm 1";
        
        // Grafische Komponenten
        systemLookAndFeelVerwenden();
        button$1 = new JButton();
        button$2 = new JButton();
        button$3 = new JButton();
        zeichnung = new Zeichnung();
        label$unsichtbar = new JLabel();
    }
    
    /** 
     * Diese Methode versucht das Aussehen des Systems zu benutzen.
     */
    private void systemLookAndFeelVerwenden() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch(Exception ex) {
            status = "Fehler: "+ex.toString()+" - SystemLookAndFeel"+
                     "konnte nicht verwendet werden!";
            System.out.println(status);
        }
    }
    
    /** 
     * Die Komponenten werden eingestellt und der Klasse hinzugefügt
     * (wegen Vererbung von JPanel möglich)
     */
    private void komponentenEinstellenUndHinzufuegen() {
        add(zeichnung);
        
        button$1.setText("Knopf 1");
        button$1.addActionListener(strg);
        add(button$1);
        button$1.setBounds(250,50,150,30);
        
        button$2.setText("Knopf 2");
        button$2.addActionListener(strg);
        add(button$2);
        button$2.setBounds(50,400,120,30);
        
        button$3.setText("Knopf 3");
        button$3.addActionListener(strg);
        add(button$3);
        button$3.setBounds(200,235,100,30);
        
        label$unsichtbar.setVisible(false);
        label$unsichtbar.setFont(new java.awt.Font("Microsoft Sans Serif", 1, 25));
        label$unsichtbar.setForeground(new java.awt.Color(200, 255, 0));
        label$unsichtbar.setText("Zeichenfläche Canvas ist unsichtbar");
        add(label$unsichtbar);
        label$unsichtbar.setBounds(15, 5, 450, 40);
    }
    
    
    /** 
     * Dient dazu, der ausführenden Klasse (Applikation / Applet) den 
     * "aktuellen Stand" zu übergeben.
     */
    public String statusGeben() {
        return status;
    }
    
    /** 
     * Ermöglicht anderen Klassen, wie etwa Steuerung, best. Oberflächen
     * zeichnen zu lassen 
     */
    public void zeichneAufCanvas(String s) {
        zeichnung.zeichne(s);
    }
    
    
    // Innere Klasse
    /**
     * Innere Klasse Zeichnung
     * 
     * Diese Klasse dient als Zeichenfläche für simple Dinge, wie etwa
     * Strings, Rechtecke, evtl. Bilder...
     */
    class Zeichnung extends JComponent {
        // Attribute
        private String bildschirm;
        private Image image$minus2;
        private MediaTracker mt;
        
        // Konstruktor
        public Zeichnung() {
            // Attribute initialisieren
            attributeInitialisieren();
            
            // Zeichnung einstellen
            setBackground(Color.blue);
            setBounds(0,0,500,500);
            
            // Bilder werden vollständig geladen
            bilderLaden();
        }
        
        
        // Methoden
        /** Aufruf in: Konstruktor Zeichnung() */
        private void attributeInitialisieren() {
            // "Normale" Attriute
            bildschirm = "Weiss";
            
            // Images
            try {
                image$minus2 = getToolkit().getImage("Resources/bild 1.jpg");
                /* Alternative:
                   image$minus2 = new javax.swing.ImageIcon(getClass().
                   getResource("/Resources/bild 1.jpg")).getImage();
                */
            }
            catch(Exception ex) {
                status = ex.toString();
                System.out.println(status);
            }
        }
        
        /** 
         * Alle Pixel der Images werden vollständig geladen.
         */
        private void bilderLaden() {
            mt = new MediaTracker(this);
            mt.addImage(image$minus2,0);
            try {
                mt.waitForAll();
            }
            catch(InterruptedException ex) {
                status = ex.toString();
                System.out.println(status);
            }
        }
        
        /** 
         * >siehe zeichneAufCanvas in Oberklasse
         */
        private void zeichne(String b) {
            bildschirm = b;
            repaint();
        }
        
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D)g;
            
            g2d.setColor(Color.white);
            g2d.drawRect(5, 5, 490, 490);
            g2d.drawRect(10, 10, 480, 480);
            g2d.setFont(new Font("Tahoma", 1, 20));
            g2d.drawString("Zeichenfläche Canvas", 15, 40);
            if(bildschirm.equals("Weiss")) {
                g2d.setColor(Color.white);
                g2d.fillRect(50, 50, 100, 100);
            }
            if(bildschirm.equals("Schwarz")) {
                g2d.setColor(Color.black);
                g2d.fillRect(50, 50, 100, 100);
            }
            if(bildschirm.equals("Bild")) {
                g2d.setColor(Color.pink);
                g2d.drawRect(80, 80, 50, 50);
                g2d.drawRect(120, 120, 50, 50);
                g2d.drawImage(image$minus2, 400, 400, this);
            }
            if(bildschirm.equals("Figuren")) {
                int xy = 50;
                g2d.setColor(Color.red);
                g2d.drawLine(10 + xy, 10 + xy, 80, 80);
                g2d.drawRect(110 + xy, 10 + xy, 80, 80); 
                g2d.draw3DRect(210 + xy, 10 + xy, 80, 80, true); 
                g2d.drawRoundRect(10 + xy, 110 + xy, 80, 80, 10, 10);
                g2d.drawArc(110 + xy, 110 + xy, 80, 80, 45, 270);
                g2d.drawOval(210 + xy, 110 + xy, 80, 80);
                int p1x[] = {10 + xy, 50, 90, 90, 50, 10};
                int p1y[] = {210 + xy, 240, 210, 290, 260, 290}; 
                g2d.drawPolygon(p1x, p1y, 6); 
                int p2x[] = {210, 250, 290, 290, 250, 210};
                int p2y[] = {210, 240, 210, 290, 260, 290};
                g2d.drawPolyline(p2x, p2y, 6);
            }
            if(bildschirm.equals("Teilkreis")) {
                g2d.setColor(Color.green);
                g2d.fillArc(100,100,100,100,0,270);
                g2d.drawArc(220,100,100,100,0,270);
            }
        }
    }
}

Wie ihr erkennen könnt, fehlen einige Bestandteile, wie etwa die Klassen Programm und Steuerung. Doch auf denen kommt es mir nicht an. Auch eine ausführbare Klasse, wie etwa ein JFrame oder ein JApplet fehlt.
 
Zuletzt bearbeitet von einem Moderator:

André Uhres

Top Contributor
Hallo GUI-Programmer,

von der Maltechnik her scheint mir das so weit das in Ordnung zu sein, außer dass das "new Font(..)" nicht in den Malcode gehört, weil dort möglichst keine neuen Objekte erzeugt werden sollten. Was man am Malcode noch verbessern könnte, hängt weitgehend von der Anwendung ab.
Beim Nullayout bin ich jedoch eher skeptisch. Layoutmanager sind meistens vorzuziehen. Auch würde ich beim "Grafik"-Panel nicht "setSize", sondern "setPreferredSize" nehmen, was uns z.B. erlaubt, einen JFrame mit "pack()" auf die ideale Größe zu bringen (was demnach ebenfalls eine Layoutfrage ist).

Gruß,
André
 

GUI-Programmer

Top Contributor
BEITRAG IST NUN HIER !!!

OK! Danke für die Kritik.

Werde das mit den Variablennamen auf jeden Fall umsetzten, z.B. anstatt von button$1 eher button1.
Frage: wäre es auch sinnvoll z.B. den JButton so zu bennen: button_1 ? Oder ähnelt das zu sehr einer Konstante (--> final)?
Habe nämlich die Erfahrung gemacht, dass man leicht durcheinander kommt, wenn man bspw. einen JButton hat, und diesen dann buttonEinstellungen oder buttonBestaetigen nennt.

Das mit den Mediatracker habe ich mir vorher auch schon überlegt, mir aber gedacht, vielleicht brauche ich ihn noch anderswo im Code, was nicht der Fall war.

Das ich new Font(...) verwende, werde ich wahrscheinlich teilweise beibehalten, da ich ich nicht für jede Schriftart einen eigenen Font erstellen möcht, allerdings für die am meisten verwendeten dann schon.

setSize(...) werde ich auch weiterhin verwenden, da ich, falls die ausführende Klasse ein JFrame ist, das JFrame immer genau in der Mitte des Bildschirms positioniere mit den Werten der Bildschirmgröße:
Java:
public class Applikation extends JFrame {
//......
private void positionieren() {
        // Bildschirmgröße wird ermittelt
        int sreenWidth = new Double(java.awt.Toolkit.getDefaultToolkit().getScreenSize().
                                getWidth()).intValue();
        int sreenHeight = new Double(java.awt.Toolkit.getDefaultToolkit().getScreenSize().
                                getHeight()).intValue();
        // Breite und Größe wird mit Rändern des JFrames' angepasst
        int Width = 500 + getInsets().left + getInsets().right;
        int Height = 500 + getInsets().top + getInsets().bottom;
        // X- und Y-Koordinaten werden bestimmt
        int X = (sreenWidth/2)-(Width/2);
        int Y = (sreenHeight/2)-(Height/2);
        // Das JFrame wird mit den ermittelten Werten positioniert
        setBounds(X, Y, Width, Height);
    }
//.......
}

Mit Layout habe ich mich noch nicht sehr beschäftigt, außer mal GridLayout und bei NetBeans das "Free Design", bei den ein eigenes Layout erstellt (mit horizontaler und vertikaler LayoutGroup) wird. Doch das selbst "per Hand" zu programmieren habe ich bis jetzt noch nicht gemacht, daher NullLayout.

Also wie bereits gesagt, danke, bin jederzeit für Verbesserungsvorschläge da, und Frage wegen Variablennamen noch beantworten. :)
 

Marco13

Top Contributor
Man könnte sagen, dass das mit den Variablennamen subjektiv ist. Aber nur in gewissen Grenzen. Sowas wie
Code:
private JButton button1;
private JButton button2;
private JButton button3;
private JButton button4;
...
private JButton button1325;
macht nicht viel Sinn. Einige haben auch die (für mich kaum nachvollziehbare, aber vielleicht auf dem was "Ungarische Notation" genannt wird basierende) Angewohnheit, den Typ als Abkürzung an den Nmn hn Vkle (Namen ohne Vokale) vorne dran zu stellen:
Code:
private JButton btnStart;
private JButton btnEnd;
private JButton btnConf;
private JButton btnSmLngName;

private JCheckBox cbThisDoesNot;
private JComboBox cbMakeAnySns;

Code wird prinzipbedingt höchstens EINmal geschrieben, aber potentiell hunderte Male gelesen (und eventuell von psychopathischen Kettensägenmördern, dessen sollte man sich immer bewußt sein ;) ). Deswegen finde ich, dass man einen Start-Button ruhig "startButton" und eine Confirm-CheckBox ruhig confirmCheckBox nennen kann. Aber wie gesagt: Das ist teilweise subjektiv.

Aber das mit den MediaTracker gilt auch allgemein: Wenn man einen Button NUR lokal in einer Methode erstellt und verdrahtet, braucht er kein Field zu sein. Also statt sowas wie
Java:
class SomeClass
{
    private JButton button1;
    private JButton button2;
    private JButton button3;

    private void createComponents() {
        button1 = new JButton();
        button2 = new JButton();
        button3 = new JButton();
    }

    private void initComponents()
    {
        button1.setText("Knopf 1");
        button1.addActionListener(strg);
        add(button1);
        
        button2.setText("Knopf 2");
        button2.addActionListener(strg);
        add(button2);
        
        button3.setText("Knopf 3");
        button3.addActionListener(strg);
        add(button3);
    }

Würde ich eher schreiben

Java:
class SomeClass
{
    private void createButtons() 
    {
        JButton button1 = new JButton();
        button1.setText("Knopf 1");
        button1.addActionListener(strg);
        add(button1);
        
        JButton button2 = new JButton();
        button2.setText("Knopf 2");
        button2.addActionListener(strg);
        add(button2);
        
        JButton button3 = new JButton();
        button3.setText("Knopf 3");
        button3.addActionListener(strg);
        add(button3);
    }
(mit sprechenderen Namen natürlich), was man ggf. noch feiner aufdröseln kann, im Sinne von
Java:
    private void createButtons() 
    {
        createStartButton();
        createEndButton();
        createConfirmButton();
    }
Besonders wenn man anonyme Listener verwendet oder das erstellen der Buttons "aufwändig" (d.h. mehrere Zeilen lang) ist.

Aber da hat man viele Freiheitsgrade, teilweise ist es subjektiv, und meistens vom konkreten Anwendungsfall abhängig. Im Fall mit den Buttons würde man für eine "richtige" Anwendung wohl eher Actions verwenden, aber das sollte ja nur ein Beispiel sein.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Frage zu Zeichnen in Swing Tutorial AWT, Swing, JavaFX & SWT 4
I Graph mit Swing zeichnen AWT, Swing, JavaFX & SWT 8
F Java Swing Rechteck in JPanel zeichnen AWT, Swing, JavaFX & SWT 7
T Swing / Kreis zeichnen AWT, Swing, JavaFX & SWT 2
Helgon Swing Mit Swing zeichnen / NetBeans GUI AWT, Swing, JavaFX & SWT 11
M Swing Warum öffnen sich beim Zeichnen mit Swing plötzlich zwei Fenster? AWT, Swing, JavaFX & SWT 5
I swing fenster neu zeichnen, wenn überdeckt AWT, Swing, JavaFX & SWT 8
E Rauten per Swing zeichnen lassen AWT, Swing, JavaFX & SWT 5
P Zeichnen von Ovalen in Swing (4 Gewinnt) AWT, Swing, JavaFX & SWT 3
B Zeichnen in Swing - Jede Menge Fragen! AWT, Swing, JavaFX & SWT 2
Psypsy Bewegtes zeichnen in Swing AWT, Swing, JavaFX & SWT 24
T Swing Component in Graphics zeichnen AWT, Swing, JavaFX & SWT 4
M Swing Zeichnen AWT, Swing, JavaFX & SWT 3
byte Swing: Ebenen zeichnen AWT, Swing, JavaFX & SWT 3
R Swing + Zeichnen Problem AWT, Swing, JavaFX & SWT 7
I Swing-Komponenten skaliert zeichnen AWT, Swing, JavaFX & SWT 6
F Effizientes zeichnen mit Swing AWT, Swing, JavaFX & SWT 9
B Zeichnen in Swing AWT, Swing, JavaFX & SWT 17
S Thread.sleep() beim Zeichnen auf Swing Komponenten? AWT, Swing, JavaFX & SWT 6
V Zeichnen mit Swing AWT, Swing, JavaFX & SWT 3
W Zeichnen auf eine Swing-Komponente AWT, Swing, JavaFX & SWT 5
G Zeichnen mit Swing AWT, Swing, JavaFX & SWT 5
M Mandelbrot mit BigDecimal erstellen und in der UI zeichnen, funktionierte nicht. AWT, Swing, JavaFX & SWT 1
H JavaFX Canvas neu zeichnen anstoßen AWT, Swing, JavaFX & SWT 34
H Transparent zeichnen mit drawImage in paintComponent Methode AWT, Swing, JavaFX & SWT 3
N JavaFX Unicode zeichnen in javafx Label verwenden AWT, Swing, JavaFX & SWT 2
G 2D-Grafik Grafik in zwei verschiedenen Fenstern gleichzeitig zeichnen AWT, Swing, JavaFX & SWT 9
S Event Handling Neu zeichnen nur wenn Berechnung fertig ist AWT, Swing, JavaFX & SWT 4
W JavaFX Ich kann keinen Kreis richtig zeichnen AWT, Swing, JavaFX & SWT 8
CptK Funktionsgraphen effizient zeichnen und nur Teile von JPanel erneuern AWT, Swing, JavaFX & SWT 2
G Dreieck aus Pixeln zeichnen AWT, Swing, JavaFX & SWT 8
N Mit KeyListener ein rechteck zeichnen AWT, Swing, JavaFX & SWT 9
B 2D-Grafik paintcomponent Probleme beim zeichnen AWT, Swing, JavaFX & SWT 10
Z Swing Graph zeichnen lassen AWT, Swing, JavaFX & SWT 16
O Kann kei neues Panel zum zeichnen aufrufen... AWT, Swing, JavaFX & SWT 4
L Swing zeichnen AWT, Swing, JavaFX & SWT 14
S GUI Kreuz zeichnen und Position ausgeben AWT, Swing, JavaFX & SWT 3
S GUI Kreis zeichnen AWT, Swing, JavaFX & SWT 13
S Swing Rechteck über JTable zeichnen (per MouseListener) AWT, Swing, JavaFX & SWT 1
L Swing Ein Rechteck in ein Grid Zeichnen AWT, Swing, JavaFX & SWT 5
L JavaFX Animation, erst zeichnen dann anzeigen AWT, Swing, JavaFX & SWT 4
K Mehrere Linien zeichnen AWT, Swing, JavaFX & SWT 8
E Transparent zeichnen AWT, Swing, JavaFX & SWT 2
S AWT Probleme beim Zeichnen AWT, Swing, JavaFX & SWT 3
T Tic Tac Toe - GUI Linien zeichnen AWT, Swing, JavaFX & SWT 14
C Applet Zeichnen über Button-Click AWT, Swing, JavaFX & SWT 13
Soloeco Graph zeichnen AWT, Swing, JavaFX & SWT 1
G Zeichnen Programm AWT, Swing, JavaFX & SWT 1
H Swing + Paint: Mehrere Objekte zeichnen lassen AWT, Swing, JavaFX & SWT 3
W Swing JPanel nur einmal nach mehreren Änderungen neu zeichnen AWT, Swing, JavaFX & SWT 1
D Quadrat, Rechteck zeichnen AWT, Swing, JavaFX & SWT 3
K Probleme beim zeichnen mit paintComponent() AWT, Swing, JavaFX & SWT 1
JG12111989 mehrere Polyline-Objekte zeichnen AWT, Swing, JavaFX & SWT 3
A Swing JRadioButton zeichnen nicht AWT, Swing, JavaFX & SWT 4
J Swing Vertikales Zeichnen eines Strings mit Java2D AWT, Swing, JavaFX & SWT 1
7 JavaFX Problem beim Zeichnen eines Dreiecks in einem GUI AWT, Swing, JavaFX & SWT 6
P 2D-Grafik Bogen(Arc) zwischen zwei Punkten zeichnen AWT, Swing, JavaFX & SWT 2
KilledByCheese Swing 2D JLabel Array Maze zeichnen AWT, Swing, JavaFX & SWT 2
S Parallele Linien zeichnen AWT, Swing, JavaFX & SWT 5
J Linien auf JPanel zeichnen AWT, Swing, JavaFX & SWT 3
P AWT Canvas freihändig zeichnen AWT, Swing, JavaFX & SWT 1
llabusch Linien in JPanel zeichnen AWT, Swing, JavaFX & SWT 6
S passende PaintComponent ? Zeichnen in TextArea mit Scrollpane ? AWT, Swing, JavaFX & SWT 2
I Applet BlueJ Applet - Bild mit if-Schleife zeichnen lassen AWT, Swing, JavaFX & SWT 16
L JavaFX JavafX Timelime zeichnen und schön stylen? AWT, Swing, JavaFX & SWT 2
I JFrame neu zeichnen, nicht überzeichnen! AWT, Swing, JavaFX & SWT 2
I Spielsteine zeichnen und entfernen AWT, Swing, JavaFX & SWT 3
H JavaFX Freezes beim Zeichnen mit Canvas AWT, Swing, JavaFX & SWT 3
H Swing BufferedImage zeichnen AWT, Swing, JavaFX & SWT 1
M JFreeChart neu zeichnen sich Wenn Jtable sich ändert AWT, Swing, JavaFX & SWT 5
S 2D-Grafik MouseDragged Linien zeichnen AWT, Swing, JavaFX & SWT 4
M Zeichnen ohne vorherige Linien zu löschen AWT, Swing, JavaFX & SWT 2
T Problem beim Zeichnen von Rechteck AWT, Swing, JavaFX & SWT 3
I Text zur Linie zeichnen AWT, Swing, JavaFX & SWT 1
I Pfeil zeichnen am Ende einer Linie AWT, Swing, JavaFX & SWT 1
D 2D-Grafik Inhalt eines Graphics in anderes Graphics zeichnen.... AWT, Swing, JavaFX & SWT 3
F Zeichnen des Button AWT, Swing, JavaFX & SWT 4
B Zeichnen mit paintComponent? Oder anders? AWT, Swing, JavaFX & SWT 15
C Swing Aus verschiedenen Klassen zeichnen. AWT, Swing, JavaFX & SWT 2
C Swing BufferedImage zeichnen und JLabels setzen. AWT, Swing, JavaFX & SWT 17
M Kein Zeichnen der Figuren auf JPanel AWT, Swing, JavaFX & SWT 4
J JButton neu zeichnen lassen AWT, Swing, JavaFX & SWT 9
S Quadrat auf Frame zeichnen AWT, Swing, JavaFX & SWT 2
P Image oder Icon auf Tooltip zeichnen AWT, Swing, JavaFX & SWT 4
C Graphics Objekt in Zeitschleife zeichnen AWT, Swing, JavaFX & SWT 4
X Swing JPanel mehrere Ebenen zeichnen AWT, Swing, JavaFX & SWT 13
G Zeichnen auf eine schwergewichtige Komponente? AWT, Swing, JavaFX & SWT 0
G Mehrere Strings um Kreis zeichnen und positionieren AWT, Swing, JavaFX & SWT 0
P SWT Nebula Gallery - Bildbereiche zeichnen AWT, Swing, JavaFX & SWT 3
A Swing Paint mit Button Clear den Hintergrund säubern um wieder zeichnen zu können AWT, Swing, JavaFX & SWT 2
A 2D-Grafik Zeichnen einer sich bewegenden Box mit BufferStrategy zieht Spur AWT, Swing, JavaFX & SWT 2
T AWT Bild laden und transparent zeichnen AWT, Swing, JavaFX & SWT 2
M JLabel über JButtons zeichnen AWT, Swing, JavaFX & SWT 4
J JApplet und Zeichnen AWT, Swing, JavaFX & SWT 8
P 2D-Grafik NPE beim Zeichnen auf Graphics g AWT, Swing, JavaFX & SWT 8
4 Swing Graphen selber zeichnen AWT, Swing, JavaFX & SWT 2
T Über mehrere Panel zeichnen AWT, Swing, JavaFX & SWT 2
T Zeichnen von getSubimage funktioniert nicht AWT, Swing, JavaFX & SWT 7
M Bilder zeichnen, NullPointer Exception AWT, Swing, JavaFX & SWT 3
N JPanel neu zeichnen AWT, Swing, JavaFX & SWT 10

Ähnliche Java Themen

Neue Themen


Oben