Concurrency und Graphics

Status
Nicht offen für weitere Antworten.

minimammut

Mitglied
Moin allerseits,
ich schreibe gerade an einer Visualisierung für Sortieralgorithmen.
Damit nicht das ganze Programm hängt während sortiert wird hab ich das starten der sortierung in nen eigenen thread gepackt.
Mit dem Observable pattern wird der view geupdated, der canvas extended.
Soweit so gut, beim adden des Canvas kann ich auch darauf zeichnen, nur wenn ich ihn updaten will returned
Java:
this.getGraphics()
immer null.
Ich versteh das nicht ganz, weil das Canvas ja eigentlich die ganze Zeit sichtbar ist.
Ich hoffe einer von euch kann mir helfen!
Vielen Dank schonmal, gruß minimammut
PS: Liste kommt aus sonner komischen Bibliothek die wir benutzen müssen - ich glaub aber nicht dass das mit dem Problem zusammenhängt.

Die Klasse mit dem Problem (SortierBeob.java)
Java:
package sortierdarstellung;

import java.awt.Canvas;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import sum.strukturen.Liste;

public class SortierBeob extends Canvas implements Observer{
    private Sortierer so;
    private ArrayList<Integer> a;
    private Graphics graphic;
    public SortierBeob(Sortierer s) {
        this.so = s;
    }

    public void update(Observable arg0, Object arg1) {
       Liste al = so.getListe();
       a = ausListe(al);
       updateDS();
       so.pause(Sort.VERZ);
    }
    private ArrayList<Integer> ausListe(Liste l) {
        ArrayList<Integer> ar = new ArrayList<Integer>();
        int i =1;
        do {
            l.geheZuPosition(i);
            ar.add((Integer)(l.aktuellesElement()));
            i++;
        }
        while(i<l.laenge());
        return ar;
    }
    public void updateDS() {
        int i = 0;
        if (this.getGraphics() != null) {
            this.getGraphics().clearRect(0, 0, this.getWidth(), this.getHeight());
            a.remove(0);
            for (int j : a) {
                this.getGraphics().drawOval(i, j, Sort.BREITE, Sort.BREITE);
                i += Sort.BREITE;
            }
        }
    }
    @Override
    public void paint(Graphics g) {
        this.graphic=g;
        System.out.println(g.getClass().toString());
        update(so,new Object());
    }
}

hier wird die Sortierung losgetreten: (Sort.java)
Java:
package sortierdarstellung;

import java.util.ArrayList;
import java.util.Collections;
import sum.strukturen.Liste;

class Sort {
    private Sortierer sorter=new FelixOliver();
    private Thread t = new Thread(sorter);
    private SortierBeob sb = new SortierBeob(sorter);
    public static final int BREITE=3;
    public static final int ANZAHL = 200;
    public static final int VERZ = 100;
    private ArrayList<Integer> a;

    public Sort() {
        fillList();
        sorter.setListe(zurListe(a));
        sorter.addObserver(sb);
    }
    public void sortiere(){
        t.start();
    }
    private void fillList(){
        a = new ArrayList<Integer>();
        for(int i=0;i<ANZAHL;i++) {
            a.add(i);
        }
        Collections.shuffle(a);
    }
    private Liste zurListe(ArrayList<Integer> a) {
        Liste list = new Liste();
        for(int i:a){
            list.haengeAn(i);
        }
        return list;
    }
    public Sortierer getSortierer() {
        return sorter;
    }

}
falls ihr noch irgendwas braucht oder fragen habt sagt bescheid!
 

Marco13

Top Contributor
Auf einer Component "getGraphics" aufrufen ist fast immer falsch. Erfreulicherweise brauche ich DIESMAL nicht dazuzusagen, warum es falsch ist (es liefert eben manchmal null....).

Ganz grib: Speichere dir die Liste, die im update übergeben wird, und mache in der paint-Methode das, was du jetzt in updateDS machst (aber eben nicht mit getGraphics(), sondern mit dem Graphics-Objekt, das an die paint-Methode übergeben wird)
 

minimammut

Mitglied
danke für die antwort, das klappt erstmal!
allerdings habe ich das Problem, dass durch aufruf von
Java:
this.repaint()
paint nicht neu aufgerufen wird.
Java:
package sortierdarstellung;

import java.awt.Canvas;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import sum.strukturen.Liste;

/**
 *
 * @author oliver
 */
public class SortierBeob extends Canvas implements Observer{
    private Sortierer so;
    private ArrayList<Integer> a;
    public SortierBeob(Sortierer s) {
        this.so = s;
    }

    public void update(Observable arg0, Object arg1) {
       System.out.println("aufgerufen");
       this.repaint();
       so.pause(Sort.VERZ);
    }
    private ArrayList<Integer> ausListe(Liste l) {
        ArrayList<Integer> ar = new ArrayList<Integer>();
        int i =1;
        do {
            l.geheZuPosition(i);
            ar.add((Integer)(l.aktuellesElement()));
            i++;
        }
        while(i<l.laenge());
        return ar;
    }
    @Override
    public void paint(Graphics g) {
        System.out.println("aufegrufen2");
        a = ausListe(so.getListe());
        g.clearRect(0, 0, this.getWidth(), this.getHeight());
        a.remove(0);
        int i = 0;
        for (int j : a) {
            g.drawOval(i, j, Sort.BREITE, Sort.BREITE);
            i += Sort.BREITE;
        }
        
    }
}
update wird aufgerufen, paint jedoch nicht.
wenn man die fenstergröße ändert wird paint aufgerufen und die darstellung ist wie sie sein soll.
Wie kann ich jetzt java dazu bringen paint aufzurufen wenn neu gezeichnet werden soll?
Danke, minimammut
 

Marco13

Top Contributor
paint wird nicht sofort nach repaint() aufgerufen, aber "so bald wie möglich" danach. Vermutlich hast du den Event-Dispatch-Thread mit der Sortierung blockiert. Ich schätze mal, du hast z.B. einen "Sortiere"-Button, und machst im ActionListener dann sowas wie
Code:
public void actionPerformed(ActionEvent e)
{
    sortiereUndRufeZwischendrinNotifyObserversAuf();
}
Das müßtest du dann ändern in
Code:
public void actionPerformed(ActionEvent e)
{
    Thread t = new Thread(new Runnable()
    {
        public void run()
        {
            sortiereUndRufeZwischendrinNotifyObserversAuf();
        }
    });
    t.start();
}
um das Sortieren in einem eigenen Thread laufen zu lassen. Um sicher zu sein, solltest du im Zweifelsfall aber ein bißchen mehr Code posten.
 

minimammut

Mitglied
beim drücken des knopfes wird sortiere aus der Klasse Sort aufgerufen (siehe Post 1).
Runnable wird vom Sorter implementiert.
Für mich sieht das so aus als würde die Sortierung in einem neuen Thread starten. Dafür spricht glaube ich auch dass das Fenster reaktionsfähig bleibt (schließen, resizen...) was bevor ich einen extra thread gemacht hab nicht so war. Auch im Debugger taucht ein zweiter Thread auf.
Hier noch ein bisschen Code:
Sortierer.java:
Java:
package sortierdarstellung;

import java.util.Observable;
import java.util.logging.Level;
import java.util.logging.Logger;
import sum.strukturen.Liste;

public abstract class Sortierer extends Observable implements Runnable{
    public abstract void setListe(Liste l);
    public abstract Liste getListe();
    public abstract void run();
    public void pause(int milli) {
        try {
            Thread.sleep(milli);
        } catch (InterruptedException ex) {
            Logger.getLogger(Sortierer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
}
FelixOliver.java:
Java:
package sortierdarstellung;

import sum.strukturen.Liste;

/**
 *
 * @author oliver
 */
class FelixOliver extends Sortierer{
    private Liste k;
    public FelixOliver() {
        //nnNNNIX
    }
    public void sortiere(Liste k) {
        System.out.println(Thread.currentThread().getName());
        this.k = k;
        k.zumAnfang();
        while (!k.istAmEnde()) {
            k.vor();
            Integer danach = (Integer) k.aktuellesElement();
            k.zurueck();
            if (((Integer) (k.aktuellesElement())).intValue() > danach.intValue()) {
                this.tauschedanach();
                int gespeichert = k.aktuellePosition();
                while (!(k.aktuellePosition()<3)) {
                   // k.zurueck();
                    k.zurueck();
                    Integer davor =(Integer)k.aktuellesElement();
                    k.vor();
                    if(((Integer) (k.aktuellesElement())).intValue() < davor.intValue()) {
                        tauschedavor();
                    }
                    k.zurueck();
                }
                k.geheZuPosition(gespeichert);
            }
            k.vor();
        }
    }

    private void tauschedanach() {
        Object Inhalt1 =k.aktuellesElement();
        k.vor();
        Object Inhalt2 = k.aktuellesElement();
        k.ersetzeAktuelles(Inhalt1);
        k.zurueck();
        k.ersetzeAktuelles(Inhalt2);
        super.setChanged();
        super.notifyObservers();
    }
    private void tauschedavor() {
        Object Inhalt1 =k.aktuellesElement();
        k.zurueck();
        Object Inhalt2 = k.aktuellesElement();
        k.ersetzeAktuelles(Inhalt1);
        k.vor();
        k.ersetzeAktuelles(Inhalt2);
        super.setChanged();
        super.notifyObservers();
    }

    @Override
    public Liste getListe() {
        return k;
    }

    @Override
    public void setListe(Liste l) {
        k=l;
    }

    @Override
    public void run() {
        sortiere(k);
    }
}
 

Marco13

Top Contributor
Hmja, was wird denn bei
System.out.println(Thread.currentThread().getName());
ausgegeben?
Und wo wird der Sortierer erstellt und gestartet?
(Ein compilierbares Beispiel wäre am besten - vielleicht liegt's auch an was anderem - das mit dem Thread hatte ich ja nur aus meiner Kristallkugel gelesen ;) )
 

minimammut

Mitglied
es wird Thread-2 ausgegeben
der Sortierer wird in Sort.java erstellt und gestartet (erster Post)
Kompilierbares Beispiel wird heute leider nichts mehr, ist nicht so leicht wegen der komischen Libraries...
vielleicht fällt dir ja auch so was ein.
 

Marco13

Top Contributor
OK, das ist dann zumindest schonmal nicht der falsche Thread. Hm... ???:L hab' nochmal drübergeschaut, aber jetzt spontan nichts entdeckt, woran das liegen könnte - außer vielleicht, dass der SortierBeob nicht der ist, der auf dem Bildschirm angezeigt wird (wobei das im Widerspruch zu der Aussage steht, dass bei einer Größenänderung das richtige angezeigt wird) : Im "Sort" wird der "SortierBeob sb" erstellt - der ist aber private, und ich sehe im Moment keine echte Möglichkeit, wie dieser Canvas wirklich der sein sollte, der auf dem Bildschirm zu sehen ist... Könnte es das sein? (Ggf. müßte der SortierBeob außerhalb von "Sort" erstellt und dann im Konstruktor an "Sort" übergeben werden...)

BTW: Das ganze erinnert an http://www.java-forum.org/awt-swing...en-einem-diagramm-sortieren-2.html#post403527 - aber ist nicht 1:1 übertragbar.
 

minimammut

Mitglied
du hattest recht – jetzt funktioniert es!
mir war das gestern mittag auch aufgefallen das da was komisch ist allerdings hab ich es aus dem gleichen grund wie du verworfen.
Als ich gesehn hatte was du geschrieben hast hab ich das gestern noch kurz geändert.
Warum es beim resizen ging: Beide SortierBeob greifen auf denselben Sortierer zurück.
Die benachrichtigungen werden an den falschen gesendet, deshalb kein repaint.
Das könnte auch der grund sein warum getgraphics immer null war...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
D [Concurrency/Threads] Code Umsetzung Schriftlich Java Basics - Anfänger-Themen 2
F Java Concurrency - Threads Java Basics - Anfänger-Themen 4
M HILFE JPanel - Graphics Java Basics - Anfänger-Themen 1
H Eingabe tätigen bevor Graphics g Fenster öffnet Java Basics - Anfänger-Themen 5
I Java Klassen "Graphics" und "MouseEvent" kombinieren Java Basics - Anfänger-Themen 7
CptK Interface Bilder mit Graphics g zeichnen Java Basics - Anfänger-Themen 7
J Erste Schritte drawLine Methode der Graphics Klasse Java Basics - Anfänger-Themen 2
J GUI / Graphics Java Basics - Anfänger-Themen 2
H Graphics / repaint Java Basics - Anfänger-Themen 8
K Zwei Fragen zu Graphics/Graphics2D Java Basics - Anfänger-Themen 5
R Cast java.awt.Graphics Java Basics - Anfänger-Themen 7
Azazel (Anfängerhilfe) awt.Graphics Schwierigkeiten Java Basics - Anfänger-Themen 6
I Methoden public void paintComponent (Graphics g) Java Basics - Anfänger-Themen 4
B Erste Schritte Anzeige von Graphics Objekten einzeln aktualisieren Java Basics - Anfänger-Themen 1
S Farbige Lebensleiste mit Graphics? Java Basics - Anfänger-Themen 10
S Ein Graphics Obejct mehrmals mit denselben Eigenschaften zeichnen lassen?!?!? Java Basics - Anfänger-Themen 4
S G Graphics Java Basics - Anfänger-Themen 1
thet1983 g.Graphics löschen? Java Basics - Anfänger-Themen 1
M Probleme mit paint() aus java.awt.Graphics Java Basics - Anfänger-Themen 2
A EAN13 Font auf graphics g erzeugt Monospaces Java Basics - Anfänger-Themen 14
N Graphics to png Java Basics - Anfänger-Themen 10
N Methode draw(Graphics g) aufrufen Java Basics - Anfänger-Themen 6
Dogge Problem mit paint(Graphics g) im Applet Java Basics - Anfänger-Themen 13
J Problem mit paint(Graphics g) Java Basics - Anfänger-Themen 4
J Jtable änderung soll graphics aktualisieren Java Basics - Anfänger-Themen 4
J JAVA Graphics Java Basics - Anfänger-Themen 5
A Graphics Objekt verhält sich merkwürdig Java Basics - Anfänger-Themen 2
G DRUCKEN von z.B. eines JFrame über print(Graphics g) Java Basics - Anfänger-Themen 9
Maxim6394 Probleme mit Graphics Java Basics - Anfänger-Themen 7
W von Graphics in BufferedImage Java Basics - Anfänger-Themen 10
M OOP Graphics immer selbstbezihend Java Basics - Anfänger-Themen 12
K Problem mit Parameter von paint(Graphics g) Java Basics - Anfänger-Themen 3
T Transparente Bilder mit Graphics zeichnen Java Basics - Anfänger-Themen 17
H Probleme mit Graphics G Java Basics - Anfänger-Themen 2
M Schiebepuzzle: MouseListener und Graphics? Java Basics - Anfänger-Themen 6
J Graphics g Java Basics - Anfänger-Themen 4
H Probleme mit Graphics Java Basics - Anfänger-Themen 5
B MouseListener & Graphics Java Basics - Anfänger-Themen 10
M Graphics zeichnen Java Basics - Anfänger-Themen 2
F Graphics PDFBox Java Basics - Anfänger-Themen 9
M kurze Frage zu Graphics Java Basics - Anfänger-Themen 5
Luk10 Buch für Swing/Awt/Graphics Java Basics - Anfänger-Themen 4
M Java Graphics etc. Java Basics - Anfänger-Themen 2
F Was ist Graphics g wirklich? Java Basics - Anfänger-Themen 5
J Klasse Graphics Nullpointerexception Java Basics - Anfänger-Themen 8
P Frage zu Graphics Java Basics - Anfänger-Themen 2
O graphics methode zeigt mein bild nicht an Java Basics - Anfänger-Themen 7
F Zweite Graphics-Methode wird nicht ausgeführt Java Basics - Anfänger-Themen 4
T rotes herz public void paint(Graphics g) Java Basics - Anfänger-Themen 2
G paintComponent(Graphics g) Java Basics - Anfänger-Themen 2
eQui Oberfläche mit Graphics zeichnen Java Basics - Anfänger-Themen 11
S Dicke bei Graphics Ovject einstellen Java Basics - Anfänger-Themen 2
V KSKB zum Verständnis von Graphics und paintComponent Java Basics - Anfänger-Themen 6
G mit Graphics erzeugte Strings verschwinden sofort wieder Java Basics - Anfänger-Themen 7
T Graphics von java.awt.Frame soll sich inhalt merken Java Basics - Anfänger-Themen 3
G Graphics-Object skalieren Java Basics - Anfänger-Themen 9
G Constructor & Graphics g Java Basics - Anfänger-Themen 5
F Frage zum Graphics Objekt Java Basics - Anfänger-Themen 3
D Instanz von Graphics in run() Java Basics - Anfänger-Themen 8
B Mouseevents und Graphics Java Basics - Anfänger-Themen 11
D Abstrakte Klasse Graphics Java Basics - Anfänger-Themen 3
W Verständisfrage zu Graphics Objekt Java Basics - Anfänger-Themen 3
P umwandeln von graphics nach image Java Basics - Anfänger-Themen 4
A Graphics g, AdjustmentEvent e Java Basics - Anfänger-Themen 5
Dilandau paint(Graphics g) { unbekannt in try{} / catch{} }? Java Basics - Anfänger-Themen 5
S Graphics Java Basics - Anfänger-Themen 11

Ähnliche Java Themen

Neue Themen


Oben