# Klasse die extended als Thread implementieren?



## denis7788 (21. Mai 2012)

Hallo!
Ich habe eine Klasse, die JFrame extended und möchte diese nun als Thread implementieren. Was für Möglichkeiten habe ich denn da? (Kann ja nicht von zwei Klassen erben)


----------



## eRaaaa (21. Mai 2012)

Zu 99% behaupte ich jetzt einfach mal, dass du weder Thread noch JFrame erweitern musst!

Schreibe eine eigene Klasse und implementiere das Runnable Interface, dieses kannst du dann der Thread-Klasse übergeben und ausführen lassen.
JFrame erweitern ist _vermutlich_ auch nicht nötig, wieso nicht einfach eine JFrame Instanz anlegen?!


----------



## Marco13 (21. Mai 2012)

Es nicht tun.

Im Ernst, es besteht da kein Grund dafür. Schon von JFrame zu erben ist in den seltensten Fällen sinnvoll (spontan würde ich sagen: Nie!). Und von Thread zu erben ebenso. (Wieder spontan: Nie!). Erstell' stattdessen eine Klasse, die Runnable implementiert, und übergib ein Objekt dieser Klasse einem neu erstellten Thread.


----------



## denis7788 (21. Mai 2012)

Naja... es ist eine Übung und der Code ist vorgegeben. Also wollte ich mir auch sparen ihn komplett umzukrempeln. 
Was meinst du mit Klasse erstellen, die Runnable implementiert? Kann mir nichts drunter vorstellen.
Ich versuche mal eine JFrame Instanz zu erstellen und dann die Sache mit extends Thread zu Lösen. Habe es bisher nur so gesehen und bin etwas unter Zeitdruck... 
Trotzdem würde mich interessieren, wie ich das mit eleganter lösen kann (mit der Implementierung von Runnable).

Hier ist der Code:


```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class ChatWindow extends JFrame implements WindowListener {

	private static final long serialVersionUID = 1L;
	private final JTextPane text;
	private final JButton send;
	private final JTextField input;
	private final JLabel label, label_2;
	private final JPanel panel_1, panel_2, panel_3, panel_4;
	private final JScrollPane scp;
	private final Color col;
	private static boolean one_window_closed = false;
	private final int id;
	private static int cnt = 0;

	public ChatWindow() {
		id = cnt++ + 1;
		setTitle("PII - Uebung 01");
		setSize(400, 400);
		col = id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78);
		text = new JTextPane();
		text.setEditable(false);
		send = new JButton("send");
		send.setBackground(col);
		send.setForeground(Color.WHITE);
		input = new JTextField();
		label = new JLabel();
		label.setAlignmentX(Component.CENTER_ALIGNMENT);
		label_2 = new JLabel("Chat#" + id);
		label_2.setForeground(Color.WHITE);
		label_2.setAlignmentX(0.03f);
		scp = new JScrollPane(text);
		panel_1 = new JPanel();
		panel_2 = new JPanel();
		panel_3 = new JPanel();
		panel_4 = new JPanel();
		// -------------------------------------------------------------
		panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.PAGE_AXIS));
		panel_1.add(scp);
		panel_1.add(Box.createRigidArea(new Dimension(0, 15)));
		panel_1.add(label);
		panel_1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		// -------------------------------------------------------------
		panel_2.setLayout(new BoxLayout(panel_2, BoxLayout.LINE_AXIS));
		panel_2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		panel_2.add(input);
		panel_2.add(Box.createRigidArea(new Dimension(10, 0)));
		panel_2.add(send);
		// -------------------------------------------------------------
		panel_4.setLayout(new BoxLayout(panel_4, BoxLayout.PAGE_AXIS));
		panel_4.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_4.add(label_2);
		panel_4.setBackground(col);
		// -------------------------------------------------------------
		panel_3.setLayout(new BorderLayout());
		panel_3.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_3.add(panel_4, BorderLayout.PAGE_START);
		panel_3.add(panel_1, BorderLayout.CENTER);
		panel_3.add(panel_2, BorderLayout.PAGE_END);
		panel_3.setBackground(col);
		// -------------------------------------------------------------
		add(panel_3);
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation(dim.width / 2 - getWidth() * (id == 1 ? 1 : 0), dim.height
				/ 2 - getHeight() / 2);
		this.addWindowListener(this);
		setMinimumSize(new Dimension(200, 200));
		setVisible(true);
	}

	public String getInput() {
		return this.input.getText();
	}

	public void resetInputText() {
		this.input.setText("");
		this.input.requestFocus();
	}

	public void writeText(int id, String str) {
		if (str.trim().equals(""))
			return;
		StyledDocument doc = this.text.getStyledDocument();
		Style style = this.text.addStyle("", null);
		StyleConstants.setForeground(style, id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78));
		try {
			doc.insertString(doc.getLength(), "# " + id + ": ", style);
			doc.insertString(doc.getLength(), str + "\n", null);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

	public JButton getSendButton() {
		return this.send;
	}

	public JTextField getTextField() {
		return this.input;
	}

	public void setLabelText(String str) {
		this.label.setText(str);
	}

	public void windowClosing(WindowEvent arg0) {
		if (ChatWindow.one_window_closed)
			System.exit(0);
		else {
			this.setVisible(false);
			ChatWindow.one_window_closed = true;
		}
	}

	public void windowActivated(WindowEvent arg0) {
	}

	public void windowClosed(WindowEvent arg0) {
	}

	public void windowDeactivated(WindowEvent arg0) {
	}

	public void windowDeiconified(WindowEvent arg0) {
	}

	public void windowIconified(WindowEvent arg0) {
	}

	public void windowOpened(WindowEvent arg0) {
	}
}
```


----------



## Marco13 (21. Mai 2012)

```
class WasInEinemEigenenThreadGemachtWerdenSoll implements Runnable
{
    @Override 
    public void run()
    {
        // Was auch immer
    }
}

// Verwendung:
Runnable runnable = new WasInEinemEigenenThreadGemachtWerdenSoll();
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.start();
```


----------



## denis7788 (21. Mai 2012)

Mh ich glaube bei mir ist es eher eine Verständnis Frage...
Ich muss die Klasse ChatWindow in einen thread umwandeln. Aber Insanzen der ChatWindows werden in der Klasse Chat erstellt.
Heißt das, ich muss in der Klasse Chat die Instanziierung der einzelnen Chatfenster als Threads realisieren?

Hier die Beiden Klassen:
ChatWindow

```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

import java.lang.Thread;

public class ChatWindow extends Thread implements WindowListener {

	private final JFrame frame;
	private static final long serialVersionUID = 1L;
	private final JTextPane text;
	private final JButton send;
	private final JTextField input;
	private final JLabel label, label_2;
	private final JPanel panel_1, panel_2, panel_3, panel_4;
	private final JScrollPane scp;
	private final Color col;
	private static boolean one_window_closed = false;
	private final int id;
	private static int cnt = 0;
	

	
	
	public ChatWindow() {
		frame = new JFrame();
		id = cnt++ + 1;
		frame.setTitle("PII - Uebung 01");
		frame.setSize(400, 400);
		col = id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78);
		text = new JTextPane();
		text.setEditable(false);
		send = new JButton("send");
		send.setBackground(col);
		send.setForeground(Color.WHITE);
		input = new JTextField();
		label = new JLabel();
		label.setAlignmentX(Component.CENTER_ALIGNMENT);
		label_2 = new JLabel("Chat#" + id);
		label_2.setForeground(Color.WHITE);
		label_2.setAlignmentX(0.03f);
		scp = new JScrollPane(text);
		panel_1 = new JPanel();
		panel_2 = new JPanel();
		panel_3 = new JPanel();
		panel_4 = new JPanel();
		// -------------------------------------------------------------
		panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.PAGE_AXIS));
		panel_1.add(scp);
		panel_1.add(Box.createRigidArea(new Dimension(0, 15)));
		panel_1.add(label);
		panel_1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		// -------------------------------------------------------------
		panel_2.setLayout(new BoxLayout(panel_2, BoxLayout.LINE_AXIS));
		panel_2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		panel_2.add(input);
		panel_2.add(Box.createRigidArea(new Dimension(10, 0)));
		panel_2.add(send);
		// -------------------------------------------------------------
		panel_4.setLayout(new BoxLayout(panel_4, BoxLayout.PAGE_AXIS));
		panel_4.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_4.add(label_2);
		panel_4.setBackground(col);
		// -------------------------------------------------------------
		panel_3.setLayout(new BorderLayout());
		panel_3.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_3.add(panel_4, BorderLayout.PAGE_START);
		panel_3.add(panel_1, BorderLayout.CENTER);
		panel_3.add(panel_2, BorderLayout.PAGE_END);
		panel_3.setBackground(col);
		// -------------------------------------------------------------
		frame.add(panel_3);
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		frame.setLocation(dim.width / 2 - frame.getWidth() * (id == 1 ? 1 : 0), dim.height
				/ 2 - frame.getHeight() / 2);
		frame.addWindowListener(this);
		frame.setMinimumSize(new Dimension(200, 200));
		frame.setVisible(true);
	}
	
	
	

	public String getInput() {
		return this.input.getText();
	}

	public void resetInputText() {
		this.input.setText("");
		this.input.requestFocus();
	}

	public void writeText(int id, String str) {
		if (str.trim().equals(""))
			return;
		StyledDocument doc = this.text.getStyledDocument();
		Style style = this.text.addStyle("", null);
		StyleConstants.setForeground(style, id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78));
		try {
			doc.insertString(doc.getLength(), "# " + id + ": ", style);
			doc.insertString(doc.getLength(), str + "\n", null);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

	public JButton getSendButton() {
		return this.send;
	}

	public JTextField getTextField() {
		return this.input;
	}

	public void setLabelText(String str) {
		this.label.setText(str);
	}

	public void windowClosing(WindowEvent arg0) {
		if (ChatWindow.one_window_closed)
			System.exit(0);
		else {
			frame.setVisible(false);
			ChatWindow.one_window_closed = true;
		}
	}

	public void windowActivated(WindowEvent arg0) {
	}

	public void windowClosed(WindowEvent arg0) {
	}

	public void windowDeactivated(WindowEvent arg0) {
	}

	public void windowDeiconified(WindowEvent arg0) {
	}

	public void windowIconified(WindowEvent arg0) {
	}

	public void windowOpened(WindowEvent arg0) {
	}
	
	
	
}
```

Chat:

```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JTextField;

public class Chat implements ActionListener, KeyListener {

	private final ChatWindow[] chatwindows;
	private int same;
	private ArrayList<ExtString>[] strings;

	@SuppressWarnings("unchecked")
	public Chat() {
		chatwindows = new ChatWindow[2];
		strings = new ArrayList[2];
		for (int i = 0; i < 2; i++) {
			chatwindows[i] = new ChatWindow();
			chatwindows[i].getSendButton().addActionListener(this);
			chatwindows[i].getTextField().addKeyListener(this);
			strings[i] = new ArrayList<ExtString>();
		}
		same = 0;
		updateLabelText();
		chatwindows[0].getTextField().requestFocus();
	}

	public void actionPerformed(ActionEvent arg0) {
		handleInput(arg0.getSource());
	}

	public void keyPressed(KeyEvent arg0) {
		if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
			handleInput(arg0.getSource());
		}
	}

	public void updateLabelText() {
		for (int i = 0; i < 2; i++)
			this.chatwindows[i].setLabelText(this.same + " common tags!");
	}

	public void handleInput(Object object) {
		boolean reset = false;
		int src = -1;
		if (object instanceof JTextField) {
			src = object == chatwindows[0].getTextField() ? 0 : 1;
			doIt(src);
			reset = true;
		} else {
			if (object instanceof JButton) {
				src = object == chatwindows[0].getSendButton() ? 0 : 1;
				doIt(src);
				reset = true;
			}
		}
		if (reset) {
			if (src == 0)
				chatwindows[0].resetInputText();
			else
				chatwindows[1].resetInputText();
		}
	}

	public void doIt(int src) {
		String str = chatwindows[src].getInput();
		StringTokenizer tok = new StringTokenizer(str, ",");
		String tmp;
		/*
		 * variable 'pos' to store the position of the currently handled tokens within the string-list
		 */
		int pos = -1;
		boolean found = false;
		while (tok.hasMoreTokens()) {
			tmp = tok.nextToken().trim();
			for (int i = strings[src].size() - 1; i > -1; i--) {
				if (tmp.equals(strings[src].get(i).getContent())) {
					strings[src].get(i).IncCnt();
					found = true;
					pos = i;
				}
			}
			if (!found) {
				strings[src].add(new ExtString(tmp));
				pos = strings[src].size() - 1;
			}
			/*
			 * check if there is another common tag
			 */
			compareTags(src, pos, tmp);
		}
		for (int i = 0; i < 2; i++)
			chatwindows[i].writeText(src + 1, str);
	}

	public void compareTags(int src, int pos, String str) {
		ArrayList<ExtString> list = strings[(src + 1) % 2];
		ExtString tmp;
		for (int i = list.size() - 1; i > -1; i--) {
			tmp = list.get(i);
			/*
			 * only increment the number of common tags if current token didn't match before
			 */
			if (str.equals(tmp.getContent()) && !tmp.wasMatched()) {
				this.same++;
				tmp.matches();
				/*
				 * also mark in the other string-list that this token has matched
				 */
				strings[src].get(pos).matches();
			}
		}
		updateLabelText();
		/*
		 * undo following comment to display the string-lists every time someone types in something new
		 */
		//printArrayLists();
	}

	public void printArrayLists() {
		System.out.println("1:");
		for (int i = this.strings[0].size() - 1; i > -1; i--) {
			System.out.print(strings[0].get(i).getContent() + "("
					+ strings[0].get(i).getCnt() + ":"
					+ strings[0].get(i).wasMatched() + "); ");
		}
		System.out.println("\n2:");
		for (int i = this.strings[1].size() - 1; i > -1; i--) {
			System.out.print(strings[1].get(i).getContent() + "("
					+ strings[1].get(i).getCnt() + ":"
					+ strings[1].get(i).wasMatched() + "); ");
		}
		System.out.println("\n--------------------------------------");
	}

	public void keyReleased(KeyEvent arg0) {
	}

	public void keyTyped(KeyEvent arg0) {
	}

	public static void main(String[] args) {
		new Chat();
	}
}
```


----------



## Marco13 (21. Mai 2012)

Ja,... ohne die 300 Zeilen unübersichtlichen Code nachvollzogen zu haben: "Eine Klasse in einen Thread umwandeln" macht so keinen Sinn. Beschreib' genauer, was du erreichen willst, und ggf. wo und wie du dazu ansetzen willst. WAS soll in diesem Thread genau ausgeführt werden?


----------



## denis7788 (21. Mai 2012)

Das ganze soll ein Chat Programm sein. Die Klasse ChatWindow implementiert ein Chatfenster. Die Klasse Chat erzeugt Instanzen von Chatfenstern.
In der aufgabe steht wortwörtlich man solle die Klasse ChatWindow in einen Thread umwandeln. So wie ich das verstehe, soll jedes Fenster einen eigenen Thread darstellen.

Ich habs jetzt mal folgendermaßen probiert:
In der Klasse chatWindow habe ich Runnable implementiert. Bin mir aber nicht sicher ob das so richtig ist.
In der Klasse Chat habe ich threads erzeugt, die mein runnable ausführen.
Ich frage mich nur, ob meine Chatfenster als einzelne Threads realisiert sind oder nciht!?

Chatwindow

```
public class ChatWindow  implements WindowListener, Runnable {
//---------------Konstruktor + Methoden der Klasse wie oben----------------------/
public void run(){
		setVisible(true);
	}	
}
```
Chat

```
public class Chat implements ActionListener, KeyListener {

	private final ChatWindow[] chatwindows;
	private final Thread[] threads;
	private int same;
	private ArrayList<ExtString>[] strings;

	@SuppressWarnings("unchecked")
	public Chat() {
		chatwindows = new ChatWindow[2];
		threads = new Thread[2];
		strings = new ArrayList[2];
		for (int i = 0; i < 2; i++) {
			chatwindows[i] = new ChatWindow();
			threads[i] = new Thread(chatwindows[i]);
			threads[i].start();
			chatwindows[i].getSendButton().addActionListener(this);
			chatwindows[i].getTextField().addKeyListener(this);
			strings[i] = new ArrayList<ExtString>();
		}
		same = 0;
		updateLabelText();
		chatwindows[0].getTextField().requestFocus();
	}
//--------------------Methoden der Klasse wie oben-----------

}
```


----------



## vanny (21. Mai 2012)

Mir ist auch nicht klar, warum du dein Fenster sozusagen threaden sollst?! ???:L

1. Läuft dein Fenster in einem Thread, und zwar im EDT.
Dieser ist genau dafür da.
2. Wenn schon multithread, dann, wie schon einige mal hier erwähnt für Aufgaben, die eben nichts mit GUI zu tun haben, um diese nicht zu blockieren.

poste mal bitte die komplette Aufgabenstellung im Originaltext.
So finde ich das gesamte Konzept iwie wiedersinnig.

Gruß Vanny


----------



## denis7788 (21. Mai 2012)

Also hier die Aufgabenstellung und die Dritte Klasse ExtString (die aber glaube ich keine Rolle spielt):

Auf der Vorlesungseite finden Sie eine Musterlosung zu der Chat-Applikation des letzten
Übungsblattes. Verandern Sie diese wie folgt:
------------------
 Wandeln Sie die Klasse ChatWindow in einen Thread um, welcher entsprechend in
der Klasse Chat auch als solcher gestartet wird.
------------------
 Ändern Sie die Architektur der Anwendung so ab, dass die Überprüfung doppelt
vorkommener Tags nun nicht mehr in der Klasse Chat stattfindet, sondern von jedem
ChatWindow-Thread selbst übernommen wird. Die Speicherung der erforderlichen
Daten (same und strings) bleibt allerdings bei der Klasse Chat.
------------------
 Sorgen Sie nun fur einen geordneten (synchronisierten) Zugriff der Threads auf die
gemeinsame Datenstruktur.
------------------
 Erweitern Sie zuletzt das Programm um eine beliebige Anzahl von Chatfenstern. D.h.
zu Beginn gibt der Benutzer die gewunschte Anzahl der Chats an. Achten Sie darauf,
dass Sie nun nur Tags als gemeinsam zählen können, wenn diese in allen Chatfenstern
eingegeben wurden (Hinweis: Erweiterung der Klasse ExtString). Unterschiedliche
Farben der Fenster können Sie bei dieser Lösung getrost ignorieren.


```
public class ExtString {

	private final String content;
	private int cnt;
	private boolean matched;

	public ExtString(String content) {
		this.content = content;
		this.cnt = 1;
		this.matched = false;
	}

	public int getCnt() {
		return this.cnt;
	}

	public String getContent() {
		return this.content;
	}

	public void IncCnt() {
		this.cnt++;
	}

	public boolean wasMatched() {
		return this.matched;
	}

	public void matches() {
		this.matched = true;
	}
}
```


----------



## Marco13 (22. Mai 2012)

Für mich ergibt die Aufgabenstellung keinen Sinn. Alles, was mit Swing-Components zu tun hat, muss ohnehin im EDT gemacht werden. Dort jetzt willkürlich irgendwelche neuen Threads einzuführen würde den snychronisationsaufwand erhöhen und keinen Vorteil bringen. Das einzige, was ich mir vorstellen könnte, wäre, dass das später noch (naheliegenderweise) um Netzwerk-Kommunikation erweitert werden soll. Und DA macht es natürlich Sinn, in einem eigenen Thread z.B. auf Antworten zu warten. 

Wie die Original-"Muster"lösung aussieht, wäre auch mal spannend. War dieser Krampf mit "handleInput" und "doit" und dem static "one_window_closed" etwa auch vorgegeben? :autsch:

Mal schauen ob jemand bei Klasse als Thread - coding-board noch eine kreative Idee hat. Ansonsten könnte man höchstens versuchen, sowas wie das "writeText" (vorausschauend in bezug auf wahrscheinliche zukünftige Erweiterungen) so umzuwandeln, dass da in einem eigenen Thread auf einen InputStream gewartet wird, der irgendwann eben ein Netzwerk-InputStream ist... :bahnhof:


----------



## denis7788 (22. Mai 2012)

Ja, das war alles vorgegeben. Und ja, das wird ein richtiges Chat Programm. Also auf coding board sagt jemand es wäre so i.o..
Weiß nicht, ob ich die Frage auch hier stellen kann, weil der Thread nicht passt, aber:

Wie könnte ich denn Teilaufgabe 2 umsetzen? Habe rumprobiert mit einer eigenen Klasse für die Methoden, die die Strings vergleichen. Das ganze wird dann aber sowas von unübersichtlich.
--> Erst muss ich aus der Klasse Chat die int same und die Arraylist strings auslesen; 
-->Diese in der neuen Klasse verwenden, da dort nun die Methode compare ist;
-->Diese Methode muss ich in Chatwindow aufrufen (innerhalb der run() Methode);
-->Dann muss ich über getter Methoden (die sich in ChatWindow befinden) die Werte wieder nach Klassse Chat auslesen!?!

Das müsste doch von der Idee her auch simpler gehen. Wäre froh über einen Denkanstoß.


----------



## timbeau (22. Mai 2012)

Grundsätzlich würde ich sagen, die Daten die du brauchst in Beans/Objekte zu packen und diese weiter zu verarbeiten. Ist das Objekt verarbeitet gibst du es zurück.


----------



## denis7788 (22. Mai 2012)

Das ändert doch aber nichts an der komplizierten Struktur, die ich habe, oder? Ob ich jetzt auf die Variablen zich mal übergebe, oder Objekte, die diese enthalten spielt doch keine Rolle?


----------



## Marco13 (22. Mai 2012)

denis7788 hat gesagt.:


> Ja, das war alles vorgegeben. Und ja, das wird ein richtiges Chat Programm. Also auf coding board sagt jemand es wäre so i.o..



Die Antwort dort war sehr unspezifisch. Aber "setVisible(true)" von einem eigenen Thread machen zu lassen, ist schlicht Unfug. Einfach falsch. (Punkt.)



> Wie könnte ich denn Teilaufgabe 2 umsetzen? Habe rumprobiert mit einer eigenen Klasse für die Methoden, die die Strings vergleichen.



So, wie das beschrieben ist, sollte genau diese Überprüfung dann von den jeweiligen Threads gemacht werden. Den Sinn könnte man auch da in Frage stellen, aber ... vielleicht denkt sich da ja irgendjemand was dabei.

Gibt's einen Link zu der Seite mit der Aufgabenstellung?

Schließ' dich mal (z.B. per PN) mit dem Autor dieses Threads kurz: http://www.java-forum.org/awt-swing-swt/136533-gui-threads-aufbauen.html


----------



## denis7788 (23. Mai 2012)

Danke für den Link!
Also heute hat sich herausgestellt, dass die Aufgabenstellung nicht optimal ist. Ich muss Threads starten, sobald der Listener etwas auffängt. D.h. dann sollen die Methoden zum Vergleich der Tags und der Speicherung der Tags in der Arraylist in Threads ablaufen.
Das ganze habe ich versucht umzusetzen. Aber äußerst erfolglos. Ich habe die Methoden updateLabel() (--> zeigt anzahl gleicher Tags an) und compareTags() in de ChatWindow Klasse geschrieben und in der run() Methode  doIt()  implementiert. 
Habe mir gedacht, das ich einen Thread aufrufen kann, sobald der Button geklickt wird und so doIt und damit auch compareTags und updateLabelText() aufgerufen werden.
So funktioniert aber garnichts mehr. Hier der Code:

Chat:

```
public class Chat implements ActionListener, KeyListener {

	public static ChatWindow[] chatwindows;
	public static int same;
	public static ArrayList<ExtString>[] strings;
	private Thread[] threads;
	public int src, src_helper;

	@SuppressWarnings("unchecked")
	public Chat() {
		chatwindows = new ChatWindow[2];
		strings = new ArrayList[2];
		threads = new Thread[2];
		for (int i = 0; i < 2; i++) {
			threads[i] = new Thread(chatwindows[i]);
			threads[i].start();
			chatwindows[i] = new ChatWindow();
			chatwindows[i].getSendButton().addActionListener(this);
			chatwindows[i].getTextField().addKeyListener(this);
			strings[i] = new ArrayList<ExtString>();
		}
		src = -1;
		same = 0;
		updateLabelText();
		chatwindows[0].getTextField().requestFocus();
	}

	public void actionPerformed(ActionEvent arg0) {
		handleInput(arg0.getSource());
	}

	public void keyPressed(KeyEvent arg0) {
		if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
			handleInput(arg0.getSource());
		}
	}

	public void updateLabelText() {
		for (int i = 0; i < 2; i++)
			Chat.chatwindows[i].setLabelText(same + " common tags!");
	}

	public void handleInput(Object object) {
		boolean reset = false;
		
		if (object instanceof JTextField) {
			src = object == chatwindows[0].getTextField() ? 0 : 1;
			threads[src].start();
			reset = true;
		} else {
			if (object instanceof JButton) {
				src = object == chatwindows[0].getSendButton() ? 0 : 1;
				threads[src].start();
				reset = true;
			}
		}
		if (reset) {
			if (src == 0)
				chatwindows[0].resetInputText();
			else
				chatwindows[1].resetInputText();
		}
		
		src_helper = src;
		src = -1;
	}
	
	public int getSrc_helper() {
		return src_helper;
	}

	/*public void doIt(int src) {
		String str = chatwindows[src].getInput();
		StringTokenizer tok = new StringTokenizer(str, ",");
		String tmp;
		/*
		 * variable 'pos' to store the position of the currently handled tokens within the string-list
		 */
		/*int pos = -1;
		boolean found = false;
		while (tok.hasMoreTokens()) {
			tmp = tok.nextToken().trim();
			for (int i = strings[src].size() - 1; i > -1; i--) {
				if (tmp.equals(strings[src].get(i).getContent())) {
					strings[src].get(i).IncCnt();
					found = true;
					pos = i;
				}
			}
			if (!found) {
				strings[src].add(new ExtString(tmp));
				pos = strings[src].size() - 1;
			}
			/*
			 * check if there is another common tag
			 */
			/*compareTags(src, pos, tmp);
		}
		for (int i = 0; i < 2; i++)
			chatwindows[i].writeText(src + 1, str);
	}*/
	
	
	

	//public void compareTags(int src, int pos, String str) {
		//ArrayList<ExtString> list = strings[(src + 1) % 2];
		//ExtString tmp;
		//for (int i = list.size() - 1; i > -1; i--) {
			//tmp = list.get(i);
			/*
			 * only increment the number of common tags if current token didn't match before
			 */
			//if (str.equals(tmp.getContent()) && !tmp.wasMatched()) {
				//this.same++;
				//tmp.matches();
				/*
				 * also mark in the other string-list that this token has matched
				 */
				//strings[src].get(pos).matches();
			//}
		//}
		//updateLabelText();
		/*
		 * undo following comment to display the string-lists every time someone types in something new
		 */
		//printArrayLists();
	//} 
	
	
	

	public void printArrayLists() {
		System.out.println("1:");
		for (int i = Chat.strings[0].size() - 1; i > -1; i--) {
			System.out.print(strings[0].get(i).getContent() + "("
					+ strings[0].get(i).getCnt() + ":"
					+ strings[0].get(i).wasMatched() + "); ");
		}
		System.out.println("\n2:");
		for (int i = Chat.strings[1].size() - 1; i > -1; i--) {
			System.out.print(strings[1].get(i).getContent() + "("
					+ strings[1].get(i).getCnt() + ":"
					+ strings[1].get(i).wasMatched() + "); ");
		}
		System.out.println("\n--------------------------------------");
	}

	public void keyReleased(KeyEvent arg0) {
	}

	public void keyTyped(KeyEvent arg0) {
	}

	public static void main(String[] args) {
		new Chat();
	}
}
```

ChatWindow:

```
public class ChatWindow extends JFrame implements WindowListener, Runnable {

	private static final long serialVersionUID = 1L;
	private final JTextPane text;
	private final JButton send;
	private final JTextField input;
	private final JLabel label, label_2;
	private final JPanel panel_1, panel_2, panel_3, panel_4;
	private final JScrollPane scp;
	private final Color col;
	private static boolean one_window_closed = false;
	private final int id;
	private static int cnt = 0;

	public ChatWindow() {
		id = cnt++ + 1;
		setTitle("PII - Uebung 01");
		setSize(400, 400);
		col = id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78);
		text = new JTextPane();
		text.setEditable(false);
		send = new JButton("send");
		send.setBackground(col);
		send.setForeground(Color.WHITE);
		input = new JTextField();
		label = new JLabel();
		label.setAlignmentX(Component.CENTER_ALIGNMENT);
		label_2 = new JLabel("Chat#" + id);
		label_2.setForeground(Color.WHITE);
		label_2.setAlignmentX(0.03f);
		scp = new JScrollPane(text);
		panel_1 = new JPanel();
		panel_2 = new JPanel();
		panel_3 = new JPanel();
		panel_4 = new JPanel();
		// -------------------------------------------------------------
		panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.PAGE_AXIS));
		panel_1.add(scp);
		panel_1.add(Box.createRigidArea(new Dimension(0, 15)));
		panel_1.add(label);
		panel_1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		// -------------------------------------------------------------
		panel_2.setLayout(new BoxLayout(panel_2, BoxLayout.LINE_AXIS));
		panel_2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		panel_2.add(input);
		panel_2.add(Box.createRigidArea(new Dimension(10, 0)));
		panel_2.add(send);
		// -------------------------------------------------------------
		panel_4.setLayout(new BoxLayout(panel_4, BoxLayout.PAGE_AXIS));
		panel_4.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_4.add(label_2);
		panel_4.setBackground(col);
		// -------------------------------------------------------------
		panel_3.setLayout(new BorderLayout());
		panel_3.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_3.add(panel_4, BorderLayout.PAGE_START);
		panel_3.add(panel_1, BorderLayout.CENTER);
		panel_3.add(panel_2, BorderLayout.PAGE_END);
		panel_3.setBackground(col);
		// -------------------------------------------------------------
		add(panel_3);
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation(dim.width / 2 - getWidth() * (id == 1 ? 1 : 0), dim.height
				/ 2 - getHeight() / 2);
		this.addWindowListener(this);
		setMinimumSize(new Dimension(200, 200));
		setVisible(true);
	}

	public String getInput() {
		return this.input.getText();
	}

	public void resetInputText() {
		this.input.setText("");
		this.input.requestFocus();
	}

	public void writeText(int id, String str) {
		if (str.trim().equals(""))
			return;
		StyledDocument doc = this.text.getStyledDocument();
		Style style = this.text.addStyle("", null);
		StyleConstants.setForeground(style, id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78));
		try {
			doc.insertString(doc.getLength(), "# " + id + ": ", style);
			doc.insertString(doc.getLength(), str + "\n", null);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

	public JButton getSendButton() {
		return this.send;
	}

	public JTextField getTextField() {
		return this.input;
	}

	public void setLabelText(String str) {
		this.label.setText(str);
	}

	public void windowClosing(WindowEvent arg0) {
		if (ChatWindow.one_window_closed)
			System.exit(0);
		else {
			this.setVisible(false);
			ChatWindow.one_window_closed = true;
		}
	}

	public void windowActivated(WindowEvent arg0) {
	}

	public void windowClosed(WindowEvent arg0) {
	}

	public void windowDeactivated(WindowEvent arg0) {
	}

	public void windowDeiconified(WindowEvent arg0) {
	}

	public void windowIconified(WindowEvent arg0) {
	}

	public void windowOpened(WindowEvent arg0) {
	}
	
	
	public void updateLabelText() {
		for (int i = 0; i < 2; i++)
			Chat.chatwindows[i].setLabelText(Chat.same + " common tags!");
	}
		
		public void compareTags(int src, int pos, String str) {
			ArrayList<ExtString> list = Chat.strings[(src + 1) % 2];
			ExtString tmp;
			for (int i = list.size() - 1; i > -1; i--) {
			  tmp = list.get(i);
				/*
				 * only increment the number of common tags if current token didn't match before
				 */
				if (str.equals(tmp.getContent()) && !tmp.wasMatched()) {
					Chat.same++;
					tmp.matches();
					/*
					 * also mark in the other string-list that this token has matched
					 */
					Chat.strings[src].get(pos).matches();
				}
			}
			updateLabelText();
			/*
			 * undo following comment to display the string-lists every time someone types in something new
			 */
			//printArrayLists();
		} 
	
	public void run() {
		Chat chat = new Chat();
		int src = chat.getSrc_helper();
		
		String str = Chat.chatwindows[src].getInput();
		StringTokenizer tok = new StringTokenizer(str, ",");
		String tmp;
		/*
		 * variable 'pos' to store the position of the currently handled tokens within the string-list
		 */
		int pos = -1;
		boolean found = false;
		while (tok.hasMoreTokens()) {
			tmp = tok.nextToken().trim();
			for (int i = Chat.strings[src].size() - 1; i > -1; i--) {
				if (tmp.equals(Chat.strings[src].get(i).getContent())) {
					Chat.strings[src].get(i).IncCnt();
					found = true;
					pos = i;
				}
			}
			if (!found) {
				Chat.strings[src].add(new ExtString(tmp));
				pos = Chat.strings[src].size() - 1;
			}
			/*
			 * check if there is another common tag
			 */
			compareTags(src, pos, tmp);
		}
		for (int i = 0; i < 2; i++)
			Chat.chatwindows[i].writeText(src + 1, str);
		
	}
}
```


----------



## Marco13 (23. Mai 2012)

Es ist immernoch fragwürdig in bezug auf Sinn und Inhalt, und auch noch falsch in der Umsetzung, aber jetzt immerhin etwas weniger fragwürdig und etwas weniger falsch. Der Hauptfehler dürfte sein, dass in "run()" ein neuer Chat erstellt wird. Das sollte nicht so sein. Stattdessen könnte/sollte der Chat z.B. dem Chatfenster (im Konstruktor) übergeben werden. Im Chatfenster kann man sich den Chat dann speichern, und später in "run" Methoden darauf aufrufen. Auch sollten diese fields im Chat nicht "static" sein, aber das erledigt sich damit gleich mit.


----------



## denis7788 (24. Mai 2012)

Hatten heute die Übung und es wurde darauf hingewiesen, dass das alles wenig Sinnn ergibt. War gedacht um sich über threads gedanken zu machen und an fremden code rum zu basteln...Das zum Sinn dahinter... Musterlösung werde ich auch bald erhalten.
Hier aber mal meine Lösung und die Gedanken dazu:
- Die doIt methode habe ich in run() eingearbeitet, da diese Methode nach dem event alle nachfolgendn Aktionen anstößt. Somit würden auch die nachfolgenden als Thread ablaufen!?
- compareTags() und updateLabel() habe ich auch nach ChatWindow übertragen, da diese durch doIt() aufgerufen werden
- jedem Chatwindow habe ich einen Parameter Chat mitgegeben, um ihn einem chat zuordnen zu können. so kann ich auch auf die ArrayList in der die Strings des Texpanes gespeichert werden und auf die anzahl gemeinsamer Tags zugreifen (same), die sich in Chat befinden (war vorgegeben)
- In handleInput() habe ich jeweils die run() methode aufgerufen (was glaub ich nix mit threads zu tun hat...aber der Zeitmangel...)
- Aufgabe zum compareTags über alle Chatfenster habe ich nicht lösen können in der Zeit. Aber denke das wird machbar sein.

Hier mal der Code:
Chat:

```
public class Chat implements ActionListener, KeyListener {

	public ChatWindow[] chatwindows;
	public static int same;
	public  ArrayList<ExtString>[] strings;
	private int src;
	public int src_helper;
	public int anzahlFenster;
	

	@SuppressWarnings("unchecked")
	public Chat() {
		anzahlFenster = Integer.parseInt(JOptionPane.showInputDialog("Wieviele Chatfenster möchten Sie starten?"));
		chatwindows = new ChatWindow[anzahlFenster];
		strings = new ArrayList[anzahlFenster];
		for (int i = 0; i < anzahlFenster; i++) {
			chatwindows[i] = new ChatWindow(this);
			Thread t = new Thread(chatwindows[i]);
			t.start();
			chatwindows[i].getSendButton().addActionListener(this);
			chatwindows[i].getTextField().addKeyListener(this);
			strings[i] = new ArrayList<ExtString>();
		}
		src = -1;
		src_helper = 1;
		same = 0;
		updateLabelText();
		chatwindows[0].getTextField().requestFocus();
	
	}

	public void actionPerformed(ActionEvent arg0) {
		handleInput(arg0.getSource());
		
	}

	public void keyPressed(KeyEvent arg0) {
		if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
			handleInput(arg0.getSource());
			
		}
	}

	public void updateLabelText() {
		for (int i = 0; i < anzahlFenster; i++)
			this.chatwindows[i].setLabelText(this.same + " common tags!");
	}
	
	

	public void handleInput(Object object) {
		//System.out.println("HandleInput wird ausgeführt!");
		boolean reset = false;
		if (object instanceof JTextField) {
			for(int i = 0; i < anzahlFenster; i++) {
				if(object == chatwindows[i].getTextField()){
					src = i;
					src_helper = src;
					chatwindows[src].run();
					reset = true;
				}
			}		
		
		} else {
			if (object instanceof JButton) {
				for(int i = 0; i < anzahlFenster; i++) {
					if(object == chatwindows[i].getSendButton()){
						src = i;
						src_helper = src;
						chatwindows[src].run();
						reset = true;
					}
				}	
			}
		}
		if (reset) {
			for (int i = 0; i <= anzahlFenster; i++){
				if(src == i) {
				chatwindows[i].resetInputText();
				}
			}
			
		}
		src = -1;
	}
	
	public int getSrc_helper(){
		return src_helper;
	}



	public void keyReleased(KeyEvent arg0) {
	}

	public void keyTyped(KeyEvent arg0) {
	}
	
	public static void main(String[] args) {
		new Chat();
	}

	
}
```

ChatWindow

```
public class ChatWindow extends JFrame implements WindowListener, Runnable {

	private static final long serialVersionUID = 1L;
	private final JTextPane text;
	private final JButton send;
	private final JTextField input;
	private final JLabel label, label_2;
	private final JPanel panel_1, panel_2, panel_3, panel_4;
	private final JScrollPane scp;
	private final Color col;
	private static boolean one_window_closed = false;
	private final int id;
	private static int cnt = 0;
	private Chat chat;

	public ChatWindow(Chat chat) {
		this.chat = chat;
		id = cnt++ + 1;
		setTitle("PII - Uebung 01");
		setSize(400, 400);
		col = id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78);
		text = new JTextPane();
		text.setEditable(false);
		send = new JButton("send");
		send.setBackground(col);
		send.setForeground(Color.WHITE);
		input = new JTextField();
		label = new JLabel();
		label.setAlignmentX(Component.CENTER_ALIGNMENT);
		label_2 = new JLabel("Chat#" + id);
		label_2.setForeground(Color.WHITE);
		label_2.setAlignmentX(0.03f);
		scp = new JScrollPane(text);
		panel_1 = new JPanel();
		panel_2 = new JPanel();
		panel_3 = new JPanel();
		panel_4 = new JPanel();
		// -------------------------------------------------------------
		panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.PAGE_AXIS));
		panel_1.add(scp);
		panel_1.add(Box.createRigidArea(new Dimension(0, 15)));
		panel_1.add(label);
		panel_1.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		// -------------------------------------------------------------
		panel_2.setLayout(new BoxLayout(panel_2, BoxLayout.LINE_AXIS));
		panel_2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		panel_2.add(input);
		panel_2.add(Box.createRigidArea(new Dimension(10, 0)));
		panel_2.add(send);
		// -------------------------------------------------------------
		panel_4.setLayout(new BoxLayout(panel_4, BoxLayout.PAGE_AXIS));
		panel_4.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_4.add(label_2);
		panel_4.setBackground(col);
		// -------------------------------------------------------------
		panel_3.setLayout(new BorderLayout());
		panel_3.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		panel_3.add(panel_4, BorderLayout.PAGE_START);
		panel_3.add(panel_1, BorderLayout.CENTER);
		panel_3.add(panel_2, BorderLayout.PAGE_END);
		panel_3.setBackground(col);
		// -------------------------------------------------------------
		add(panel_3);
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		setLocation(dim.width / 2 - getWidth() * (id == 1 ? 1 : 0), dim.height
				/ 2 - getHeight() / 2);
		this.addWindowListener(this);
		setMinimumSize(new Dimension(200, 200));
		setVisible(true);
		
		
	}

	public String getInput() {
		return this.input.getText();
	}

	public void resetInputText() {
		this.input.setText("");
		this.input.requestFocus();
	}

	public void writeText(int id, String str) {
		//System.out.println("writeText wurde aufgerufen!\n--------------");
		if (str.trim().equals(""))
			return;
		StyledDocument doc = this.text.getStyledDocument();
		Style style = this.text.addStyle("", null);
		StyleConstants.setForeground(style, id == 1 ? new Color(79, 128, 188) : new Color(192, 80, 78));
		try {
			doc.insertString(doc.getLength(), "# " + id + ": ", style);
			doc.insertString(doc.getLength(), str + "\n", null);
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

	public JButton getSendButton() {
		return this.send;
	}

	public JTextField getTextField() {
		return this.input;
	}

	public void setLabelText(String str) {
		this.label.setText(str);
	}

	public void windowClosing(WindowEvent arg0) {
		if (ChatWindow.one_window_closed)
			System.exit(0);
		else {
			this.setVisible(false);
			ChatWindow.one_window_closed = true;
		}
	}

	public void windowActivated(WindowEvent arg0) {
	}

	public void windowClosed(WindowEvent arg0) {
	}

	public void windowDeactivated(WindowEvent arg0) {
	}

	public void windowDeiconified(WindowEvent arg0) {
	}

	public void windowIconified(WindowEvent arg0) {
	}

	public void windowOpened(WindowEvent arg0) {
	}
	
	public void updateLabelText() {
		for (int i = 0; i < chat.anzahlFenster; i++)
			Chat.chatwindows[i].setLabelText(Chat.same + " common tags!");
	}
	
	public synchronized void compareTags(int src, int pos, String str) {
		//System.out.println("CompareTags wird ausgeführt!");
		ArrayList<ExtString> list = Chat.strings[(src + 1) % 2];
		ExtString tmp;
		System.out.println("list size = "+list.size());
		for (int i = list.size() - 1; i > -1; i--) {
			tmp = list.get(i);
			/*
			 * only increment the number of common tags if current token didn't match before
			 */
			if (str.equals(tmp.getContent()) && !tmp.wasMatched()) {
				Chat.same++;
				tmp.matches();
				/*
				 * also mark in the other string-list that this token has matched
				 */
				Chat.strings[src].get(pos).matches();
			}
		}
		updateLabelText();
		
	}
	
	@Override
	public void run(){
		int src = chat.getSrc_helper();
			String str = Chat.chatwindows[src].getInput();
			StringTokenizer tok = new StringTokenizer(str, ",");
			String tmp;
			/*
			 * variable 'pos' to store the position of the currently handled tokens within the string-list
			 */
			int pos = -1;
			boolean found = false;
			while (tok.hasMoreTokens()) {
				tmp = tok.nextToken().trim();
				for (int i = Chat.strings[src].size() - 1; i > -1; i--) {
					if (tmp.equals(Chat.strings[src].get(i).getContent())) {
						Chat.strings[src].get(i).IncCnt();
						found = true;
						pos = i;
					}
				}
				if (!found) {
					Chat.strings[src].add(new ExtString(tmp));
					pos = Chat.strings[src].size() - 1;
				}
				/*
				 * check if there is another common tag
				 */
				compareTags(src, pos, tmp);
			}
			for (int i = 0; i < chat.anzahlFenster; i++)
				Chat.chatwindows[i].writeText(src + 1, str);
		
		
	}

	

	
}
```


----------



## Marco13 (25. Mai 2012)

Nur kurz geschaut: Das müßte wohl nicht
chatwindows[src].run();
sondern
Thread t = new Thread(chatwindows[src]);
t.run();
sein, aber das wirklich nur in bzeug auf dieses spezifischen Punkt..


----------

