Swing/MajorTickOnTrack の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/MajorTickOnTrack へ行く。
- Swing/MajorTickOnTrack の差分を削除
--- category: swing folder: MajorTickOnTrack title: JSliderのトラック内部に目盛りを描画する tags: [JSlider, NimbusLookAndFeel] author: aterai pubdate: 2022-03-14T01:15:06+09:00 description: JSliderのトラック内部に大目盛り、ノブ内部に現在値を描画します。 image: https://drive.google.com/uc?id=1L0-XlJbF6L06V-UhIgnH2jae6Zs2kCVq hreflang: href: href: https://java-swing-tips.blogspot.com/2022/03/paint-major-tick-marks-inside-jslider.html href: https://java-swing-tips.blogspot.com/2022/03/paint-major-tick-marks-inside-jslider.html lang: en --- * 概要 [#summary] `JSlider`のトラック内部に大目盛り、ノブ内部に現在値を描画します。 #download(https://drive.google.com/uc?id=1L0-XlJbF6L06V-UhIgnH2jae6Zs2kCVq) * サンプルコード [#sourcecode] #code(link){{ JSlider slider = new JSlider(); slider.setSnapToTicks(true); slider.setMajorTickSpacing(10); slider.addMouseMotionListener(new MouseAdapter() { @Override public void mouseDragged(MouseEvent e) { super.mouseDragged(e); e.getComponent().repaint(); } }); UIDefaults d = new UIDefaults(); d.put("Slider.thumbWidth", 24); d.put("Slider.thumbHeight", 24); Painter<JSlider> thumbPainter = (g, c, w, h) -> { g.setPaint(new Color(0x21_98_F6)); g.fillOval(0, 0, w, h); NumberIcon icon = new NumberIcon(c.getValue()); int xx = (w - icon.getIconWidth()) / 2; int yy = (h - icon.getIconHeight()) / 2; icon.paintIcon(c, g, xx, yy); }; d.put("Slider:SliderThumb[Disabled].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[Enabled].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[Focused+MouseOver].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[Focused+Pressed].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[Focused].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[MouseOver].backgroundPainter", thumbPainter); d.put("Slider:SliderThumb[Pressed].backgroundPainter", thumbPainter); d.put("Slider:SliderTrack[Enabled].backgroundPainter", new Painter<JSlider>() { @Override public void paint(Graphics2D g, JSlider c, int w, int h) { int arc = 10; int thumbSize = 24; int trackHeight = 8; int tickSize = 4; int trackWidth = w - thumbSize; int fillTop = (thumbSize - trackHeight) / 2; int fillLeft = thumbSize / 2; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(0xC6_E4_FC)); g.fillRoundRect(fillLeft, fillTop + 2, trackWidth, trackHeight - 4, arc, arc); // Paint track g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(0xC6_E4_FC)); g.fillRoundRect(fillLeft, fillTop + 2, trackWidth, trackHeight - 4, arc, arc); int fillBottom = fillTop + trackHeight; Rectangle r = new Rectangle(fillLeft, fillTop, trackWidth, fillBottom - fillTop); // Paint the major tick marks on the track g.setColor(new Color(0x31_A8_F8)); int value = c.getMinimum(); while (value <= c.getMaximum()) { int xpt = getXPositionForValue(c, r, value); g.fillOval(xpt, (int) r.getCenterY() - tickSize / 2, tickSize, tickSize); // Overflow checking if (Integer.MAX_VALUE - c.getMajorTickSpacing() < value) { break; } value += c.getMajorTickSpacing(); } // JSlider.isFilled int fillRight = getXPositionForValue(c, r, c.getValue()); g.setColor(new Color(0x21_98_F6)); g.fillRoundRect(fillLeft, fillTop, fillRight - fillLeft, fillBottom - fillTop, arc, arc); } // @see javax/swing/plaf/basic/BasicSliderUI#xPositionForValue(int value) private int getXPositionForValue(JSlider slider, Rectangle trackRect, float value) { float min = slider.getMinimum(); float max = slider.getMaximum(); float pixelsPerValue = trackRect.width / (max - min); int trackLeft = trackRect.x; int trackRight = trackRect.x + trackRect.width - 1; int pos = trackLeft + Math.round(pixelsPerValue * (value - min)); return Math.max(trackLeft, Math.min(trackRight, pos)); } }); slider.putClientProperty("Nimbus.Overrides", d); }} * 解説 [#explanation] - `Slider:SliderTrack[Enabled].backgroundPainter` -- トラック描画用の`Painter<JSlider>`を作成し、その`Painter#paint(...)`メソッドをオーバーライドしてトラック内部に大目盛りを描画 -- [[NimbusLookAndFeelを適用したJSliderで範囲の塗りつぶしを行う>Swing/NimbusFilledSlider]] -- 垂直`JSlider`や`JSlider#setInverted(true)`で値が通常の順序と逆に設定されている場合には未対応 - `Slider:SliderThumb[Enabled].backgroundPainter` -- ノブ描画用の`Painter<JSlider>`を作成し、その`Painter#paint(...)`メソッドをオーバーライドしてノブ内に`JSlider#getValue()`で取得した現在値を描画 -- [[JLabel内のアイコンにJLayerを使用してバッジを表示する>Swing/NotificationBadge]] * 参考リンク [#reference] - [[JSliderでオン・オフ切り替え可能なスイッチボタンを作成する>Swing/ToggleSwitch]] - [[JLabel内のアイコンにJLayerを使用してバッジを表示する>Swing/NotificationBadge]] - [[NimbusLookAndFeelを適用したJSliderで範囲の塗りつぶしを行う>Swing/NimbusFilledSlider]] * コメント [#comment] #comment #comment