Grafikfehler nach einem Robot-Mausklick


#1

Moin,

ich habe ein Programm geschrieben, das u.a. per Mausklick Daten in einem anderen (in Delphi geschriebenen) Programm updatet. Dabei wird in beiden Programmen, die zu diesem Zeitpunkt übereinander auf dem Bildschirm angeordnet sind (eins verdeckt das andere teilweise), die Oberfläche teilweise aktualisiert/neu gezeichnet.
Zuerst wird in meinem Programm nach Ablauf einer definierten Zeit eine automatische Routine gestartet, die zunächst per Robot auf einen Button im “externen” Programm geklickt, worauf sich dieses neue Daten besorgt und auf seiner Oberfläche darstellt. 500 ms später beauftragt die Routine mein Programm seine Daten zu aktualisieren. Zu diesem Zeitpunkt hat das externe Programm sein Update noch nicht abgeschlossen.
Dabei kommt es zu Grafikfehlern auf dem Bildschirm. Teile der Oberflächen sind miteinander vermischt.

Ich bin nun ratlos. Ich vermute, dass beide Programme parallel in den Grafikspeicher schreiben. Kann das sein?
Mein Lösungsansatz, den ich noch nicht probiert habe ist, eine Pausenzeit zwischen den jeweiligen Updates der Programme einzubauen, so dass es eben nicht mehr zu den vermuteten parallelen Zeichenvorgängen kommt.

Habt ihr mit solchen Sachen schon mal zu tun bekommen? Welchen möglichen Fehler könnte ich sogar eingebaut haben, der damit gar nichts zu tun hat?

Danke für eure Hilfe/Meinungen.

Lex


#2

Schwer, bei sowas eine Ferndiagnose zu erstellen. Ein paar Punkte:

  • Welches Programm verdeckt (teilweise) welches andere? Ist das Delphi- oder das Java-Programm im Vordergrund?
  • Wo treten die Grafikfehler auf? Willkürlich/random, oder immer an der gleichen Stelle? Wird z.B. immer eine spezielle Component, die “hinten” sein sollte, “vorne” gezeichnet? Oder ist es einfach Pixelmüll?
  • Klassiker: Grafikkartentreiberupdate :wink:
  • Tritt das Problem nur zusammen mit Robot auf, oder auch, wenn man die Robot-Aktionen manuell macht?
  • (tbc)

#3

Danke für deinen Beitrag, Marco13.

Das Java-Programm liegt teilweise über dem Delphi-Programm, der Button, der geklickt werden muss, ist in der Delphi-Oberfläche erreichrbar. Das Java-Programm geht dann aber durch den Mausklick in den Hintergrund. Nach 300 ms durch [inline]robot.delay(300);[/inline] habe ich derzeit eine kurze Pause drin, danach rufe ich im Java-Programm [inline]setVisible(true);[/inline] auf dem JFrame auf.

Hmm, so genau habe ich mir das nicht angesehen. Aber es wurde neben Grafik-Mix meist ein Bereich meines JFrames verdeckt bzw. leer dargestellt, in dem eigentlich einige JButtons und JLabels mit fixen Informationen eingebaut sind. Die JTable, in der die Daten aktualisiert werden, wird immer vollständig angezeigt.

Grafikkartentreiber kann ich nicht updaten, ist ein “outsourced” Firmenrechner.

Wenn ich die Aktionen manuell ohne Robot durchführe funktioniert alles. Ich muss abschließend eben nur meinen JFrame wieder nach vorne holen.


#4
  • Hört sich für mich so an als würdest du dein Fenster von einem anderen Thread ausführend in den Vordergrund holen.(?)
    Versuchs mal mit EventQueue.invokeLater() auf dem EDT.

  • Oder ist es genau umgekehrt herum und du führst alles auf dem EDT aus? Sprich blockiert den EDT.

  • Denkst du auch an das provisorische repaint()?


#5

Danke, TMII.

Die ersten beiden Hinweise muss ich noch mal genau prüfen, da ist ein Thread und der EDT im Spiel.
Den 3. Hinweis könntest du mir bitte noch mal näher erläutern. Ich kann mit einem provisorischem repaint() nix anfangen.
Wo baust du das ein? Und warum?


#6

Die Frage, auf welchem Thread die Aktionen durchgeführt werden, könnte durchaus relevant sein. Aber ich gehe mal davonn aus, dass die Robot-Aktionen nicht im EDT durchgeführt werden, sondern in einem eigenen Thread.

Unabhängig davon: setVisible hat eigentlich nichts damit zu tun, ob das Fenster im Vordergrund ist, oder nicht. Eigentlich gibt’s dafür toFront. Sowas wie

SwingUtilities.invokeLater(new Runnable() 
{
    @Override
    public void run() 
    {
        frame.toFront();
        frame.repaint();
    }
});

sollte eigentlich den gewünschten Effekt haben.

(Bei solchen “Fenstermanger- und OS-spezifischen” Sachen gibt’s aber immer mal wieder Glitches, weil irgendein OS irgendeine Operation eben nicht unterstützt, oder das Ergebnis nicht eindeutig ist. Zumindest erinnere ich mich dunkel, mal irgendwas damit gemacht zu haben, und da dann scheinbar (!) sinnlos mit ein paar verschachtelten toFront, toBack, frame.setAlwaysOnTop(true); / false hin- und her schalten zu müssen, damit es funktionierte - aber was genau das war, weiß ich gerade nicht mehr)


#7

Danke Marco13. Ich probiere deinen Vorschlag aus, der Rat klingt plausibel.


#8

Danke TMII, dein Tipp ging in die richtige Richtung, Marco13 hat dann das Codebeispiel noch gebracht, das der Lösung sehr nahe kam.

Ich hatte tatsächlich einige Dinge bei der Aktualisierung der GUI in Threads und EDT vermischt bzw. nicht Threadsicher programmiert. Ich habe ein paar Methoden noch mal überarbeitet. Ein [inline]setVisible(true);[/inline] musste ich trotzdem setzen.

Jedenfalls geht das jetzt perfekt. Danke euch beiden.