View Full Version : [Java]Coda eventi AWT, listener personalizzati e effetti immagini
ciao!!
come al solito torno a rompere a voi che ne sapete di Java :D
prima di tutti ringrazio PGI-Bis per avermi aiutato nell'altro thread :ave:
ma ora passiamo al nuovo problema (trattato più o meno nell'altro 3d) la coda eventi awt.
premetto che io devo realizzare un programma che gestisce un multitouch, quindi mi servono eventi personalizzati visto che posso gestine un numero n di "dita".
detto ciò il mio dubbio è su come mettere un evento nella queue di awt e come dire a un componente di restare in ascolto per quell'evento!
qualcuno mi può dire come si fa?
ho intravisto un oggetto eventqueue nelle api, ma non mi è chiaro come funzioni :mbe:
detto questo passiamo a una domandina "secondaria" in java posso creare effetti tipo il blur e lo sfocamento di immagini in modo semplice? sarebbe bello implementarli nel menu :D
grazie a tuttttti!
PS. PGI-Bis fai parte di qualche team? che il tuo avatar l'ho già visto in siti che ho girato per recuperare informazioni :)
uppp! please help me!:mc: :mc:
Nel mio logo c'è Duke, la mascotte di Java. Ah, infedele, non l'hai riconosciuto!
Infilare eventi nella coda degli eventi è una questione di poche righe:
EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
systemQueue.postEvent(un qualsiasi evento AWT);
Se crei una classe che estende ad esempio MouseEvent (per un multitouch potrebbe essere una classe identica a MouseEvent salvo il fatto che indica anche quale "mouse" abbia prodotto l'evento, esistendone più d'uno), crei un'istanza e la "posti" nella coda degli eventi AWT quell'evento viene propagato quasi come fosse un evento del mouse di sistema.
Questo ti permette di catturarlo con un normalissimo MouseListener.
Esempio:
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Main().start();
}
});
}
private volatile boolean execute = true;
private final Frame window = new Frame("Custom Mouse Event Generation");
private final int MOUSE_1 = 0;
private final int MOUSE_2 = 1;
private void start() {
window.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(e instanceof CustomMouseEvent) {
System.out.println("Evento del mouse numero " + ((CustomMouseEvent)e).getMouseId());
}
}
public void mouseReleased(MouseEvent e) {
if(e instanceof CustomMouseEvent) {
System.out.println("Evento del mouse numero " + ((CustomMouseEvent)e).getMouseId());
}
}
});
window.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
window.dispose();
stopMouseEventProducer();
}
public void windowOpened(WindowEvent e) {
startMouseEventProducer();
}
});
window.setSize(400, 400);
window.setVisible(true);
}
private void startMouseEventProducer() {
Runnable task = new Runnable() {
public void run() {
while(execute) {
Component source = window;
CustomMouseEvent mouse1Event = new CustomMouseEvent(
source,
MouseEvent.MOUSE_PRESSED,
MouseEvent.BUTTON1_DOWN_MASK,
100,
100,
1,
MouseEvent.BUTTON1,
MOUSE_1);
CustomMouseEvent mouse2Event = new CustomMouseEvent(
source,
MouseEvent.MOUSE_RELEASED,
MouseEvent.BUTTON1_DOWN_MASK,
100,
100,
0,
MouseEvent.BUTTON1,
MOUSE_2);
EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
systemQueue.postEvent(mouse1Event);
systemQueue.postEvent(mouse2Event);
try {
Thread.sleep(2000);
} catch(InterruptedException ex) {
execute = false;
return;
}
}
}
};
new Thread(task).start();
}
private void stopMouseEventProducer() {
execute = false;
}
}
class CustomMouseEvent extends MouseEvent {
private final int screenX, screenY, mouseId;
public CustomMouseEvent(Component source, int id, int modifiers, int x, int y, int clickCount, int button, int mouseId) {
super(source, id, System.currentTimeMillis(), modifiers, x, y, clickCount, false, button);
screenX = x;
screenY = y;
this.mouseId = mouseId;
}
public int getMouseId() {
return mouseId;
}
private Point getSourceLocationOnScreen() {
return getComponent().getLocationOnScreen();
}
public Point getLocationOnScreen() {
return new Point(screenX, screenY);
}
public Point getPoint() {
Point componentLocationOnScreen = getSourceLocationOnScreen();
return new Point(componentLocationOnScreen.x + screenX, componentLocationOnScreen.y + screenY);
}
public int getX() {
return getSourceLocationOnScreen().x + screenX;
}
public int getY() {
return getSourceLocationOnScreen().y + screenY;
}
public int getXOnScreen() {
return screenX;
}
}
Questa roba qua stampa due scritte attraverso un MouseListener su Window. L'evento che genera la stampa è un MouseEvent personalizzato.
C'è un piccolo problema con gli eventi semantici (tipo ActionEvent). Questi eventi sono generati da eventi di basso livello (MouseEvent è un evento di basso livello). Il problema è che non sembra che eventi di basso livello personalizzati siano in grado di generare eventi semantici. Bisognerebbe spulciare un po' i sorgenti di OpenJDK per capire come mai.
:cry:
grazie mille per il codice, me lo guarderò con calma ;)
il mio awtevent personalizzato deve avere particolari caratteristiche?
questo è il codice che ho provato a fare alla veloce e fa una cosa strana:
EventQueue queue=Toolkit.getDefaultToolkit().getSystemEventQueue();
MyAWTEvent event=new MyAWTEvent(new String("sourceasd"), 10);
queue.postEvent(event);
while(true){
AWTEvent e;
try {
e = queue.getNextEvent();
if(e instanceof MyAWTEvent){
String source=(String)(e.getSource());
System.out.println(source);
break;
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
se faccio così mi inserisce il mio evento e mi stampa suourceasd come ci si apetterebbe, ma se commento il while mi da un errore: unable to dispatch: (il mio awtevent)
PS myAWTEvent è solo un'implementazione di AWTEvent che non gli aggiunge nulla:
public class MyAWTEvent extends AWTEvent {
public MyAWTEvent(Object arg0, int arg1) {
super(arg0, arg1);
}
}
L'errore ha una traccia o da solo quel messaggio? Comunque fai una cosa strana, in pratica immetti l'evento nella coda e poi inizi a consumarla parallelamente all'Event Dispatcher Thread.
Per il blur se hai sotto mano un BufferedImage puoi applicare una convoluzione (ConvolveOp) e poi la applichi come un filtro (BufferedImage blurred = convolution.filter(source, null));
L'errore ha una traccia o da solo quel messaggio? Comunque fai una cosa strana, in pratica immetti l'evento nella coda e poi inizi a consumarla parallelamente all'Event Dispatcher Thread.
era solo per vedere se c'era il mio evento dentro, ma se faccio solo il post non funziona...
ecco cosa dice la console:
unable to dispatch event: MyAWTEvent[] on sourceasd
è system.err.....
grazie per il blur :D
tu hai fatto un esempio con mouse move, ma se lo volessi fare con actionevent e lo ascolta un awteventlistener?:confused:
ActionEvent è uno degli eventi semantici di cui parlavo. In pratica un pulsante rileva un MouseReleased su sè stesso e per tutta risposta spara un ActionEvent.
Il fatto è che se spariamo un MouseReleased nella coda avente come bersaglio il pulsante lo stesso non genera un ActionEvent. E non dovrebbe fare così :mad:
O l'evento che genera un ActionEvent non è un MouseReleased (non ho provato con MouseClicked o con una coppia MousePressed-MouseReleased entro un certo intervallo di tempo) o deve avere una sorgente particolare. Sono quelle cose che andrebbero verificate nei sorgenti di Java perchè non sono comportamenti documentati.
ActionEvent è uno degli eventi semantici di cui parlavo. In pratica un pulsante rileva un MouseReleased su sè stesso e per tutta risposta spara un ActiveEvent.
Il fatto è che se spariamo un MouseReleased nella coda avente come bersaglio il pulsante lo stesso non genera un ActionEvent. E non dovrebbe fare così :mad:
O l'evento che genera un ActionEvent non è un MouseReleased (non ho provato con MouseClicked o con una coppia MousePressed-MouseReleased entro un certo intervallo di tempo) o deve avere una sorgente particolare. Sono quelle cose che andrebbero verificate nei sorgenti di Java perchè non sono comportamenti documentati.
allora credo di aver spulciato un pò il sorgente di eventqueue (http://www.docjar.com/html/api/java/awt/EventQueue.java.html) e il system.err unable to dispatch c'è solo nel metodo dispatchEvent:
protected void dispatchEvent(AWTEvent event) {
596 event.isPosted = true;
597 Object src = event.getSource();
598 if (event instanceof ActiveEvent) {
599 // This could become the sole method of dispatching in time.
600 setCurrentEventAndMostRecentTimeImpl(event);
601
602 ((ActiveEvent)event).dispatch();
603 } else if (src instanceof Component) {
604 ((Component)src).dispatchEvent(event);
605 event.dispatched();
606 } else if (src instanceof MenuComponent) {
607 ((MenuComponent)src).dispatchEvent(event);
608 } else if (src instanceof TrayIcon) {
609 ((TrayIcon)src).dispatchEvent(event);
610 } else if (src instanceof AWTAutoShutdown) {
611 if (noEvents()) {
612 dispatchThread.stopDispatching();
613 }
614 } else {
615 System.err.println("unable to dispatch event: " + event);
616 }
617 }
quindi sono giunto a un paio di conclusioni(come scritto nelle api)
O come source si ha un derivato di Component o MenuComponent o TrayIcon, e in questo caso l'evento viene postato in modo automatico, O l'evento è di una classe che estende ActiveEvent, e in questo caso viene chiamato il suo metodo dispatch che DEVE essere sovrascritto, cosa che io non facevo, ora cosa cavolo bisognerebbe scrivere dentro dispatch dell'action event?
perchè il mio obbiettivo sarebbe questo:
una volta trovato il mio evento del touch, incapsulare un mio oggetto che contiene informazioni sull'evento stesso e lanciarlo nella cod di awt, da un altra parte del programma verificare continuamente la coda e vedere se il source dell'evento primo della coda è del mio tipo, e in caso processarlo.
quindi vedendo tutti gli Event in java.awt.event il più adatto alla mia situazione sarebbe proprio activeevent, visto che non mi legherebbe a niente (mouse, key, componentevent, etc..) il problema è che action event deve sovrascrivere quel diavolo di metodo dispatch!! come posso fare?
PS tutte queste cose le hai lette in un libro o da internet? mi potresti postare dove? :rolleyes:
scusami mi sono confuso con active e action event:(
la soluzione per me è un activeevent (credo) ma non so come avere un listener per questo genere di eventi..
Le cose che so sono il frutto di un collage di libri letti ed esperimenti fatti nel corso degli anni. Non ho una fonte univoca da poterti dare.
Usi la coda degli eventi di sistema la usi se vuoi approfittare del meccanismo predefinito di propagazione degli eventi che consiste semplicemente nella notifica di un certo evento a tutti gli ascolatori di evento registrati e attivi per una certa classe di eventi.
L'ultimo post mi sembra suggerire il fatto che di questo meccanismo predefinito in verità non ti interessi granchè.
Allora perchè non creare una tua coda degli eventi? Sei molto più libero.
E' un semplice schema produttore-consumatore. Da una parte rilevi i touch, quando si verificano li immetti nella tua coda, dall'altra parte avrai uno o più consumatori che ricevono automaticamente la notifica di produzione dei touch e reagiscono di conseguenza. Senza eventi e listener AWT.
innanzitutto grazie delle risposte che mi hai dato, mi hanno aiutato a risolvere questo problema :D
alla fine sono riiuscito a usare un actionevent!!
tutti i miei dubbi si sono risolti con una prova, in pratica non avevo capito che quando crei un actionevent il parametro source(nelle api viene chiamato così) che sarebbe un component, è il conponent A cui viene segnalato l'evento, quindi mi è bastato avere un riferimento alla mia window, e dentro il suo codice abilitarla a ascoltare gli actionevent con .enableEvents(AWTEvent.ACTION_EVENT_MASK); e l'evento viene processato dal metodo processEvent(AWTEvent e) !!
sarebbe un'ottima soluzione da implementare una mia queue, solo che questo progetto lo devo consegnare prima della fine dell'anno scolastico, e quindi per ora cerco di farlo nel modo migliore senza usare troppo tempo, devo ancora fare le applicazioni :mc:
grazie di tutto! domani provo a usare il blur e scalare un'immagine, a proposito sai come si fa? :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.