Swing/GradientTrackSlider のバックアップ(No.6)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/GradientTrackSlider へ行く。
- 1 (2011-06-05 (日) 22:38:45)
- 2 (2012-12-21 (金) 19:11:06)
- 3 (2012-12-22 (土) 16:36:25)
- 4 (2012-12-26 (水) 06:00:35)
- 5 (2012-12-26 (水) 11:13:30)
- 6 (2014-12-02 (火) 01:29:07)
- 7 (2015-03-01 (日) 16:09:25)
- 8 (2015-03-20 (金) 15:30:21)
- 9 (2015-03-24 (火) 16:04:08)
- 10 (2015-07-08 (水) 16:58:41)
- 11 (2016-05-26 (木) 14:56:20)
- 12 (2017-08-10 (木) 14:40:29)
- 13 (2018-02-24 (土) 19:51:30)
- 14 (2018-08-15 (水) 20:30:15)
- 15 (2018-12-20 (木) 11:34:58)
- 16 (2020-11-15 (日) 01:58:30)
- 17 (2022-12-01 (木) 10:42:41)
- title: JSliderのスタイルを変更する tags: [JSlider, LinearGradientPaint, Transparent, UIManager, Icon] author: aterai pubdate: 2011-05-23T15:19:26+09:00 description: JSliderのトラックとノブを透明にし、値を半透明の色で描画します。
概要
JSlider
のトラックとノブを透明にし、値を半透明の色で描画します。
Screenshot
Advertisement
サンプルコード
UIManager.put("Slider.horizontalThumbIcon", new Icon() {
@Override public void paintIcon(Component c, Graphics g, int x, int y) {}
@Override public int getIconWidth() { return 15; }
@Override public int getIconHeight() { return 64; }
});
UIManager.put("Slider.trackWidth", 64);
UIManager.put("Slider.majorTickLength", 6);
JSlider slider = makeSlider();
slider.setUI(new MetalSliderUI() {
int[] pallet = makeGradientPallet();
@Override public void paintTrack(Graphics g) {
//Color trackColor = !slider.isEnabled()
// ? MetalLookAndFeel.getControlShadow() : slider.getForeground();
boolean leftToRight = true; //MetalUtils.isLeftToRight(slider);
Color controlDarkShadow = Color.GRAY;
Color controlHighlight = new Color(200,255,200);
Color controlShadow = new Color(0,100,0);
g.translate( trackRect.x, trackRect.y );
int trackLeft = 0;
int trackTop = 0;
int trackRight = 0;
int trackBottom = 0;
// Draw the track
if(slider.getOrientation() == JSlider.HORIZONTAL) {
trackBottom = (trackRect.height - 1) - getThumbOverhang();
trackTop = trackBottom - (getTrackWidth() - 1);
trackRight = trackRect.width - 1;
}else{
if(leftToRight) {
trackLeft = (trackRect.width - getThumbOverhang()) - getTrackWidth();
trackRight = (trackRect.width - getThumbOverhang()) - 1;
}else{
trackLeft = getThumbOverhang();
trackRight = getThumbOverhang() + getTrackWidth() - 1;
}
trackBottom = trackRect.height - 1;
}
if(slider.isEnabled()) {
g.setColor(controlDarkShadow);
g.drawRect(trackLeft, trackTop,
(trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);
g.setColor(controlHighlight);
g.drawLine(trackLeft + 1, trackBottom, trackRight, trackBottom);
g.drawLine(trackRight, trackTop + 1, trackRight, trackBottom);
g.setColor(controlShadow);
g.drawLine(trackLeft + 1, trackTop + 1, trackRight - 2, trackTop + 1);
g.drawLine(trackLeft + 1, trackTop + 1, trackLeft + 1, trackBottom - 2);
} else {
g.setColor(controlShadow);
g.drawRect(trackLeft, trackTop,
(trackRight - trackLeft) - 1, (trackBottom - trackTop) - 1);
}
// Draw the fill
int middleOfThumb = 0;
int fillTop = 0;
int fillLeft = 0;
int fillBottom = 0;
int fillRight = 0;
if(slider.getOrientation() == JSlider.HORIZONTAL) {
middleOfThumb = thumbRect.x + (thumbRect.width / 2);
middleOfThumb -= trackRect.x; // To compensate for the g.translate()
fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
if(!drawInverted()) {
fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
fillRight = middleOfThumb;
}else{
fillLeft = middleOfThumb;
fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
}
}else{
middleOfThumb = thumbRect.y + (thumbRect.height / 2);
middleOfThumb -= trackRect.y; // To compensate for the g.translate()
fillLeft = !slider.isEnabled() ? trackLeft : trackLeft + 1;
fillRight = !slider.isEnabled() ? trackRight - 1 : trackRight - 2;
if(!drawInverted()) {
fillTop = middleOfThumb;
fillBottom = !slider.isEnabled() ? trackBottom - 1 : trackBottom - 2;
}else{
fillTop = !slider.isEnabled() ? trackTop : trackTop + 1;
fillBottom = middleOfThumb;
}
}
if(slider.isEnabled()) {
g.setColor(slider.getBackground());
g.drawLine(fillLeft, fillTop, fillRight, fillTop );
g.drawLine(fillLeft, fillTop, fillLeft, fillBottom );
double x = (fillRight - fillLeft) / (double)(trackRight - trackLeft);
g.setColor(getColorFromPallet(pallet, x));
g.fillRect(fillLeft+1,fillTop+1,fillRight-fillLeft,fillBottom-fillTop);
}else{
g.setColor(controlShadow);
g.fillRect(fillLeft,fillTop,fillRight-fillLeft,trackBottom-trackTop);
}
int yy = trackTop + (trackBottom - trackTop) /2;
for(int i=10;i>=0;i--) {
g.setColor( new Color(1f,1f,1f,i*0.07f) );
g.drawLine( trackLeft+2, yy, (trackRight - trackLeft), yy );
yy--;
}
g.translate(-trackRect.x, -trackRect.y);
}
});
View in GitHub: Java, Kotlin解説
上記のサンプルでは、MetalSliderUI#paintTrack(...)
メソッドをオーバーライドしたSliderUI
を設定するなどして、JSlider
の各スタイルを変更しています。
Track
JSlider#setOpaque(false)
で透明化MetalSliderUI#paintTrack(...)
内で、Fill
の後でハイライトを描画
Thumb
UIManager.put("Slider.horizontalThumbIcon", emptyIcon)
で、空のアイコンを設定して非表示
Fill
MetalSliderUI#paintTrack(...)
内で、値に応じてLinearGradientPaint
から作成した色で描画
private static int[] makeGradientPallet() {
BufferedImage image = new BufferedImage(100, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = image.createGraphics();
Point2D start = new Point2D.Float(0f, 0f);
Point2D end = new Point2D.Float(99f, 0f);
float[] dist = {0.0f, 0.5f, 1.0f};
Color[] colors = { Color.RED, Color.YELLOW, Color.GREEN };
g2.setPaint(new LinearGradientPaint(start, end, dist, colors));
g2.fillRect(0, 0, 100, 1);
int width = image.getWidth(null);
int[] pallet = new int[width];
PixelGrabber pg = new PixelGrabber(image, 0, 0, width, 1, pallet, 0, width);
try{
pg.grabPixels();
}catch(Exception e) {
e.printStackTrace();
}
return pallet;
}
private static Color getColorFromPallet(int[] pallet, float x) {
int i = (int)(pallet.length * x);
int max = pallet.length-1;
int index = i<0?0:i>max?max:i;
int pix = pallet[index] & 0x00ffffff | (0x64 << 24);
return new Color(pix, true);
}
- メモ: 例えば
WindowsLookAndFeel
では、UIManager.get("Slider.trackWidth")
はnull
なので、MetalSliderUI#installUI()
中にある以下のコードでエラーになる。
trackWidth = ((Integer)UIManager.get("Slider.trackWidth")).intValue();
- なぜ
UIManager.getInt(...)
ではないのか不明 UIManager.put("Slider.majorTickLength", 6);
などで回避MetalSliderUI
ではなく、BasicSliderUI
を継承するぺき?