View Full Version : [Java] riscrivere listener standard
ho un problemino con un il mouselistener di default della Jslider, vorrei riscriverlo in modo da poter cambiare l'incremento che ha il cursore quando si clicca sulla slider in un punto qualsiasi (avete presente il saltino che fa) mentre volevo lasciare intatta la gestione del trascinamento del cursore. ho provato ad eliminarlo ma mi cancella ovviamente tutte e due le gestioni, nessuno sa dirmi come faccio a vedere il codice che esegue per la gestione del trascinamento così elimino il listener e ne faccio uno nuovo, spero di essere stato chiaro... :D
dimenticavo, io uso jbuilder quindi mi basterebbe sapere come aprire con jbuilder il codice della classe jslider in cui dovrebbe esserci quello che voglio
Io non sono un esperto di Java...ma conosci già l'intestazione della funzione che si occupa della gestione del mouse ?
Originally posted by "Franz83"
ho un problemino con un il mouselistener di default della Jslider, vorrei riscriverlo in modo da poter cambiare l'incremento che ha il cursore quando si clicca sulla slider in un punto qualsiasi (avete presente il saltino che fa) mentre volevo lasciare intatta la gestione del trascinamento del cursore. ho provato ad eliminarlo ma mi cancella ovviamente tutte e due le gestioni, nessuno sa dirmi come faccio a vedere il codice che esegue per la gestione del trascinamento così elimino il listener e ne faccio uno nuovo, spero di essere stato chiaro... :D
dimenticavo, io uso jbuilder quindi mi basterebbe sapere come aprire con jbuilder il codice della classe jslider in cui dovrebbe esserci quello che voglio
puoi farlo tranquillamente (i sorgenti dovrebbero essere pubblici) ma e' una porcheria, se distribuisci il tuo prodotto devi poi fare in modo che la classe che venga caricata sia la tua e non quella di default e puo' essere causa di problemi notevoli, senza contare i problemi di licenza (per sun NON hai facoltà di modificare i package standard).
Suggerimento: mai sentito parlare di ereditarietà? ;)
Originally posted by "kingv"
Suggerimento: mai sentito parlare di ereditarietà? ;)
Infatti era quello che gli volevo suggerire ;)
so cos'è l'ereditarietà ma non capisco cosa centri in questo caso, poi io non voglio modificare il package, ma solo riscrevere il mio listener in modo che contenga una parte del codice originale.
mettiamola così la classe JSlider ha 1 listener di default che gestisce sia il trascinamento che il salto, io voglio instanziare un oggetto JSlider, eliminare il suo listener standard, e crearne uno io che gestisca solo il trascinamento. Mi manca solo il codice che gestisce il trascinamento che vorrei prendere dalla classe padre JSlider, ma come faccio?
Originally posted by "cionci"
Io non sono un esperto di Java...ma conosci già l'intestazione della funzione che si occupa della gestione del mouse ?
il mouse (solo alcuni eventi) sono gestiti dal listener di default dell'oggetto, il listener, a quanto ne so io, puoi solo eliminarlo ma non modificarlo
Appunto ti fai una classe che estende JSlider e ridefinisci solo il listener...
Non ho idea di come sia fatto il listener di default della classe jslider ma non dovrebbe essere una tragedia farne uno alternativo.
Se ti serve solo il "dragger" probabilmente sei già in grado di determinare il punto relativo in cui il mouse viene premuto sulla barra. Per vedere se il mouse sta trascinando l'indicatore è sufficiente creare un Rectangle che abbia la larghezza dell'indicatore stesso (larghezza che si ottiene con il metodo getExtent() della classe JSlider) e verificare se il punto Point associato all'evento MouseDragged è compreso nell'area definita dall'indicatore.
Originally posted by "cn73"
Appunto ti fai una classe che estende JSlider e ridefinisci solo il listener...
e' ben quello che dicevo ... :o
Originally posted by "kingv"
e' ben quello che dicevo ... :o
era proprio quello il problema!!
grazie PGI proverò a fare come mi hai detto, io non avevo idea di cosa scrivere per fare il trascinamento! :)
ho appena controllato e il metodo getExtent() mi ritorna sempre 0 (perchè può muoversi ovunque) , fra l'altro ho visto che il metodo setExtent specifica fino a dove può scorrere il nodo e non quanto è largo
un'altra cosa, come si fa a modificare il valore di cui salta il nodo quando clicco sulla slider ma non sul nodo?
sono arrivato alla conclusione che non è per niente facile costruirsi il codice per gestire il trascinamento, almeno per il mio livello di preparazione, e soprattutto se lo si vuole fare riutilizzabile per altre slider, mi sono impiantato sul fatto che non riesco a calcolare di quante unità incrementare la slider per ogni pixel di spostamento nel caso in cui le due quantità nn siano multiple fra di loro (praticamente mai), ma mi chiedo come mai non ci siano metodi all'interno della slider per gestire graficamente il nodo! mi sembra una mancanza abbastanza grave
maxithron
19-06-2003, 20:14
stai usando questo tipo di struttura?
public interface MouseListener {
void mousePressed(MouseEvent event);
void mouseReleased(MouseEvent event);
void mouseClicked(MouseEvent event);
void mouseEntered(MouseEvent event);
void mouseExited(MouseEvent event);
}
Originally posted by "Franz83"
non riesco a calcolare di quante unità incrementare la slider per ogni pixel di spostamento nel caso in cui le due quantità nn siano multiple fra di loro
Non funziona proprio così, l'utente che trascini una barra di scorrimento si aspetta di poter fermare la barra su qualunque valore, se la sposti di quantità multiple di uno dovrà impazzire per riuscire a fermarla esattamente dove vuole! Quindi l'incremento e il decremento devono essere sempre unitari e devi gestire il trascinamento con un thread sincronizzato con lo spostamento della barra.
Mi sorge una curiosità, esattamente cosa c'è che non va nel trascinamento di default della classe JSlider?
Originally posted by "maxithron"
stai usando questo tipo di struttura?
public interface MouseListener {
void mousePressed(MouseEvent event);
void mouseReleased(MouseEvent event);
void mouseClicked(MouseEvent event);
void mouseEntered(MouseEvent event);
void mouseExited(MouseEvent event);
}
si sto usando quel listener
Originally posted by "PGI"
Non funziona proprio così, l'utente che trascini una barra di scorrimento si aspetta di poter fermare la barra su qualunque valore, se la sposti di quantità multiple di uno dovrà impazzire per riuscire a fermarla esattamente dove vuole! Quindi l'incremento e il decremento devono essere sempre unitari e devi gestire il trascinamento con un thread sincronizzato con lo spostamento della barra.
Mi sorge una curiosità, esattamente cosa c'è che non va nel trascinamento di default della classe JSlider?
mi spiace ma ti devo contraddire! ho provato proprio ieri perchè anche io credevo fosse così, cmq ci si può arrivare, se tu hai una slider di 600 pixel di lunghezza i cui valori vanno da 0 d 10000 come fai ad avere un incremento di 1 draggando, visto che il minino spostamento è di 1 pixel? sempre che sia questo quello che intendevi, comunque ho novità e forse con il vostro aiuto posso farcela, prima di tutto volevo dirvi che ho trovato gente che sostiene che effettivamente la JSlider ha un bug perchè il metodo che incrementa di un blocco la barra (quando si clicca sulla barra ma non sul nodo) calcola l'incremento come valore della barra/10, quando questa ha dimensione minore di 10 sembra che non funzioni, poi ho visto che nella classe in oggetto e scritto proprio "/10" quindi il salto di un decimo non è modificabile, a meno di modificare la classe del jdk in oggetto, per il fatto del dragging se riesco a modificare il salto non mi serve implementare il dragging.
Ho trovato il codice che gestisce il salto e molte altre proprietà della slider in javax.swing.plaf.basicBasicSliderUI, però non so cosa farne! mi spiego non sono ancora molto ferrato e quindi non so cosa devo fare per modificare il metodo scrollByBlock(), vorrei fare in modo di avere una classe identica a questa, così modifico il metodo, poi però dovrei dire alla mia slider di usare la mia classe modificata e non quella vecchia, ma come si fa?
se avete bisogno di altre informazioni ditemelo che ve le do
grazie a tutti
Premesso che ancora non ho capito cosa vuoi fare, se vuoi modificare il metodo scrollByBlock() del l&f manager per la slider devi:
a) fare una classe che estenda BasicSliderUI con un costruttore così:
MyUI(JSlider s) {
super(s)
}
poi fai l'override del metodo scrollByBlock(), nell'esempio si sposta di metà del valore della barra (credo :D )
public void scrollByBlock(int direction) {
synchronized(slider) {
int oldValue = slider.getValue();
int blockIncrement =
(slider.getMaximum() - slider.getMinimum()) / 2; //esempio
if (blockIncrement <= 0 &&
slider.getMaximum() > slider.getMinimum()) {
blockIncrement = 1;
}
int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
slider.setValue(oldValue + delta);
}
}
poi setti il l&f della slider:
JSlider s=new JSlider();
s.setUI(new MyUI);
A questo punto dovresti avere una barra estremamente "spoglia" per cui dovresti cercare di importare anche i metodi che "dipingono" gli oggetti secondo il lookandfeel corrente oppure settare il lookandfeel su "basiclookand feel".
Ciao.
Dimenticavo, per la faccenda del pixel probabilmente parliamo di due cose diverse, perchè che una barra di scorrimento non possa essere spostata di pixel ma solo di unità di valore, tramite accesso esterno, è certo. Se vuoi spostare l'indicatore di 1 pixel devi avere accesso diretto all'oggetto Graphics del componente cosa che è possible solo "riscrivendo" l'immagine della barra di scorrimento.
Ari-ciao.
Se ti interessa solo spostare la barra al click del mouse di un valore a piacere potrebbe essere più semplice aggiungere un mouse listener che al click determini se il punto è a destra o a sinistra dell'indicatore e sposti la barra di un tot in quella direzione.
public void mouseClicked(MouseEvent m) {
Point p=m.getPoint();
Rectangle r=target.getBounds();
p.y+=r.y;
if(target.getBounds().contains(p)) {
double l=r.getWidth();
double pc=target.getValue()*100/target.getMaximum();
double lA=target.getWidth()*pc/100;
Rectangle rA=new Rectangle(r.x,r.y,(int)lA,(int)r.getHeight());
if(rA.contains(p)) {
System.out.println("LEFT");
target.setValue(target.getValue()-10);
} else {
System.out.println("RIGHT");
target.setValue(target.getValue()+10);
}
}
}
dove target è il JSlider associato all'evento mousePressed.
hehe, a questo ci avevo già pensato e l'avevo anche già fatto ma sai cosa succedeva? che avevo 2 listener che mi intercettevano il click, quello di default che me la spostava di 1/10 più quello che hai scritto tu che me la spostava di altri 10! (se elimino quello standandard perdo il drag) è vero anche che si potrebbe farne uno uguale al tuo soltanto con i segni invertiti degli spostamenti (+10 al posto di -10 e viceversa) però non mi sembra un bel lavoro, inoltre graficamente vedi il nodo prima andare a +20 e poi tornare indietro a +10 e non è bello.
per l'altra cosa invece ho capito cosa intendi. per il fatto che ho la barra spoglia, se estendo la classe BasicSliderUI non dovrei avere tutti i sui metodi e proprietà? il fatto che è spoglia dipende solo da cosa contiene la mia classe MyUI? e se ricopio la classe intera BasicSliderUI nella mia MyUI modificando solo quel metodo non avrei una slider perfettamente uguale a una di default tranne che per quel metodo?
grazie per la pazienza e per l'aiuto
PS
quello che voglio ottenere è semplicemente una slider che si incrementa di un blocco che voglio io, il problema ha due soluzioni:
1- elimino il listener standard, gestisco l'incremento nel mio listener, fin qui tutto ok, però poi devo riscrivere anche il dragger e altre proprietà che per me risulta abb complicato
2- modifico in qualche modo la gestione standard dell'incremento che è come mi hai spiegato tu :D
Se vuoi passare per il lookandfeel devi decidere prima di visualizzare l'interfaccia che lookandfeel usare oppure gestire con un condizionale il lookandfeel corrente.
Diciamo che la tua applicazione usa solo il lookandfeel "Metal", che, essendo lo stile Java dovrebbe essere multipiattaforma per definizione e quindi il più consigliabile.
All'inizio del programma (nel costruttore della classe principale ad esempio) selezioni il lookandfeel "Metal"
try {
UIManager.setLookAndFeel(new MetalLookAndFeel());
} catch(UnsupportedLookAndFeelException e) {...}
Così sei sicuro che tutti i componenti usano il lookandfeel Metal.
Poi estendi il lookandfeel Metal per lo slider
class MyUI extends MetalSliderUI {
MyUI() {
}
public void scrollDueToClickInTrack(int direction) {
synchronized(slider) {
//esempio
if(direction==POSITIVE_SCROLL) {
slider.setValue(slider.getValue()+5);
} else {
slider.setValue(slider.getValue()-5);
}
//***********************************************************
/* questo qua sotto è quello di default
int oldValue = slider.getValue();
int blockIncrement =
(slider.getMaximum() - slider.getMinimum()) / 2;
if (blockIncrement <= 0 &&
slider.getMaximum() > slider.getMinimum()) {
blockIncrement = 1;
}
int delta = blockIncrement * ((direction > 0) ? POSITIVE_SCROLL : NEGATIVE_SCROLL);
slider.setValue(oldValue + delta);*/
}
}
}
Infine applichi lo stile al tuo slider
JSlider s=new JSlider(...);
s.setUI(new MyUI());
Ciao.
provo e ti faccio sapere
grazie ancora
COME "PROVO"??? :D
Deve funzionare! Se non va mi mangio la tastiera! :D
Ciao.
grande!! funziona alla perfezione!!
un'ultima cosa, come posso fare se voglio rimettere il L&F standard, ovverò come si chiama quello standard? ce ne sono altri oltre a questi 2?
Lo standard dovrebbe essere proprio Metal, poi c'è "Motif", "Windows" e "Mac" dove Windows e Mac funzionano solo sui rispettivi pc.
com.sun.java.swing.plaf.mac.MacLookAndFeel
javax.swing.plaf.metal.MetalLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Il lookandfeel si cambia usando il metodo UIManager.setLookAndFeel(...), se lo associ ad un evento dovresti vedere il lookandfeel cambiare "dinamicamente". Fai una ricerca su google per "SwingSet2", è una demo di Sun che mostra i diversi "look".
Ciao.
grazie di tutto!!!
adesso mi informo, provo era nel senso di "vedere se riesco a copiare mezza pagine di codice e farla funzionare..." ;) :D :D
ma con le tue indicazioni è impossibile sbagliare!! :D :D
altro piccolo problemino, se estendo la classe WindowSliderUI mi dice che manca un costruttore, non gli va più bene quello vuoto MyUI() ?
Il costruttore di WindowSliderUI richiede un "JSlider" come parametro.
class WinUI {
public WinUI(JSlider l) {
super(l);
}
}
Ciao.
sono proprio cotto, è ovvio che non va se uso il costruttore della classe padre e non MyUI()... :o
ok per oggi basta
ti stresserò ancora un'altro giorno.. :D :D :) ;)
nuovo giorno nuovo problemino, come posso fare per avere uno spinner con 8 pulsanti di incremento invece che i soliti 2? io ho provato facendo un text field con dei pulsanti normali ma mi sono impiantato perchè non riesco a fare i triangolini dentro i pulsanti! :cry:
Scusa, ma che funzione avrebbero gli altri 6 pulsanti ?
voglio che ogni coppia incrementi-decrementi le migliaia, le centinaia, le decine e le unità
Ma non puoi mettere 4 spinner uno accanto all'altro ?
come intendi? voglio anche poter modificare il numero normalmente, scrivendolo da tastiera
Un'idea:
fai un pannello con il layout settato a "BorderLayout" e aggiungi al centro uno spinner.
Costruisci un'altro pannello con "GridLayout", 1 riga e tre colonne e lo aggiungi al primo pannello, a destra.
Poi costruisci 3 JSpinner e da questi tre rimuovi il campo di testo con il metodo
JSpinner.remove(int componentIndex)
dove componentIndex è 2 (0 e 1 sono i bottoni)
aggiungi i tre spinner al pannello a griglia.
A questo punto dovresti avere uno spinner completo e altri 3 set di bottoni uguali a quelli dello spinner.
JPanel spinnerPanel=new JPanel();
JPanel spinnerButton=new JPanel();
spinnerButton.setLayout(new GridLayout(1,3));
spinnerPanel.setLayout(new BorderLayout());
spinnerPanel.add("East",spinnerButton);
spinnerPanel.add("Center",spin1);
JSpinner spin2=new JSpinner();
spin2.remove(2);
spinnerButton.add(spin2);
JSpinner spin3=new JSpinner();
spin3.remove(2);
spinnerButton.add(spin3);
JSpinner spin4=new JSpinner();
spin4.remove(2);
spinnerButton.add(spin4);
sono riuscito a farlo solo che non riesco a configurarlo bene graficamente, mi sembra più ordinata la versione con i bottoni, oppure modificare la classe JSpinner in modo da fargli avere in partenza già tutti i bottoni, sai dirmi come posso fare ad aggiungere il triangolino ad un bottone?
I bottoni degli spinner dovrebbero essere dei "BasicArrowButton" (javax.swing.plaf.basic.BasicArrowButton), estensioni della classe JButton e hanno di default la "freccina".
il costruttore è
BasicArrowButton(int p0) dove p0 può essere o SwingConstants.NORTH o SwingConstants.SOUTH (forse anche EAST, WEST e via di seguito).
In generale per disegnare un triangolo (o altro) direttamente su un bottone devi sovrascrivere il metodo paint(Graphics g) della classe JButton e poi passare all'oggetto Graphics quello che vuoi disegnare ricordando di impostare le dimensioni del bottone in modo che il disegno sia sempre visibile.
Ciao.
grazie mille adesso faccio un po' di esperimenti!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.