2009-02-05 20 views
13

Ogni volta che faccio clic su un JSlider, viene posizionato un dito maggiore nella direzione del clic anziché saltare al punto in cui effettivamente clicco. (Se il cursore si trova al punto 47 e faccio clic su 5, salterà a 37 anziché a 5). C'è un modo per cambiarlo mentre usi JSliders o devo usare un'altra infrastruttura?JSlider question: Position after leftclick

risposta

16

Per quanto bizzarro possa sembrare, è in realtà il Look and Feel che controlla questo comportamento. Dai un'occhiata a BasicSliderUI, il metodo che devi sostituire è scrollDueToClickInTrack(int).

Per impostare il valore di JSlider sul valore più vicino al punto in cui l'utente ha fatto clic sulla traccia, è necessario eseguire una traduzione di fantasia tra le coordinate del mouse da getMousePosition() a un valore di traccia valido, tenendo in considerazione tenere conto della posizione dello Component, dell'orientamento, della dimensione e della distanza tra le zecche ecc.. Per fortuna, BasicSliderUI ci dà due funzioni a portata di mano per farlo: valueForXPosition(int xPos) e valueForYPosition(int yPos):

JSlider slider = new JSlider(JSlider.HORIZONTAL); 
slider.setUI(new MetalSliderUI() { 
    protected void scrollDueToClickInTrack(int direction) { 
     // this is the default behaviour, let's comment that out 
     //scrollByBlock(direction); 

     int value = slider.getValue(); 

     if (slider.getOrientation() == JSlider.HORIZONTAL) { 
      value = this.valueForXPosition(slider.getMousePosition().x); 
     } else if (slider.getOrientation() == JSlider.VERTICAL) { 
      value = this.valueForYPosition(slider.getMousePosition().y); 
     } 
     slider.setValue(value); 
    } 
}); 
+0

Questo è un po 'strano, bella cattura. Cercando di capire come viene creato l'input per scrollDue .. (int). Per la direzione da determinare ci deve essere qualche controllo in cui faccio clic su sliderposition rispetto. Perché ciò sia determinato, un metodo non dovrebbe sapere esattamente dove sul cursore faccio clic? –

+0

non proprio, la direzione è facile: per una traccia orizzontale è sufficiente sapere che la coordinata x del clic del mouse è minore o maggiore della coordinata x della maniglia del cursore. – ninesided

+0

Sì, ma per sapere se è inferiore o superiore alla coordinata X non hai bisogno di sapere dove sul dispositivo di scorrimento fai clic per effettuare il confronto? Se la maniglia del cursore è a 50, devi sapere dove clicchi per vedere se quella posizione è> o <50, no? –

0

Questo comportamento è derivato dal sistema operativo. Sei sicuro di voler ridefinirlo e confondere gli utenti? Io non la penso così ;)

4

Questa domanda è un po 'vecchia, ma mi sono imbattuto in questo problema da solo. Questa è la mia soluzione:

JSlider slider = new JSlider(/* your options here if desired */) { 
    { 
     MouseListener[] listeners = getMouseListeners(); 
     for (MouseListener l : listeners) 
      removeMouseListener(l); // remove UI-installed TrackListener 
     final BasicSliderUI ui = (BasicSliderUI) getUI(); 
     BasicSliderUI.TrackListener tl = ui.new TrackListener() { 
      // this is where we jump to absolute value of click 
      @Override public void mouseClicked(MouseEvent e) { 
       Point p = e.getPoint(); 
       int value = ui.valueForXPosition(p.x); 

       setValue(value); 
      } 
      // disable check that will invoke scrollDueToClickInTrack 
      @Override public boolean shouldScroll(int dir) { 
       return false; 
      } 
     }; 
     addMouseListener(tl); 
    } 
}; 
+0

questa soluzione non significa che non è più possibile utilizzare una rotella di scorrimento per spostare il cursore? – ninesided

+0

+1, ho apportato una leggera modifica per rimuovere e aggiungere anche MouseMotionListener. Questo dà un piccolo cambiamento estetico in quanto il mouse rimarrà centrato nel pollice del cursore mentre trascini il pollice invece di saltare verso il margine sinistro del pollice. – camickr