KEIN Swing-Tutorial

Bitte aktiviere JavaScript!
Als kleinen Einstieg zum Punkt aus diesem Thread. Ich dachte da an einige einfache, compilierbare Schnipsel, jeweils jeweils auf minimale Weise (!) einige Funktionen anbieten, nach denen immer wieder mal gefragt wird.

GANZ grob:

- Einfach etwas zeichnen
(Frame mit von JPanel abgeleiteter Klasse mit überschriebener paintComponent)

- Mehrere verschiedene Objekte zeichnen
(Wie oben, aber mit einer List<Drawable> in der JPanel-Klasse)

- Anklickbare Objekte zeichnen
- Verschiebbare Objekte zeichnen
- Animierte Objekte zeichnen

...

Die Schwierigkeit bestünde da für mich weniger darin, das zu machen, sondern dem Abstraktionsdrang entgegenzuwirken und das ganze so rudimentär und minimalistisch wie möglich zu machen, damit jede einzelne "Stufe" noch nachvollziehbar bleibt, und man sich nicht mit den Dingen konfrontiert sieht, die eigentlich erst bei komplexeren Programmen relevant werden. Es ginge ja wirklich um Beispiele, wo man 100 Zeilen (notfalls auch unverstanden) rauskopiert und nur an so wenigen Stellen wie möglich solche Kommentare wie "// Hier dein Zeug zeichnen" mit eigenem Code ergänzt.
 
A

Anzeige




Schau mal hier —> (hier klicken)
Ist der Thread als "Lieber Tagebuch, ich werde bald..." oder als "Schmeißt mal Vorschläge rein..." zu verstehen?
Man könnte ja ein Beispiel von "Systemauslastung-Graph-Zeichnen-Ding" brigen, wo man eben erkennen sollte, dass die pain-Methode nur dazu gedacht ist das was da ist zu zeichnen und die Berechnungen woanders erfolgen sollten.
 
Hm ich habe den Thread mal hier im Entwurfsbereich aufgemacht, damit es einen Platz gibt, wo ich oder jemand anderes bei Gelegenheit solche Schnipsel posten kann, und sie dann von anderen zerrissen werden können (in noch kleinere Schnipsel :D ) bevor sie in die FAQ wandern.... Nicht OK? ???:L

@XHelp: Das mit dem Graphen ist einerseits etwas spezifischer, als das, was ich meinte: Ich dachte wirklich an sowas wo z.B. einfach eine von JPanel abgeleitete Klasse in ein JFrame gelegt wird, und dort in der paintComponent eben steht
// Hier kannst du das Graphics zum Malen verwenden (und NUR hier ;) )
und wo eben NICHT irgendwo getGraphics aufgerufen wird, dafür aber super.paintComponent, und wo das GUI mit den SwingUtilities im EDT erstellt wird... Dann darauf aufbauen eben Beispiele wie oben angedeutet, z.B. auch sowas wie "Mit einem Buttonklick etwas zeichnen lassen"... Und wenn dann mal wieder jemand in einem AWT-Frame paint überschreibt oder im der actionPerformed mit getGraphics rumpfuscht, kann man ihn darauf verweisen, und er hat ein template, wo schonmal viele Fehler vermieden sind.

Andererseits ist eine Sache, die auch immer wieder angefragt wird: Ein Funktionsplotter :D ...
 
Die Schwierigkeit bestünde da für mich weniger darin, das zu machen, sondern dem Abstraktionsdrang entgegenzuwirken und das ganze so rudimentär und minimalistisch wie möglich zu machen...
Aber nicht zu rudimentär, bitte. ;) Ein gewisser Grad an Abstraktion sollte schon enthalten sein. Von daher finde ich den Ansatz gut, das hier gemeinschaftlich zu erstellen und zu diskuiteren.
Das wären Beispiele, die sicherlich oft verlinkt würden. :D
 
Wenn man einfach nur etwas zeichnen will:
Java:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

// Ein JPanel, bei dem die paintComponent-Methode überschrieben ist,
// so dass man in das JPanel etwas reinmalen kann.
class PaintPanel extends JPanel
{
	@Override
	public void paintComponent(Graphics graphics)
	{
		super.paintComponent(graphics);
		Graphics2D g = (Graphics2D)graphics;
		
		// Hier die Zeichenbefehle einfügen:
		g.setColor(Color.BLACK);
		g.drawString("Hello, Swing!", 60, 50);
	}
}


public class SwingSimplePaint 
{
	public static void main(String args[])
	{
		// Das Erzeugen des GUIs muss auf dem 
		// Swing-Thread ausgeführt werden:
		SwingUtilities.invokeLater(new Runnable() 
		{
			@Override
			public void run() 
			{
				// Fenster erstellen
				JFrame frame = new JFrame("Simple Paint");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				
				// PaintPanel erstellen und in das Fenster legen
				PaintPanel paintPanel = new PaintPanel();
				paintPanel.setPreferredSize(new Dimension(200, 100));
				frame.getContentPane().add(paintPanel);
				
				// Fenster zentrieren und anzeigen
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
}

Wenn man durch einen Button-Klick etwas zeichnen will:
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

// Ein JPanel, bei dem die paintComponent-Methode überschrieben ist, und
// bei dem man ein Objekt setzen kann, das gezeichnet werden soll.
class ShapePaintPanel extends JPanel
{
	// Das Objekt, das gezeichnet werden soll
	private Shape objectToPaint = null;
	
	// Setzt das Objekt, das gezeichnet werden soll, und
	// löst ein Neuzeichnen aus.
	public void setObjectToPaint(Shape objectToPaint)
	{
		this.objectToPaint = objectToPaint;
		repaint();
	}
	
	@Override
	public void paintComponent(Graphics graphics)
	{
		super.paintComponent(graphics);
		Graphics2D g = (Graphics2D)graphics;
		
		// Hier wird das zu zeichnende Objekt gemalt:
		if (objectToPaint != null)
		{
			g.setColor(Color.BLACK);
			g.draw(objectToPaint);
		}
	}
}

//Die Hauptklasse für das GUI: Ein Panel, das die weiteren
//GUI-Komponenten enthält
class MainPanel extends JPanel
{
	public MainPanel()
	{
		setLayout(new BorderLayout());
		
		// PaintPanel erstellen und in die Mitte legen
		final ShapePaintPanel shapePaintPanel = new ShapePaintPanel();
		shapePaintPanel.setPreferredSize(new Dimension(200, 100));
		add(shapePaintPanel, BorderLayout.CENTER);
		
		// Button erstellen und and den unteren Rand legen
		JButton button = new JButton("Paint object");
		add(button, BorderLayout.SOUTH);
		
		// Wenn der Button geklickt wird, wird das zu zeichnende 
		// Objekt erstellt und an das ObjectPaintPanel übergeben
		button.addActionListener(new ActionListener() 
		{
			@Override
			public void actionPerformed(ActionEvent arg0) 
			{
				Shape objectToPaint = new Rectangle(50,50,100,20);
				shapePaintPanel.setObjectToPaint(objectToPaint);
			}
		});
	}
}


//Die Hauptklasse mit der main-Methode. 
public class SwingPaintOnButtonClick 
{
	public static void main(String args[])
	{
		// Das Erzeugen des GUIs muss auf dem 
		// Swing-Thread ausgeführt werden:
		SwingUtilities.invokeLater(new Runnable() 
		{
			@Override
			public void run() 
			{
				// Fenster erstellen
				JFrame frame = new JFrame("Paint on button click");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.getContentPane().setLayout(new BorderLayout());
				
				// Hauptpanel erstellen und in den Frame legen
				MainPanel mainPanel = new MainPanel();
				frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
				
				// Fenster zentrieren und anzeigen
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}
}

Wenn man verschiedene Objekte zeichnen will:
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

//Ein Interface für alle Objekte, die gezeichnet werden können. 
interface Paintable
{
  void paintObject(Graphics2D g);
}


//Ein Smiley, der gezeichnet werden kann. 
class Smiley implements Paintable
{
  private int x;
  private int y;
  
  public Smiley(int x, int y)
  {
      this.x = x;
      this.y = y;
  }
  
  // Implementierung des Paintable-Interfaces 
  public void paintObject(Graphics2D g)
  {
      g.setColor(Color.YELLOW);
      g.fillOval(x, y, 50, 50);
      g.setColor(Color.BLACK);
      g.fillOval(x+15, y+15, 8, 8);
      g.fillOval(x+30, y+15, 8, 8);
      g.draw(new Arc2D.Double(x+10,y+10,30,30,190,160,Arc2D.OPEN));
  }
}



// Ein JPanel, bei dem die paintComponent-Methode überschrieben ist, und 
// das eine Liste von Objekten speichert, die gezeichnet werden können
class GeneralPaintPanel extends JPanel
{
	// Die Liste der Paintablen Objekte, und Methoden um solche
	// Objekte hinzuzufügen oder zu entfernen.
	private List<Paintable> paintables = new ArrayList<Paintable>();

	public void addPaintable(Paintable paintable)
	{
		paintables.add(paintable);
		repaint();
	}

	public void removePaintable(Paintable paintable)
	{
		paintables.remove(paintable);
		repaint();
	}
	
	@Override
	public void paintComponent(Graphics graphics)
	{
		super.paintComponent(graphics);
		Graphics2D g = (Graphics2D)graphics;
		g.setRenderingHint(
			RenderingHints.KEY_ANTIALIASING, 
			RenderingHints.VALUE_ANTIALIAS_ON);
		for (Paintable paintable : paintables)
		{
			paintable.paintObject(g);
		}
	}
}

//Die Hauptklasse für das GUI: Ein Panel, das die weiteren
//GUI-Komponenten enthält
class GeneralMainPanel extends JPanel
{
	public GeneralMainPanel()
	{
		setLayout(new BorderLayout());
		
		// PaintPanel erstellen und in die Mitte legen
		final GeneralPaintPanel paintPanel = new GeneralPaintPanel();
		paintPanel.setPreferredSize(new Dimension(400, 400));
		add(paintPanel, BorderLayout.CENTER);
		
		// Button erstellen und an den unteren Rand legen
		JButton button = new JButton("Paint object");
		add(button, BorderLayout.SOUTH);
		
		// Wenn der Button geklickt wird, wird das zu zeichnende 
		// Objekt erstellt und an das ObjectPaintPanel übergeben
		button.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				int x = (int)(Math.random()*(paintPanel.getWidth() - 100));
				int y = (int)(Math.random()*(paintPanel.getHeight() - 100));
				Smiley smiley = new Smiley(x,y);
				paintPanel.addPaintable(smiley);
			}
		});
		
	}
}

//Die Hauptklasse mit der main-Methode. 
public class SwingGeneralPaint
{
	// Das Erzeugen des GUIs muss auf dem 
	// Swing-Thread ausgeführt werden:
	public static void main(String args[])
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				// Fenster erstellen
				JFrame frame = new JFrame("Paint on button click");
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.getContentPane().setLayout(new BorderLayout());
				
				// Hauptpanel erstellen und in den Frame legen
				GeneralMainPanel mainPanel = new GeneralMainPanel();
				frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
				
				// Fenster zentrieren und anzeigen
				frame.pack();
				frame.setLocationRelativeTo(null);
				frame.setVisible(true);
			}
		});
	}

}
Schon bei diesen Beispielen stellen sich viele Fragen: Sollte man zwischen den letzten beiden einen Unterschied machen? Wenn nicht, sollte man dann immer gleich "Paintable" oder überall nur Shapes verwenden? Wie hält man es damit für die weiteren Funktionen (anklickbar, verschiebbar, animiert (ohne den EDT zu blockieren ;) ) ... ?)

Vielleicht hat ja jemand Ideen.
 
Sollte man zwischen den letzten beiden einen Unterschied machen? Wenn nicht, sollte man dann immer gleich "Paintable" oder überall nur Shapes verwenden? Wie hält man es damit für die weiteren Funktionen (anklickbar, verschiebbar, animiert (ohne den EDT zu blockieren ;) ) ... ?)
Ich finde die Paintable-Variante irgendwie besser. Dann könnte man das stufenweise aufbauen. Im nächsten Schritt könnte man sowas wie
Java:
interface Clickable extends Paintable {
  boolean isResponsibleForPoint(Point position);
  void addMouseListener(MouseListener l);
  void removeMouseListener(MouseListener l);
  void fireMouseEvent(MouseEvent e);
}
machen. Zumal man da auch eine gewisse Grundlage für alle Beispiele schaffen kann und mehrmals benutzte Schnittstellen/Klassen einmalig zentral erklären kann.
Habe zu dem anklickbarem Teil eine Idee, muss ich aber noch eine Nacht darüber schlafen. Vllt wird die aber schon aus dem Interface deutlich.
 
Zuletzt bearbeitet:
Schöne Beispiele. :) 2 Anmerkungen sind mir beim Überfliegen eingefallen.

1. Mir ist nicht ganz klar, warum Du grundsätzlich das Graphics-Object in ein Graphics2D castest? Außer bei den RenderingHints im letzten Beispiel sehe ich da keinen Vorteil? (Lasse mich aber gern eines besseren belehren :D)

2. Ich fände es gut, wenn die Beispiele aufeinander aufbauen. Für das GeneralPaintPanel im 3. Beispiel hast Du eine komplett neue Klasse. Evtl. wäre es lehrreicher für den Newbie, wenn man stattdessen das ShapePaintPanel erweitert/aufbohrt?
 
@L-ectron-X: Eine (schlechte :oops: ) Angewohnheit (seltsamerweise NUR bei dieser Methode) - werde ich ändern.

@XHelp: Viel "erklären" wollte ich eigentlich nicht ... nicht dass das doch noch ein Swing-Tutorial wird :mad: ;) (BTW: Das anklicken wäre im einfachsten Fall ja ein shape.contains(...) ?!). Ein ein Punkt, der für das Interface sprechen würde, wäre natürlich der des "Stufenweisen Aufbauens", und...
([email protected]: ) ...dieser Gedanke der "Stufenweisen Erweiterung" steckte da schon ein bißchen drin. Ich aber bin nicht sicher, wie dafür de günstigste Strategie wäre. Eigentlich sollte es ja wirklich nur eine Art "Steinbruch" sein, wo man sich Copy&Paste-Vorlagen für eine spezifische(!) Zielsetzung rausholt - andererseits würde sich schon jetzt eine potentielle Kombinatorische Explosion andeuten: Zeichenbar, Zeichenbar+Klickbar, Zeichenbar+Animiert, Zeichenbar+Klickbar+Animiert... (Und DAS wäre ein Fall, wo man sowas nicht mit OSGi & Co lösen würde :D )... Aber vielleicht kann man diesen Gedanken noch ein bißchen besser ausnutzen... (Ich bin nicht sicher, wie man das formulieren soll, aber grob: ) ... ohne dass man bei der letzten "Stufe" sieht, dass es vorher schon andere Stufen gab...
 
So, nun habe ich die Nacht drüber geschlafen und es kommt mir mittlerweile gar nicht so richtig vor. Aber da der Thread in "Entwürfe" ist, packe ich das mal rein.
Habe einfach mal dein Smiley-Beispiel etwas umgebaut:
Java:
//Paintable, SwingGeneralPaint bleiben wie gehabt

//Ein Interface für alle Objekte, die gezeichnet und geklickt werden können. 
//Wobei sich durch den ganzen Listener-Kram eine abstrakte Klasse eher anbieten würde
public interface Clickable extends Paintable {
	boolean isResponsibleForPoint(Point position);
	void addMouseListener(MouseListener l);
	void removeMouseListener(MouseListener l);
	void fireMouseEvent(MouseEvent e);
}

//Ein Smiley, der gezeichnet und angeklickt werden kann. 
public class Smiley implements Clickable {
	private List<MouseListener> listenerList;
	private int x;
	private int y;
	private Color mainColor = Color.YELLOW;
	private final int DIAMETER = 50;

	public Smiley(int x, int y) {
		this.x = x;
		this.y = y;
		listenerList = new ArrayList<MouseListener>();
	}

	public void setRandomColor() {
		Random random = new Random();
		mainColor = new Color(random.nextInt(256), random.nextInt(256),
				random.nextInt(256));
	}

	// Implementierung des Clickable-Interfaces
	public void paintObject(Graphics2D g) {
		g.setColor(mainColor);
		g.fillOval(x, y, DIAMETER, DIAMETER);
		g.setColor(Color.BLACK);
		g.fillOval(x + 15, y + 15, 8, 8);
		g.fillOval(x + 30, y + 15, 8, 8);
		g.draw(new Arc2D.Double(x + 10, y + 10, 30, 30, 190, 160, Arc2D.OPEN));
	}

	public boolean isResponsibleForPoint(Point position) {
		float r = DIAMETER / 2;
		float center_x = x + r;
		float center_y = y + r;
		float dist = (float) Math.sqrt(Math.pow(position.x - center_x, 2)
				+ Math.pow(position.y - center_y, 2));
		return dist < r;
	}

	public void addMouseListener(MouseListener l) {
		listenerList.add(l);
	}

	public void removeMouseListener(MouseListener l) {
		listenerList.remove(l);
	}

	public void fireMouseEvent(MouseEvent e) {
		for (MouseListener currentListener : listenerList) {
			switch (e.getID()) {
			case MouseEvent.MOUSE_CLICKED:
				currentListener.mouseClicked(e);
				break;
			case MouseEvent.MOUSE_ENTERED:
				currentListener.mouseEntered(e);
				break;
			case MouseEvent.MOUSE_EXITED:
				currentListener.mouseExited(e);
				break;
			case MouseEvent.MOUSE_PRESSED:
				currentListener.mousePressed(e);
				break;
			case MouseEvent.MOUSE_RELEASED:
				currentListener.mouseReleased(e);
			}
		}
	}
}

// Ein JPanel, bei dem die paintComponent-Methode überschrieben ist, und 
// das eine Liste von Objekten speichert, die gezeichnet werden können
// Darüber hinaus ist es auch für das Weiterleiten der Mouseevents zuständig
public class GeneralPaintPanel extends JPanel {
	// Die Liste der Paintablen Objekte, und Methoden um solche
	// Objekte hinzuzufügen oder zu entfernen.
	// Die Mouseevents werden auch an die jeweiligen Objekten weitergeleitet
	private List<Clickable> clickables = new ArrayList<Clickable>();

	public GeneralPaintPanel() {
		addMouseListener(new MouseListener() {
			//Mouseevents an die zuständigen Objekte weiterleiten
			private void dispatchEvent(MouseEvent e) {
				for (Clickable clickable : clickables) {
					if (clickable.isResponsibleForPoint(e.getPoint())) {
						MouseEvent event = new MouseEvent((Component) e.getSource(), e.getID(),
								e.getWhen(), e.getModifiers(), e.getX(),
								e.getY(), e.getClickCount(),
								e.isPopupTrigger(), e.getButton());
						event.setSource(clickable);
						clickable.fireMouseEvent(event);
					}
				}
				repaint();
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				dispatchEvent(e);
			}

			@Override
			public void mousePressed(MouseEvent e) {
				dispatchEvent(e);
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				dispatchEvent(e);
			}
		});
	}

	public void addPaintable(Clickable paintable) {
		clickables.add(paintable);
		repaint();
	}

	public void removePaintable(Paintable paintable) {
		clickables.remove(paintable);
		repaint();
	}

	@Override
	protected void paintComponent(Graphics graphics) {
		super.paintComponent(graphics);
		Graphics2D g = (Graphics2D) graphics;
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		for (Clickable clickable : clickables) {
			clickable.paintObject(g);
		}
	}
}

//Die Hauptklasse für das GUI: Ein Panel, das die weiteren
//GUI-Komponenten enthält
public class GeneralMainPanel extends JPanel {
	public GeneralMainPanel() {
		setLayout(new BorderLayout());

		// PaintPanel erstellen und in die Mitte legen
		final GeneralPaintPanel paintPanel = new GeneralPaintPanel();
		paintPanel.setPreferredSize(new Dimension(400, 400));
		add(paintPanel, BorderLayout.CENTER);

		// Button erstellen und an den unteren Rand legen
		JButton button = new JButton("Paint object");
		add(button, BorderLayout.SOUTH);

		// Wenn der Button geklickt wird, wird das zu zeichnende
		// Objekt erstellt und an das ObjectPaintPanel übergeben
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int x = (int) (Math.random() * (paintPanel.getWidth() - 100));
				int y = (int) (Math.random() * (paintPanel.getHeight() - 100));
				Smiley smiley = new Smiley(x, y);
				smiley.addMouseListener(new MouseListener() {

					@Override
					public void mouseReleased(MouseEvent e) {
					}

					@Override
					public void mousePressed(MouseEvent e) {
					}

					@Override
					public void mouseExited(MouseEvent e) {
					}

					@Override
					public void mouseEntered(MouseEvent e) {
					}

					@Override
					public void mouseClicked(MouseEvent e) {
						Smiley smiley = (Smiley) e.getSource();
						smiley.setRandomColor();
					}
				});
				paintPanel.addPaintable(smiley);
			}
		});

	}
}
 
@XHelp: So recht funktioniert Dein Beispiel aber nicht? Oder sagen wir so: Nicht bei mir. ;) Der MouseListener im GeneralPaintPanel schlägt bei mir nicht zu. Ich schau' da später nochmal genauer drauf.

Nachdem die Idee von Marco ja war, daß man die Dinger einfach kopiert und ausführen kann, fehlt mir zusätzlich noch die main-Methode.

Außerdem bin ich der Meinung, daß man Basis-Klassen verwenden sollte, wo es möglich ist, auch in einem NICHT-Tutorial ;)
Ich habe daher das Smiley mal von Rectangle erben lassen:

Java:
//Ein Smiley, der gezeichnet und angeklickt werden kann. 
class Smiley extends Rectangle implements Clickable {
	
    private ArrayList<MouseListener> listenerList;
    private Color mainColor = Color.YELLOW;
 
    public Smiley(int x, int y, int dia) {
        super(x,y,dia,dia);
        listenerList = new ArrayList<MouseListener>();
    }
 
    ....
 
    // Implementierung des Clickable-Interfaces
    public void paintObject(Graphics2D g) {
        g.setColor(mainColor);
        g.fillOval(x, y, width,height);
        g.setColor(Color.BLACK);
        g.fillOval(x + 15, y + 15, 8, 8);
        g.fillOval(x + 30, y + 15, 8, 8);
        g.draw(new Arc2D.Double(x + 10, y + 10, 30, 30, 190, 160, Arc2D.OPEN));
    }

    ....
}
 
Außerdem bin ich der Meinung, daß man Basis-Klassen verwenden sollte, wo es möglich ist, auch in einem NICHT-Tutorial ;)
Ich habe daher das Smiley mal von Rectangle erben lassen:
Darüber könnte jetzt eine lange philosophische Diskussion ausbrechen. Als erstes "Gegenargument" würde ich stichwortartig "Composition over Inheritance" einwerfen. Rectangle macht wirklich nicht viel, deswegen könnte es fast noch vertretbar sein, aber ... solche Methoden wie "reshape", "addPoint" oder "union" will man eigentlich nicht in einem Ding, dessen einzige und alleinige Aufgabe es ist, etwas zu repräsentieren, was einen Smiley auf den Bildschirm malt. (Threads in denen irgendwelche Sprites von JComponent erben, weil "...das mit setLocation und addMouseListener so praktisch ist" gibt es schon einige, da ist verständlicher, warum ich mit sowas Bauchschmerzen habe...)
 
Ja, wenn nur bestimmte Teile weiterdiskutiert werden, braucht man ja nicht alles zu posten, am Ende können die Beispiele ja als 1:1-Singe-C&P-Blöcke zusammengebastelt werden.
 
Die Frage wäre eher "Gibt es schon Fortschritte", aber in anbetracht des Datums, ja... :oops: Aber das ist eine gute Idee, ich kann da heute mal ein bißchen weiterbasteln...
 
Soo... ich habe nochmal weitergebastelt. Aber irgendwie sind die Fragen, wie man das am günstigsten strukturiert, für mich immer noch nicht geklärt. Das "einfachste Zeichnen" geht ja noch. Aber schon bei Zeichnen+Klicken stellen sich Fragen, von denen ich nicht weiß, ob sie egal sind oder nicht.

Zum Beispiel: Sollte Clickable von Paintable erben? Eigentlich nicht. Die beiden Sachen haben nicht viel miteinander zu tun. Wenn man beides vermischt, wirkt es unstrukturiert, und wenn man es trennt, wird es so schnell so "aufwändig", dass es jemanden, der nur ein Snippet sucht, vielleicht schon erschlägt oder verwirrt.

Das ist nur ein Beispiel. Darüber hinaus und allgemeiner wäre die Frage: Sollen die Snippets so sein, dass sie auch ohne Vorwissen leicht nachvollziehbar sind? Auch wenn das bedeutet, dass die Struktur, die durch sie vorgegeben wird, schlecht erweiterbar ist?

Ich würde jetzt dazu tendieren, um der Einfachheit willen Dinge auch mal so zu machen, wie man sie eigentlich (in einem "echten Programm") nicht machen würde, und die vielleicht nicht von Eleganz, Allgemeingültigkeit und Erweiterbarkeit strotzen....
 
A

Anzeige




Vielleicht hilft dir das hier weiter: (klicke hier)
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben