repaint wird trotz Thread nicht ausgeführt

tobitobsen82

Grünschnabel
Hallo Leude,

folgendes Programm tut nicht, was es soll:

ein Algorithmus (z. B. BubbleSort) soll grafisch mittels Canvas/Paint() dargestellt werden. Man hat ein dynamisch erzeugbares int[] beliebiger Länge, welches zuerst im Ausgangszustand durch unterschiedlich hohe (Höhe in Relation zur Größe des int-Werts) Balken dargestellt wird. Danach wird die sortBubble() Methode ausgeführt, welche mit einem gewissen Delay mittels Thread/sleep etwas ausgebremst wird. Hierbei soll aber nicht nur das Array im Sinne des Algorithmus umgeformt werden, sondern auch ein repaint() ausgeführt werden, um den (nach jedem Durchlauf des gesamten Arrays) aktuellen Stand des Arrays wiederum als Balkengrafik wie oben beschrieben darzustellen. Und genau das geht nicht. Zwar bekomme ich ein SystemOut nach der Sleep-Anweisung, jedoch wird kein repaint() darin ausgeführt. Die Veränderungen am Array werden über die printArray-Methode kontrolliert und funktionieren auch.

Nachfolgend der Code aus der SortBubble-Klasse (extends Sort -> Sort ist ein Canvas, welches einige getXY-Methoden mitbringt):

Code:
package gui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Timer;
import java.util.TimerTask;

import gui.AlgorithmenFenster;

public class SortBubble extends Sort {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private AlgorithmenFenster aF;
	private int[] array;
	private int yAxis;
	private int staticXAxis = this.getWidth();
	private int xAxis;
	private int staticYAxis = this.getHeight();
	private int height;
	private int width = 5;
	
	public SortBubble(int[] array){
		this.array = array.clone();		
	}
	
	public void paint(Graphics g) {
		System.out.println("paint");
		g.clearRect(0, 0, getWidth(), getHeight());
		String infoLabel = "Ticks: - Vergleiche: " + getVergleiche() + " Vertauschungen: " + getVertauschungen();
		g.setColor(Color.black);		
		g.drawString(infoLabel, staticXAxis, staticYAxis + getHighestValue() + 69);		
		
		g.setColor(Color.black);
		g.drawLine(1, getHighestValue() + 70, array.length * 7, getHighestValue() + 70);
		
		g.setColor(Color.blue);		
		for (int i = 0; i < array.length; i++) {
			xAxis = i*7;
			yAxis = this.getHeight() - 1 - array[i];
			height = array[i];
			g.draw3DRect(xAxis, yAxis - 15, width, height, true);
		}
	}
	
	private int getHighestValue() {
		int highest = 0;
		for (int i = 0; i < array.length; i++) {
			if (array[i] > highest) {
				highest = array[i];
			}
		}
		return highest;
	}
	
	//--------------------------------ALGORITHMUS----------------------------
	
	public void sortArray(){
		sort(array);
		repaint();
	}
	
	private void sort(int[] a) {
		array = a;
		for (int i = 0; i < array.length - 1; i++) {
			printArray();
			for (int j = array.length - 1; j > i; j--) {
				
				vergleiche++;
				
				try {
					Thread.sleep(10);
					repaint();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if (array[j - 1] > array[j]) {
					vertauschungen++;
					int temp = array[j - 1];
					array[j - 1] = array[j];
					array[j] = temp;
				}
			}
		}
	}
	
	public void printArray(){
		for(int k = 0 ; k < array.length ; k++){
			System.out.print(array[k]);
		}
		System.out.println();
	}
	
	public int[] getArray(){
		return array;
	}
}
 
Moin!
Probiers mal mit
Code:
public void paint(Graphics g) {
   super.paint(g);
   ...
   ...
}

*grüssle*
MeinerEiner
 
Hi,

geht leider nicht. In der Konsole kriege ich weiterhin das initialisierende "paint", dann das aktuelle array während des Durchlaufs des Algorithmus und dann aber wieder erst am Ende ein weiteres "paint" ausgegeben. Eigentlich müsste aber das syso "paint" pro Array-Durchlauf ausgegeben werden. Die repaint() wird also erst gar nicht aufgerufen.
 
Also dein Programm läuft bei mir ohne Probleme...
zeigt auch die entsprechenden Schritte an...

Kann es sein, das deine GUI noch nicht fertig aufgebaut ist, der Algorithmus aber bereits läuft? Dann kann es nämlich passieren, das die repaint Methode nicht korrekt aufgerufen wird...

Code:
package gui;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;



public class Test extends JPanel {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    private int[] array;
    private int yAxis;
    private int staticXAxis = this.getWidth();
    private int xAxis;
    private int staticYAxis = this.getHeight();
    private int height;
    private int width = 5;
    
    public Test(int[] array){
        this.array = array.clone();
                
                
    }
    
    public void paint(Graphics g) {
        System.out.println("paint");
        g.clearRect(0, 0, getWidth(), getHeight());
        g.setColor(Color.black);        
        
        g.setColor(Color.black);
        g.drawLine(1, getHighestValue() + 70, array.length * 7, getHighestValue() + 70);
        
        g.setColor(Color.blue);        
        for (int i = 0; i < array.length; i++) {
            xAxis = i*7;
            yAxis = this.getHeight() - 1 - array[i];
            height = array[i];
            g.draw3DRect(xAxis, yAxis - 15, width, height, true);
        }
    }
    
    private int getHighestValue() {
        int highest = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] > highest) {
                highest = array[i];
            }
        }
        return highest;
    }
    
    //--------------------------------ALGORITHMUS----------------------------
    
    public void sortArray(){
        sort(array);
        repaint();
    }
    
    private void sort(int[] a) {
        array = a;
        for (int i = 0; i < array.length - 1; i++) {
            printArray();
                        for (int j = array.length - 1; j > i; j--) {
                
                try {
                    Thread.sleep(100);
                                        repaint();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (array[j - 1] > array[j]) {
                    int temp = array[j - 1];
                    array[j - 1] = array[j];
                    array[j] = temp;
                }
            }
        }
    }
    
    public void printArray(){
        for(int k = 0 ; k < array.length ; k++){
            System.out.print(array[k]);
        }
        System.out.println();
    }
    
    public int[] getArray(){
        return array;
    }
        
        public static void main(String[] arg){
            int[] i = {12,1,5,34,12,45,67,97,5,3,2};
            JFrame j = new JFrame();
            Test t = new Test(i);
            j.getContentPane().add(t);
            j.setSize(500,500);
            j.setVisible(true);
            j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            t.sortArray();
        }
}

*grüssle*
MeinerEiner
 
Dann haben wir uns falsch verstanden. Die GUI steht bereits. Auf der Konsole werden die Zwischenschritte bzgl. des Algorithmus bzw. des Arrays auch angezeigt, jedoch wird die repaint() Methode nicht ausgeführt und somit nur das Initialisierte Array und das fertig sortierte angezeigt, allerdings nicht die Zwischenschritte ( die gibts nur auf der Konsole mit syso).
 
Ich denke wir haben uns schon richtig verstanden..
Auf dem Bildschirm wird ausgegeben(anhand der Balken), wie das Array sortiert ist, die entsprechende debug asugabe (paint) kommt auch.. Alle Zwischenschritte werden angezeigt!
Schau dir mal den von mir geposteten Code an..

Falls ich dich dennoch falsch verstehe.. nun dann geb ichs auf..

*grüssle*
MeinerEiner
 
Haben wieder etwas weitergearbeitet...Idee momentan ist, den Algorithmus in einen eigene Thread zu legen und die repaint() in einem eigenen "Repaint"-Thread auszuführen. Geht im moment allerdings noch nicht.

Hier die aktuellen Klassen:

Klasse SortBubble
Code:
package gui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import gui.AlgorithmenFenster;

public class SortBubble extends Sort implements ActionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private AlgorithmenFenster aF;
	private int[] array;
	private int yAxis;
	private int staticXAxis = this.getWidth();
	private int xAxis;
	private int staticYAxis = this.getHeight();
	private int height;
	private int width = 5;
	
	public SortBubble(int[] array){
		this.array = array;
		repaint();
	}	
	
	public void startSort(){
		new SortThread(this, array);
	}
	
	public void paint(Graphics g) {
		System.out.println("paint");
		g.clearRect(0, 0, getWidth(), getHeight());
		String infoLabel = "Ticks: - Vergleiche: " + getVergleiche() + " Vertauschungen: " + getVertauschungen();
		g.setColor(Color.black);		
		g.drawString(infoLabel, staticXAxis, staticYAxis + getHighestValue() + 69);		
		
		g.setColor(Color.black);
		g.drawLine(1, getHighestValue() + 70, array.length * 7, getHighestValue() + 70);
		
		g.setColor(Color.blue);		
		for (int i = 0; i < array.length; i++) {
			xAxis = i*7;
			yAxis = this.getHeight() - 1 - array[i];
			height = array[i];
			g.draw3DRect(xAxis, yAxis - 15, width, height, true);
		}
	}
	
	private int getHighestValue() {
		int highest = 0;
		for (int i = 0; i < array.length; i++) {
			if (array[i] > highest) {
				highest = array[i];
			}
		}
		return highest;
	}
	
	//--------------------------------ALGORITHMUS----------------------------
	
	public void zeichneSortierung(){
		System.out.println("Sortierung wird gezeichnet.");
		repaint();
	}

	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
		
	}
	
	public void printArray(){
		for(int k = 0 ; k < array.length ; k++){
			System.out.print(array[k]);
		}
		System.out.println();
	}
	
	public int[] getArray(){
		return array;
	}

	public void setArray(int[] array) {
		this.array = array;
		repaint();
	}
}

Klasse SortThread:

Code:
package gui;

public class SortThread extends Thread {

	SortBubble referenzBubble;
	Sort referenzSort;
	
	private int[] array = referenzBubble.getArray();
	private int vergleiche;
	private int vertauschungen;

	public SortThread(SortBubble bubble, int[] array) {
		referenzBubble = bubble;
		this.array = array;
		start();
	}

	public void run() {
		sort(array);
	}
	
	private void sort(int[] a) {
		array = a;
		//sortiertNoch = true;
		//new SortThread(this);
		for (int i = 0; i < array.length - 1; i++) {
			referenzBubble.printArray();
			try {
				referenzBubble.setArray(array.clone());
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
			for (int j = array.length - 1; j > i; j--) {
				vergleiche++;
				if (array[j - 1] > array[j]) {
					vertauschungen++;
					int temp = array[j - 1];
					array[j - 1] = array[j];
					array[j] = temp;
				}
			}
		}
	}

}


Klasse Sort:
Code:
package gui;

import java.awt.Canvas;

public abstract class Sort extends Canvas{
	protected int vergleiche;
	protected int vertauschungen;
	protected long delay = 1;
	protected int[] currentArray;
	
	public void setTimeDelay(int value){
		delay = (long)value;
	}
	
	public int getVergleiche(){
		return vergleiche;
	}
	
	public int getVertauschungen(){
		return vertauschungen;
	}
	
	public int[] getCurrentArray(){		
		return currentArray;
	}
}

Klasse Fenster:

Code:
package gui;

import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Fenster {

	/**<b>Hauptprogramm Fenster (Übung 4)</b><br>
	 * Dateiname: Fenster.java
	 * Compiler: JRE 1.6.0_01 (Eclipse SDK 3.2.1)
	 * @since 03.06.07
	 * Letzte Änderung: 03.06.07
	 * Beschreibung des Moduls: Hauptprogramm zur Anzeige. Methoden werden teils aus der Klasse FensterElemente bezogen
	 * Paket: gui
	 */
	public static void main(String[] args) {		
		// Instanzierung des Fensterobjekts
		AlgorithmenFenster fensterobjekt = new AlgorithmenFenster("Algorithmen Fenster");		
		
		KontrollCenter kC = new KontrollCenter(fensterobjekt);

		fensterobjekt.setVisible(true);
		
		fensterobjekt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);		
		kC.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

class AlgorithmenFenster extends JFrame{
	private static final long serialVersionUID = 1L;
	
	//Variablendeklaration
	public JPanel panel;	
	private int[] array = randomArray(10);
	public SortBubble bubble;
	public SortSelection selection;	
	public Container cpane;
	
	public AlgorithmenFenster( String titel ){
		super(titel);
		setSize(600,380);
				
		cpane = this.getContentPane();
		GridBagLayout gbl = new GridBagLayout();
	    cpane.setLayout (gbl);
		
		setupBubble();
		setupSelection();
	}
	
	public void setupBubble(){		
		bubble = new SortBubble(array);
		bubble.setSize(this.getWidth() - 10,120);		
		
	    panel = new JPanel();   	    
	    panel.add(bubble);
	    addComponent(cpane, panel, 0,0);

		repaint();
	}
	
	public void setupSelection(){		
		selection = new SortSelection(array);
		selection.setSize(this.getWidth() - 10,120);		
		
	    panel = new JPanel();	    
	    panel.add(selection);
	    addComponent(cpane, panel, 0,1);
	   
		repaint();
	}
	
	public void setNewRandom(int length){
		array = randomArray(length);
		setupBubble();
		setupSelection();
	}
	
	public int[] randomArray(int length){
		int[] array = new int[length];
		//Random generator = new Random();
		for(int i = 0 ; i < length ; i++){
			array[i] = (int)(50*Math.random());
			
		}
		return array;
	}
	
	public void addComponent(Container container, Component component, int xAxis, 
			                 int yAxis){
		
	    GridBagConstraints constr = new GridBagConstraints();

	    constr.gridx = xAxis;	//Spalte
	    constr.gridy = yAxis;	//Zeile	    
	    constr.anchor = GridBagConstraints.WEST;
	    constr.gridwidth = GridBagConstraints.REMAINDER;
	    
	    container.add(component, constr);
	}
	
	class EventHandling implements ActionListener{
		public void actionPerformed(ActionEvent event){
			//EventHandling für das Fenster
			if(event.getActionCommand().equals("Beenden")){
				System.exit(0);				
			}
			else if(event.getActionCommand().equals("Windows")){
				updateLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
			}
			else if(event.getActionCommand().equals("Metal")){
				updateLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");				
			}
			else if(event.getActionCommand().equals("Motif")){
				updateLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");	
			}		
		}	
	}
	
	/**
	 * Verändert das LookAndFeel des gesamten Fensters je nach Userwunsch
	 * 
	 * @param laf Enthält den Pfad des gewünschten LookAndFeel
	 */	
	public void updateLookAndFeel(String laf){				
		try{
			UIManager.setLookAndFeel(laf);
			SwingUtilities.updateComponentTreeUI(this);
		}
		catch(Exception xcpt){
			System.out.println("Fehler beim Ändern des Look and Feel: " + xcpt.getLocalizedMessage());
		}
		this.pack();
	}

	public void startSorts() {
		bubble.startSort();
		selection.sortArray();
	}
	
}//Ende der Klasse KarteikartenFenster
 
Recht haste, sieht gut aus. Unser Problem scheint dann wohl wirklich ein Mixing von AWT und Swing zu sein, da die Darstellung auf einem Canvas stattfindet und nicht wie bei dir auf einem Frame...

Gibt es eine Möglichkeit, das mit Canvas auch hinzukriegen?
 
Dein Algorithmen Fenster ist qauch ein ein JFrame? Ich denke mal du meinst das Sort Fenster, das JPanel..
Nun nutze mal statt JPanel ein Canvas und es funktioniert trotzdem (zumindest bei mir)

*grüssle*
MeinerEiner
 
Zurück