Behandlung von inputs nun in eigener EventQueue

Tastatur- und Mauseingaben werden nun nicht mehr direkt verarbeitet, sondern in eine interne EventQueue geschoben, die nach dem Aufruf von `draw()` abgearbeitet wird. Die `InputEvent`s werden momentan direkt an die üblichen Listener Methoden weitergegeben. Ggf. ist in Zukunft hier auch ein vereinfachtes Eventsystem (siehe Processing) sinnvoll.
Ist die ZM pausiert, werden Events ohne verzögerung direkt ausgelöst.
This commit is contained in:
ngb
2022-06-30 21:29:01 +02:00
parent 3e94f42ed3
commit c989e69f9f

View File

@@ -12,6 +12,8 @@ import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/** /**
* Hauptklasse der Zeichenmaschine. * Hauptklasse der Zeichenmaschine.
@@ -20,17 +22,45 @@ import java.util.LinkedList;
* Die Klasse übernimmt die Initialisierung eines Programmfensters und der * Die Klasse übernimmt die Initialisierung eines Programmfensters und der
* nötigen Komponenten. * nötigen Komponenten.
*/ */
public class Zeichenmaschine extends Constants implements MouseInputListener, KeyListener { public class Zeichenmaschine extends Constants {
/** /**
* Gibt an, ob die Zeichenmaschine aus BlueJ heraus gestartet wurde. * Gibt an, ob die Zeichenmaschine aus BlueJ heraus gestartet wurde.
*/ */
public static boolean IN_BLUEJ; public static final boolean IN_BLUEJ;
static { static {
IN_BLUEJ = System.getProperty("java.class.path").contains("bluej"); IN_BLUEJ = System.getProperty("java.class.path").contains("bluej");
} }
public static final boolean MACOS;
public static final boolean WINDOWS;
public static final boolean LINUX;
static {
final String name = System.getProperty("os.name");
if( name.contains("Mac") ) {
MACOS = true;
WINDOWS = false;
LINUX = false;
} else if( name.contains("Windows") ) {
MACOS = false;
WINDOWS = true;
LINUX = false;
} else if( name.equals("Linux") ) { // true for the ibm vm
MACOS = false;
WINDOWS = false;
LINUX = true;
} else {
MACOS = false;
WINDOWS = false;
LINUX = false;
}
}
/* /*
* Objektvariablen, die von Unterklassen benutzt werden können. * Objektvariablen, die von Unterklassen benutzt werden können.
*/ */
@@ -112,6 +142,9 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Hauptthread der Zeichenmaschine. // Hauptthread der Zeichenmaschine.
private Thread mainThread; private Thread mainThread;
// Queue für abgefangene InputEvents
private BlockingQueue<InputEvent> eventQueue = new LinkedBlockingQueue<>();
// Gibt an, ob nach Ende des Hauptthreads das Programm beendet werden soll, // Gibt an, ob nach Ende des Hauptthreads das Programm beendet werden soll,
// oder das Zeichenfenster weiter geöffnet bleibt. // oder das Zeichenfenster weiter geöffnet bleibt.
private boolean quitAfterTeardown = false; private boolean quitAfterTeardown = false;
@@ -250,16 +283,22 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
// Das Icon des Fensters ändern // Das Icon des Fensters ändern
try { try {
ImageIcon icon = new ImageIcon(ImageIO.read(new File("res/icon_64.png"))); ImageIcon icon = new ImageIcon(ImageIO.read(new File("res/icon_64.png")));
frame.setIconImage(icon.getImage());
// Dock Icon in macOS setzen if( MACOS ) {
Taskbar taskbar = Taskbar.getTaskbar(); // Dock Icon in macOS setzen
taskbar.setIconImage(icon.getImage()); Taskbar taskbar = Taskbar.getTaskbar();
taskbar.setIconImage(icon.getImage());
} else {
// Kleines Icon des Frames setzen
frame.setIconImage(icon.getImage());
}
} catch( IOException e ) { } catch( IOException e ) {
} }
// Erstellen der Leinwand // Erstellen der Leinwand
canvas = new Zeichenleinwand(width, height); canvas = new Zeichenleinwand(width, height);
frame.add(canvas); frame.add(canvas);
@@ -279,9 +318,67 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
settings(); settings();
// Listener hinzufügen, um auf Maus- und Tastatureingaben zu hören. // Listener hinzufügen, um auf Maus- und Tastatureingaben zu hören.
canvas.addMouseListener(this); //canvas.addMouseListener(this);
canvas.addMouseMotionListener(this); //canvas.addMouseMotionListener(this);
canvas.addKeyListener(this); //canvas.addKeyListener(this);
canvas.addMouseListener(new MouseInputListener() {
@Override
public void mouseClicked( MouseEvent e ) {
enqueueEvent(e);
}
@Override
public void mousePressed( MouseEvent e ) {
enqueueEvent(e);
}
@Override
public void mouseReleased( MouseEvent e ) {
enqueueEvent(e);
}
@Override
public void mouseEntered( MouseEvent e ) {
}
@Override
public void mouseExited( MouseEvent e ) {
}
@Override
public void mouseDragged( MouseEvent e ) {
enqueueEvent(e);
}
@Override
public void mouseMoved( MouseEvent e ) {
enqueueEvent(e);
}
});
/*
canvas.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved( MouseWheelEvent e ) {
enqueueEvent(e);
}
});
*/
canvas.addKeyListener(new KeyListener() {
@Override
public void keyTyped( KeyEvent e ) {
enqueueEvent(e);
}
@Override
public void keyPressed( KeyEvent e ) {
enqueueEvent(e);
}
@Override
public void keyReleased( KeyEvent e ) {
enqueueEvent(e);
}
});
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override @Override
public void windowClosing( WindowEvent e ) { public void windowClosing( WindowEvent e ) {
@@ -527,12 +624,13 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
* @see #setSize(int, int) * @see #setSize(int, int)
* @see #setFullscreen(boolean) * @see #setFullscreen(boolean)
*/ */
private void changeSize( int width, int height ) { private void changeSize( int newWidth, int newHeight ) {
width = Math.min(Math.max(newWidth, 100), screenWidth);
height = Math.min(Math.max(newHeight, 100), screenHeight);
if( canvas != null ) { if( canvas != null ) {
canvas.setSize(width, height); canvas.setSize(width, height);
} }
this.width = Math.min(Math.max(width, 100), screenWidth);
this.height = Math.min(Math.max(height, 100), screenHeight);
} }
/** /**
@@ -995,9 +1093,95 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
/* /*
* Mouse handling * Mouse handling
*/ */
@Override private void enqueueEvent( InputEvent evt ) {
public final void mouseClicked( MouseEvent e ) { eventQueue.add(evt);
mouseEvent = e;
if (isPaused()) {
dispatchEvents();
}
}
private void dispatchEvents() {
synchronized( eventQueue ) {
while( !eventQueue.isEmpty() ) {
InputEvent evt = eventQueue.poll();
// ???
switch( evt.getID() ) {
case KeyEvent.KEY_TYPED:
case KeyEvent.KEY_PRESSED:
case KeyEvent.KEY_RELEASED:
handleKeyEvent((KeyEvent) evt);
break;
case MouseEvent.MOUSE_CLICKED:
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
case MouseEvent.MOUSE_WHEEL:
handleMouseEvent((MouseEvent) evt);
break;
}
}
}
}
private void handleKeyEvent( KeyEvent evt ) {
keyEvent = evt;
key = evt.getKeyChar();
keyCode = evt.getKeyCode();
switch( evt.getID() ) {
case KeyEvent.KEY_TYPED:
keyTyped(evt);
break;
case KeyEvent.KEY_PRESSED:
keyPressed = true;
keyPressed(evt);
break;
case KeyEvent.KEY_RELEASED:
keyPressed = false;
keyReleased(evt);
break;
}
}
private void handleMouseEvent( MouseEvent evt ) {
if( mouseEvent != null && evt.getComponent() == canvas ) {
pmouseX = mouseX;
pmouseY = mouseY;
mouseX = evt.getX();
mouseY = evt.getY();
}
mouseEvent = evt;
switch( evt.getID() ){
case MouseEvent.MOUSE_CLICKED:
mouseClicked(evt);
break;
case MouseEvent.MOUSE_PRESSED:
mousePressed = true;
mouseButton = evt.getButton();
mousePressed(evt);
break;
case MouseEvent.MOUSE_RELEASED:
mousePressed = false;
mouseButton = NOBUTTON;
mousePressed(evt);
break;
case MouseEvent.MOUSE_DRAGGED:
mouseDragged(evt);
break;
case MouseEvent.MOUSE_MOVED:
mouseMoved(evt);
break;
}
}
public void mouseClicked( MouseEvent e ) {
mouseClicked(); mouseClicked();
} }
@@ -1005,11 +1189,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void mousePressed( MouseEvent e ) {
public final void mousePressed( MouseEvent e ) {
mouseEvent = e;
mousePressed = true;
mouseButton = e.getButton();
mousePressed(); mousePressed();
} }
@@ -1017,11 +1197,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void mouseReleased( MouseEvent e ) {
public final void mouseReleased( MouseEvent e ) {
mouseEvent = e;
mousePressed = false;
mouseButton = NOBUTTON;
mouseReleased(); mouseReleased();
} }
@@ -1029,19 +1205,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void mouseDragged( MouseEvent e ) {
public final void mouseEntered( MouseEvent e ) {
// Intentionally left blank
}
@Override
public final void mouseExited( MouseEvent e ) {
// Intentionally left blank
}
@Override
public final void mouseDragged( MouseEvent e ) {
mouseEvent = e;
mouseDragged(); mouseDragged();
} }
@@ -1049,9 +1213,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void mouseMoved( MouseEvent e ) {
public final void mouseMoved( MouseEvent e ) {
mouseEvent = e;
mouseMoved(); mouseMoved();
} }
@@ -1083,9 +1245,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
/* /*
* Keyboard handling * Keyboard handling
*/ */
@Override public void keyTyped( KeyEvent e ) {
public final void keyTyped( KeyEvent e ) {
saveKeys(e);
keyTyped(); keyTyped();
} }
@@ -1093,10 +1253,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void keyPressed( KeyEvent e ) {
public final void keyPressed( KeyEvent e ) {
saveKeys(e);
keyPressed = true;
keyPressed(); keyPressed();
} }
@@ -1104,10 +1261,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
@Override public void keyReleased( KeyEvent e ) {
public final void keyReleased( KeyEvent e ) {
saveKeys(e);
keyPressed = false;
keyReleased(); keyReleased();
} }
@@ -1115,12 +1269,6 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// Intentionally left blank // Intentionally left blank
} }
private final void saveKeys( KeyEvent event ) {
keyEvent = event;
key = event.getKeyChar();
keyCode = event.getKeyCode();
}
// Window changes // Window changes
public void fullscreenChanged() { public void fullscreenChanged() {
// Intentionally left blank // Intentionally left blank
@@ -1161,7 +1309,7 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
delta = (System.nanoTime() - beforeTime) / 1000000000.0; delta = (System.nanoTime() - beforeTime) / 1000000000.0;
beforeTime = System.nanoTime(); beforeTime = System.nanoTime();
saveMousePosition(mouseEvent); //saveMousePosition(mouseEvent);
if( state != Options.AppState.PAUSED ) { if( state != Options.AppState.PAUSED ) {
handleUpdate(delta); handleUpdate(delta);
@@ -1172,6 +1320,8 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
// canvas.invalidate(); // canvas.invalidate();
// frame.repaint(); // frame.repaint();
} }
dispatchEvents();
} }
// delta time in ns // delta time in ns
@@ -1190,7 +1340,6 @@ public class Zeichenmaschine extends Constants implements MouseInputListener, Ke
overslept = (System.nanoTime() - afterTime) - sleep; overslept = (System.nanoTime() - afterTime) - sleep;
} else { } else {
overslept = 0L; overslept = 0L;
} }
_tick += 1; _tick += 1;