JSlider question, please help!

Hi,

I have a problem with JSlider. What I need a slider to have is both upper and lower tick marks. Lower is default,

but my method for having upper ticks is to make another JSlider, with a custom SliderUI class for it's UI. By doing

so, all I have is paintTicks defined, and set the slider to paint only the ticks. But the problem is the JSlider

leaves an empty space above the ticks where the bar and thumb would have been painted.

Is there any way to remove this space, and just have the ticks displayed?

TIA,

csmathie

[580 byte] By [csmathie] at [2007-9-26 1:19:45]
# 1
Do u want the thumb(knob) to be not painted ? when u say it is leaving empty space do u mean that it is drawing background color or blank square piece equivalent to the knob size unpainted ?Can u be more descriptive on what u are trying to acheive?-sri
chinimilli at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 2
well it is leaving a blank space equivalent to the size of the NON-PAINTED components, above the tickmarks. My goal is to remove this space, so the tickmarks are displayed with no space above them. Please help!Thanks!
csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 3
Wouldn't it be more straightforward to have only *one* slider, and assign it a custom UI class in which you define a paintTicks method to paint the ticks both above and below the slider?
artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 4

> Wouldn't it be more straightforward to have only *one*

> slider, and assign it a custom UI class in which you

> define a paintTicks method to paint the ticks both

> above and below the slider?

Well, I have that setup, but any help as to how one would "manually" paint the ticks above the bar so that they are aligned with the ticks below the bar? I don't *think* there is a way to get the alignment of the preset ticks below the bar....

csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 5
... and dukedollars for a solution :-)
csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 6

ok, i think i have a solution,

in your customUI, override the paint track method and paint your own track-- this would be an icon that you create w/ your track image on it

this is what i did for a custom scrollBar

protected void paintTrack(grapics g, JComponent j, rectangle trackBounds)

{

imageIcon icon=new imageIcon("blahblah.gif");

g.drawImage(icon.getImage(),0,0,null);

}

just make an image w/ your tic marks on it and then paint the track- you might have to play around w/ your image or your slider size to get it to fit properly

I hope this helped

yeti17 at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 7

Here's a better solution - this overrides the BasicSliderUI to draw the ticks wherever you wan them. NOTE this is for a horizontal scrollbar only - you'd have to do some extra stuff for a vertical one.import java.awt.Graphics;

import java.awt.Rectangle;

import javax.swing.*;

import javax.swing.plaf.basic.*;

public class eBasicSliderUI extends BasicSliderUI{

eBasicSliderUI(JSlider s) {

super(s);

}

protected void calculateGeometry() {

calculateFocusRect();

calculateContentRect();

contentRect.height+=tickRect.height;

calculateThumbSize();

calculateTrackBuffer();

calculateTrackRect();

int newTicksHeight = 20;

trackRect.y+=newTicksHeight;

calculateTickRect();

calculateLabelRect();

labelRect.y+=4;

calculateThumbLocation();

tickRect.y = tickRect.y -tickRect.height-trackRect.height;

tickRect.height+=(2*tickRect.height+trackRect.height);

}

protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {

int minorHeight = (tickBounds.height - trackRect.height) / 4 - 1;

g.drawLine( x, 0, x, minorHeight);

g.drawLine( x, (tickBounds.height+trackRect.height)/2-2,

x, (tickBounds.height+trackRect.height)/2 + minorHeight);

}

protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {

int majorHeight = (tickBounds.height - trackRect.height)/2 - 2;

g.drawLine( x, 0, x, majorHeight );

g.drawLine( x, (tickBounds.height+trackRect.height)/2-2,

x, (tickBounds.height+trackRect.height)/2 + majorHeight);

}

public void paint( Graphics g, JComponent c ){

recalculateIfInsetsChanged();

recalculateIfOrientationChanged();

Rectangle clip = g.getClipBounds();

if ( slider.getPaintTicks() && clip.intersects( tickRect ) ) {

paintTicks( g );

}

if ( slider.getPaintLabels() && clip.intersects( labelRect ) ) {

paintLabels( g );

}

if ( slider.hasFocus() && clip.intersects( focusRect ) ) {

paintFocus( g );

}

if ( slider.getPaintTrack() && clip.intersects( trackRect ) ) {

paintTrack( g );

}

if ( clip.intersects( thumbRect ) ) {

paintThumb( g );

}

}

}

You use this class by saying:JSlider slider = new JSlider(JSlider.HORIZONTAL,0,100,10);

slider.setPaintTicks(true);

slider.setPaintLabels(true);

slider.setMajorTickSpacing(10);

slider.setMinorTickSpacing(2);

slider.setUI(new eBasicSliderUI(slider));

artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 8
Thanks a lot! That *just* about works, but why is it that the thumb seems to "jump" instead of scrolling lazily (slowly) across the slider bar? Any way to change that?
csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 9

> Thanks a lot! That *just* about works, but why is it

> that the thumb seems to "jump" instead of scrolling

> lazily (slowly) across the slider bar? Any way to

> change that?

I don't understand how you see that behaviour - is that when you drag the thumb with your mouse, or are you changing the value from your code, or are you clicking on the track to the side of the thumb? If you're doing it from your code, can you post an example?

artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 10

If it's due to a click on the track, try adding this method to the eBasicSliderUI class (to override the super class method):protected void scrollDueToClickInTrack( int dir ) {

scrollByUnit( dir );

}

artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 11

Thanks a lot! And for the last of my DukeDollars, it seems like whenever I call:

contentRect.height+=tickRect.height + someNumber;

where someNumber is any large integer, it doesn't actually do anything to change the height of the JSlider, no matter what someNumber is. Isn't contentRect responsible for the overall size of the JSlider (width and height)? I ask because I need to move all components "down" in the contentRect so that I can add the labels to the top of the JSlider.

Thanks again,

csm.

csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 12

In you rmain program, after you create your slider, but before you set the UI, do:

mySlider.setPreferredSize(new Dimension(w,h));

where h is the height you want, including the additional space for the top labels

Then in the eBasicSliderUI class calculateGeometry() method, increase the value of:

int newTicksHeight = 40;

...or however much space you want above the track. newTicksHeight isn't actually the height of the new ticks themselves, it's the height of the rectangle above the track.

artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 13

thanks, that worked (I had this, just wrong layout). So my final question is: is there a way to dynamically change the position of the centerlabel on a JSlider?

For example, if the user selected the thumb at the center of the slider, that label that was at the center follows the JSlider thumb around (just above the thumb)? I've almost got it, it just doesn't like to be set with the slider.getValue and is just painting an empty JLabel. Any thoughts?

Thanks again.

csmathie at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 14

> I've almost got it, it just doesn't like

> to be set with the slider.getValue and is just

> painting an empty JLabel. Any thoughts?

not 100% sure what you're trying to do, but did you try a "slider.validate()" right after you do the "label.setText(slider.getValue())"?

Otherwise, can you post some compilable/working code?

artntek at 2007-6-29 0:52:40 > top of Java-index,Archived Forums,Swing...
# 15

ex.

0 50 100

==================

O

when the user moves the o (or thumb), the label that was previously at 50 should move with the thumb, and have it's label text value to be that of the slider.getValue(). Ie. the label that was first in the middle follows the thumb

position 2:

079100

====================

O

if the user moved thumb to 79.

thanks!

csmathie at 2007-6-30 21:35:03 > top of Java-index,Archived Forums,Swing...
# 16
ok spacing is off there, but I hope you get the point! :-)
csmathie at 2007-6-30 21:35:03 > top of Java-index,Archived Forums,Swing...
# 17
can you post your working (or "kinda working"!) code?
artntek at 2007-6-30 21:35:03 > top of Java-index,Archived Forums,Swing...
# 18
the code will be posted by 8:00AM Pacific time, just don't have my work at home (fortunately :-) )
csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 19

Here is the code...

<html>

<pre>

protected void paintHorizontalLabel(Graphics g, int value, Component label) {

if (value == 0 || value == 50 || value == 100) {

super.paintHorizontalLabel(g, value, label);

}

else {

//prints out nothing (label text is empty for some reason...)

System.out.println("*******************" + ((JLabel)label).getText());

JLabel newLabel = new JLabel("");

newLabel.setText(((JLabel)label).getText());

//doesn't work with newLabel OR the label param passed to this method

super.paintHorizontalLabel(g, slider.getValue(), newLabel);

}

}

</pre>

</html>

csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 20
This would be called when the thumb moves. So for example it should reset the center label to the value of slider.getValue() and set the position of this label to be above the thumb.
csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 21

Don't override paintHorizontalLabel(); instead, add these to your eBasicSliderUI class:private Rectangle unionRect = new Rectangle();

private final int labelDistAboveThumb = 25;

public void setThumbLocation(int x, int y) {

unionRect.setBounds( thumbRect );

thumbRect.setLocation( x, y );

int buffer=thumbRect.width;

SwingUtilities.computeUnion(thumbRect.x,

thumbRect.y - labelDistAboveThumb,

thumbRect.width,

thumbRect.height+labelDistAboveThumb,

unionRect );

slider.repaint( unionRect.x-buffer, unionRect.y,

unionRect.width+2*buffer, unionRect.height );

}

public void paintThumb(Graphics g) {

super.paintThumb(g);

paintUpperLabel(g);

}

protected void paintUpperLabel( Graphics g) {

int value = slider.getValue();

int lw = 20;//label width

int lh = 15;//label height

int labelCenter = xPositionForValue(value);

int labelLeft = labelCenter-lw/2;

g.translate(labelLeft, thumbRect.y-labelDistAboveThumb);

g.setColor(Color.green);//label color

g.fillRect(0, 0, lw,lh);

g.setColor(Color.black);//text color

g.drawString(""+value,2,labelDistAboveThumb/2);

g.translate(-labelLeft, -thumbRect.y+labelDistAboveThumb);

}

artntek at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 22
I had that, almost... wasn't sure about the translate method before, but it's my new favourite! :-)Thanks again.
csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 23

As well, would the correct approach to painting the start and end labels parallel (horizontally) to the start and end points of the JSlider be to use the translate method as well?

ie.

0 -- 100

where 0 and 100 are the two end labels, painted as shown... When I tried this, it paints the labels at the correct height, but they are too close to the ends of the slider, and I am not sure how to move them a few pixels away from the ends, as shown above.

TIA!

csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 24

lastly, if the labels at ends are created using a drawstring method, they appear to

be a thin black colour. How can this be changed to a look and feel of the original/labels, ie. the light purple colour with thicker text? This also affects the label

that moves with the thumb.

csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 25

> 0 -- 100

> I am not sure how to move them a

> few pixels away from the ends, as shown above.

If you look at the paintUpperLabel method I posted, you'll see these lines:

int labelCenter = xPositionForValue(value);

int labelLeft = labelCenter-lw/2;

g.translate(labelLeft, thumbRect.y-labelDistAboveThumb);

the labelLeft is the x-coord of the label's top left corner, and the method xPositionForValue(), from the superclass, calculates the x coord given a slider value. So- just check to make sure that the labelLeft isn't too near the ends://declare these outside the method, since

//they only need to be declared once:

final int lw = 20;//label width

final int lh = 15;//label height

final int leftLimit = xPositionForValue(5); //for example

final int rightLimit = xPositionForValue(95) - lw; //for example

//

//...

//then add this to the method itself:

}protected void paintUpperLabel( Graphics g) {

int value = slider.getValue();

int labelCenter = xPositionForValue(value);

int labelLeft = labelCenter-lw/2;

//ADD:

if (labelLeft<leftLimit) labelLeft=leftLimit;

if (labelRight>rightLimit) labelLeft=rightLimit;

g.translate(labelLeft, thumbRect.y-labelDistAboveThumb);

g.setColor(Color.green);//label color

g.fillRect(0, 0, lw,lh);

g.setColor(Color.black);//text color

g.drawString(""+value,2,labelDistAboveThumb/2);

g.translate(-labelLeft, -thumbRect.y+labelDistAboveThumb);

}

artntek at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 26

> lastly, if the labels at ends are created using a

> drawstring method, they appear to

> be a thin black colour. How can this be changed to a

> look and feel of the original/labels, ie. the light

> purple colour with thicker text? This also affects

> the label

> that moves with the thumb.

change the line:

g.setColor(Color.black);//text color

to match the other labels, and to change the font, add the line:

g.setFont(...);

(maybe you can get the existing font using slider.getFont()); ?)

artntek at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 27

As well, is it possible to update one endlabel (right label) of the JSlider if the setMaximum(value) method is called

during application runtime? Ie. a dynamic JSlider. The ticks and every other respect of the JSlider updates,

but that end label just is removed, and not replaced with the new maximum value.

TIA!

csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...
# 28
The above issue was solved!
csmathie at 2007-6-30 21:35:04 > top of Java-index,Archived Forums,Swing...