Java EventRecorder/Player

Status
Nicht offen für weitere Antworten.

thE_29

Top Contributor
Also ich bräuchte (bzw ich muss das Schreiben wenn es das noch nicht gibt - für was das Rad erfinden falls es sowas schon gibt) das mir alle Events von meinem Programm (auch Java) aufnimmt.

Also Tastendrücke, Mouseklicke usw und das müsste ich danach dann wieder abspielen können (für Massentests halt).


Mit Robot könnte ich die Tastendrücke simulieren (so einen Player habe ich schon) nur ist mir das mit Koordinaten bezüglich Mausklicks ziemlich blöde (falls das Programm verruckt oder sonstiges).


Also wie könnte ich das gegebenenfalls am besten implementieren, bzw gibt es sowas in Java schon (muss unter Linux + Win laufen können).


Mfg
 
B. Eckel hat in seinem Buch "Thinking in Java" in Kap. 13 ein Beispiel "TrackEvent.java", mit dem alle Events jeweils via JLabel (nur) angezeigt werden.

Das könntest du als Basis oder Anregung verwenden, müsstest es allerdings noch erweitern.
 
ich musste sowas mal für unsere firma programmieren. der code is _stark_ verbesserungsfähig, teilweise wird die thread-unsicherheit von swing nicht berücksichtigt, aber da diese funktion bei uns lediglich zu debugzwecken benutzt wurde, is das ganze auf dem stand geblieben, auf dem ich damals in punkto java war 😉

Code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;



/*

voraussetzung für die funktionalität:

alle auftauchende subklassen von Window müssen das als parameter
übergebene Window als "owner" aufweisen

*/



public final class EventTracer {

  private static ObjectOutputStream myObjectOutputStream;
  private static FileOutputStream myFileOutputStream;
  private static AWTEventListener myAWTEventListener;

  // pause zw. einzelnen events
  private static long myTime;

  // welche events sind überhaupt von interesse?
  private static final long myEvents = AWTEvent.ACTION_EVENT_MASK |
                                       AWTEvent.KEY_EVENT_MASK |
                                       AWTEvent.MOUSE_EVENT_MASK |
                                       AWTEvent.MOUSE_MOTION_EVENT_MASK;

  // in dieser form werden die events erfasst
  private static final int EVENT_ACTION =       1;
  private static final int EVENT_KEY =          2;
  private static final int EVENT_MOUSE =        4;
  private static final int EVENT_MOUSE_MOTION = 8;

  // true, wenn gerade eine aufzeichnung läuft
  private static boolean myIsTraceRunning = false;

  // true, wenn gerade eine ausführung der aufgezeichneten events läuft
  private static boolean myIsApplyRunning = false;

  // var., mit deren hilfe die doppelte erfassung von keyevents vermiden wird
  private static boolean myEven = false;



  //---------------------------------------------------------------------------
  public static void startTracingAWTEvents(final Window window,
                                           final int terminateKey) {

    if (isAnythingRunning(window)) return;


    new Thread() { public void run() {

      JFileChooser fc = new JFileChooser();
      fc.setSelectedFile(new File("events.bin"));
      fc.setDialogTitle("Ereignisdatei speichern...");
      if (fc.showSaveDialog(window) != JFileChooser.APPROVE_OPTION) return;
      final String filePath = fc.getSelectedFile().getPath();

      myIsTraceRunning = true;

      // öffne die beiden benötigten streams
      try {
        myFileOutputStream = new FileOutputStream(filePath);
        myObjectOutputStream = new ObjectOutputStream(myFileOutputStream);
      } catch (Exception e) {
        myFileOutputStream = null;
        myObjectOutputStream = null;
        System.out.println("Fehler beim Schreiben der Event-Datei");
        e.printStackTrace();
        return;
      }

      myTime = System.currentTimeMillis();

      myAWTEventListener = new AWTEventListener() {
        public void eventDispatched(AWTEvent e) {

          // erfasse je nach 'typ' des events relevante parameter

          // fall 1: MouseEvent
          if (e instanceof MouseEvent) {
            MouseEvent me = (MouseEvent)e;
            int x = me.getX(), y = me.getY();
            Component c = (Component)me.getSource();
            // berechne die zum Window relativen koordinaten der komponente
            while ( !(c == window) ) {
              x += c.getX();
              y += c.getY();
              if ( c instanceof Window ) { // wenn die komponente ein window
                                        // oder eine subklasse von window ist...
                c = ((Window)c).getOwner(); // 'window' muss der owner sein
                x -= window.getX();
                y -= window.getY();
              } else {
                c = c.getParent();
              }
            }
            // schreibe ermittelte daten in datei
            try {
              myObjectOutputStream.writeShort(EVENT_MOUSE);
              myObjectOutputStream.writeInt(me.getID());
              myObjectOutputStream.writeShort(x);
              myObjectOutputStream.writeShort(y);
              myObjectOutputStream.writeInt(me.getModifiers());
            } catch (Exception ex) {
              System.out.println("Fehler beim schreiben in Datei");
              ex.printStackTrace();
            }
          }

          // fall 2: KeyEvent
          if (e instanceof KeyEvent) {

            // vermeide das (unerklärliche) doppelte erfassen von keyevents
            myEven = !myEven;
            if (myEven) return;

            KeyEvent ke = (KeyEvent)e;
            int kc = ke.getKeyCode();
            if (kc == terminateKey) stopTracingAWTEvents(window);
            try {
              myObjectOutputStream.writeShort(EVENT_KEY);
              myObjectOutputStream.writeInt(ke.getID());
              myObjectOutputStream.writeInt(ke.getKeyCode());
            } catch (Exception ex) {
              System.out.println("Fehler beim schreiben in Datei");
              ex.printStackTrace();
            }
          }

          try {
            myObjectOutputStream.writeLong(System.currentTimeMillis() - myTime);
          } catch (Exception ex) {
            System.out.println("Fehler beim schreiben in Datei");
            ex.printStackTrace();
          }
          myTime = System.currentTimeMillis();
        }
      };

      // füge globalen awtlistener ein
      Toolkit.getDefaultToolkit().addAWTEventListener(myAWTEventListener, myEvents);
    }}.start();
  }



  //---------------------------------------------------------------------------
  private static void stopTracingAWTEvents(Window window) {
    // save all occured awt events to a binary file
    try {
      myObjectOutputStream.flush();
      myFileOutputStream.flush();
    } catch (Exception e) {
      e.printStackTrace();
    }

    // remove the global awt event listener
    Toolkit.getDefaultToolkit().removeAWTEventListener(myAWTEventListener);
    myAWTEventListener = null;

    myObjectOutputStream = null;
    myFileOutputStream = null;

    myIsTraceRunning = false;

    JOptionPane.showMessageDialog(window, "Aufzeichnung beendet.");
  }



  //---------------------------------------------------------------------------
  public static void runRecordedEvents(final Window window) {

    if (isAnythingRunning(window)) return;

    new Thread() { public void run() {

      JFileChooser fc = new JFileChooser();
      fc.setSelectedFile(new File("events.bin"));
      fc.setDialogTitle("Ereignisdatei öffnen...");
      if (fc.showOpenDialog(window) != JFileChooser.APPROVE_OPTION) return;
      final String filePath = fc.getSelectedFile().getPath();

      myIsApplyRunning = true;

      FileInputStream fis;
      ObjectInputStream ois;
      try {
        fis = new FileInputStream(filePath);
        ois = new ObjectInputStream(fis);
      } catch (Exception e) {
        fis = null;
        ois = null;
        System.out.println("Fehler beim Öffnen der Event-Datei");
        e.printStackTrace();
        return;
      }

      Robot robot = null;
      try {
        robot = new Robot();
      } catch (Exception e) {
        System.out.println("Konnte Robot nicht initialisieren");
        e.printStackTrace();
        return;
      }

      int event;
      while (true) {
        try {
          event = (int)ois.readShort();

          switch (event) {
            case EVENT_MOUSE:
              int mouseActID = ois.readInt();
              int x = (int)ois.readShort();
              int y = (int)ois.readShort();
              int modifiers = ois.readInt();
              if (mouseActID == MouseEvent.MOUSE_PRESSED)
                robot.mousePress(modifiers);
              else if (mouseActID == MouseEvent.MOUSE_RELEASED)
                robot.mouseRelease(modifiers);
              else if (mouseActID == MouseEvent.MOUSE_MOVED)
                robot.mouseMove(x + window.getX(), y + window.getY());
              break;
            case EVENT_KEY:
              int keyActID = ois.readInt();
              int keyCode = ois.readInt();
              if (keyActID == KeyEvent.KEY_PRESSED)
                robot.keyPress(keyCode);
              else if (keyActID == KeyEvent.KEY_RELEASED)
                robot.keyRelease(keyCode);
          }

          // pause
          sleep(ois.readLong());

        } catch (Exception ex) {
          ex.printStackTrace();
          break;
        }
      }

      // gebe control-taste frei
      robot.keyRelease(KeyEvent.VK_CONTROL);

      myIsApplyRunning = false;
      JOptionPane.showMessageDialog(window, "Ausführung beendet.");

    }}.start();
  }



  //---------------------------------------------------------------------------
  /// prüfe ob gerade eine aufzeichnung/ausführung läuft
  private static boolean isAnythingRunning(Window window) {
    // prüfe ob nicht gerade eine aufzeichnung läuft
    if (myIsTraceRunning) {
      JOptionPane.showMessageDialog(window,
                                          "Es läuft gerade eine Aufzeichnung.");
      return true;
    }
    // prüfe ob nicht gerade eine ausführung der aufzeichnung läuft
    if (myIsApplyRunning) {
      JOptionPane.showMessageDialog(window,
                                   "Eine Aufzeichnung wird gerade ausgeführt.");
      return true;
    }
    return false;
  }

}
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben