Immer, wenn ich auf einen JSlider klicke, wird ein großerTick in Richtung des Klicks positioniert, anstatt zu dem Punkt zu springen, auf den ich tatsächlich klicke. (Wenn der Schieberegler bei Punkt 47 ist und ich auf 5 klicke, springt er auf 37 statt auf 5). Gibt es eine Möglichkeit, dies bei der Verwendung von JSliders zu ändern, oder muss ich eine andere Datenstruktur verwenden?JSlider Frage: Position nach Linksklick
Antwort
So bizarr dies scheinen mag, ist es tatsächlich das Look and Feel, das dieses Verhalten steuert. Werfen Sie einen Blick auf BasicSliderUI
, die Methode, die Sie überschreiben müssen, ist scrollDueToClickInTrack(int)
.
Um den Wert von JSlider
auf den nächsten Wert zu setzen, an dem der Benutzer auf den Track geklickt hat, müssen Sie eine spezielle Übersetzung zwischen den Mauskoordinaten von getMousePosition()
zu einem gültigen Track-Wert vornehmen Konto die Position der Component
, es ist die Ausrichtung, Größe und Abstand zwischen Ticks etc. Glücklicherweise BasicSliderUI
gibt uns zwei praktische Funktionen zur Verfügung: valueForXPosition(int xPos)
und 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);
}
});
Dieses Verhalten von OS abgeleitet wird. Sind Sie sicher, dass Sie es neu definieren und Benutzer verwirren möchten? Ich denke nicht. ;)
Diese Frage ist irgendwie alt, aber ich bin gerade über dieses Problem selbst gestolpert. Das ist meine Lösung:
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);
}
};
bedeutet diese Lösung nicht, dass Sie ein Schieberad nicht mehr verwenden können, um den Schieberegler zu verschieben? – ninesided
+1, habe ich eine kleine Änderung vorgenommen, um auch den MouseMotionListener zu entfernen und hinzuzufügen. Dies ergibt eine geringfügige kosmetische Änderung dahingehend, dass die Maus in dem Schieberegler-Daumen zentriert bleibt, während Sie den Daumen ziehen, anstatt zu der linken Kante des Daumens zu springen. – camickr
Das ist irgendwie bizarr, schöner Fang. Versuchen herauszufinden, wie die Eingabe für scrollDue .. (int) erstellt wird. Für die zu bestimmende Richtung muss überprüft werden, wo ich die Schiebeposition anklicke. Um das zu bestimmen, müsste eine Methode nicht genau wissen, wo auf dem Schieberegler ich klicke? –
nicht wirklich, Richtung ist einfach - für eine horizontale Spur muss es nur wissen, dass die x-Koordinate des Mausklicks kleiner oder größer als die x-Koordinate des Schiebereglers ist. – ninesided
Ja, aber um zu wissen, ob es kleiner oder größer als die X-Koordinate ist, müssen Sie nicht wissen, wo auf dem Schieberegler Sie klicken, um den Vergleich durchzuführen? Wenn der Schieberegler bei 50 ist, müssen Sie wissen, wo Sie klicken, um zu sehen, ob diese Position> oder <50 ist, nein? –