JSliderでオン・オフ切り替え可能なスイッチボタンを作成する
Total: 2274
, Today: 2
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JSlider
を使用してマウスクリックやつまみのドラッグでオン・オフの切り替え可能なスイッチボタンを作成します。
Screenshot
Advertisement
サンプルコード
UIDefaults d = new UIDefaults();
d.put("Slider.thumbHeight", 40);
d.put("Slider.thumbWidth", 40);
d.put("Slider:SliderTrack[Enabled].backgroundPainter", (Painter<JSlider>) (g, c, w, h) -> {
int arc = 40;
int fillLeft = 2;
int fillTop = 2;
int trackWidth = w - fillLeft - fillLeft;
int trackHeight = h - fillTop - fillTop;
int baseline = trackHeight - fillTop - fillTop; // c.getBaseline(w, h);
String off = "Off";
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.GRAY);
g.fillRoundRect(fillLeft, fillTop, trackWidth, trackHeight, arc, arc);
g.setPaint(Color.WHITE);
g.drawString(off, w - g.getFontMetrics().stringWidth(off) - fillLeft * 5, baseline);
int fillRight = getXPositionForValue(
c, new Rectangle(fillLeft, fillTop, trackWidth, trackHeight));
g.setColor(Color.ORANGE);
g.fillRoundRect(
fillLeft + 1, fillTop, fillRight - fillLeft, trackHeight, arc, arc);
g.setPaint(Color.WHITE);
if (fillRight - fillLeft > 0) {
g.drawString("On", fillLeft * 5, baseline);
}
g.setStroke(new BasicStroke(2.5f));
g.drawRoundRect(fillLeft, fillTop, trackWidth, trackHeight, arc, arc);
});
Painter<JSlider> thumbPainter = (g, c, w, h) -> {
int fillLeft = 8;
int fillTop = 8;
int trackWidth = w - fillLeft - fillLeft;
int trackHeight = h - fillTop - fillTop;
g.setPaint(Color.WHITE);
g.fillOval(fillLeft, fillTop, trackWidth, trackHeight);
};
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);
JSlider slider = new JSlider(0, 1, 0) {
@Override public Dimension getPreferredSize() {
return new Dimension(100, 40);
}
};
slider.setFont(slider.getFont().deriveFont(Font.BOLD, 32f));
slider.putClientProperty("Nimbus.Overrides", d);
View in GitHub: Java, Kotlin解説
Default
JSlider
を最小値0
、最大値1
に設定- コンポーネントのサイズを
getPreferredSize()
をオーバーライドして変更
Thumb size
- つまみのサイズを
Slider.thumbWidth
、Slider.thumbHeight
を設定して変更
- つまみのサイズを
SliderTrack
- トラックの背景を描画する
Painter
を設定して背景色やフチ、On/Off
の文字列の描画を変更 - トラックをプレスすると
On/Off
が切り替わる - つまみを描画する
Painter
を設定してその描画を変更 - つまみをドラッグすると残像が表示される場合があるので
MouseMotionListener
を追加してドラッグ中に全体を再描画 - つまみをプレス、またはクリックしても
On/Off
の切り替えは発生しない
- トラックの背景を描画する
JSlider + JLayer
- トラックとつまみの描画は
SliderTrack
と同様 JLayer
を使用してトラックやつまみに関係なくJSlider
をクリックするとOn/Off
が切り替わるよう設定- つまみのドラッグ中の再描画も以下のように
LayerUI#processMouseMotionEvent(...)
中で実行
- トラックとつまみの描画は
class ToggleSwitchLayerUI extends LayerUI<JSlider> {
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override protected void processMouseEvent(MouseEvent e, JLayer<? extends JSlider> l) {
if (e.getID() == MouseEvent.MOUSE_PRESSED && SwingUtilities.isLeftMouseButton(e)) {
e.getComponent().dispatchEvent(new MouseEvent(
e.getComponent(),
e.getID(), e.getWhen(),
InputEvent.BUTTON3_DOWN_MASK, // e.getModifiers(),
e.getX(), e.getY(),
e.getXOnScreen(), e.getYOnScreen(),
e.getClickCount(),
e.isPopupTrigger(),
MouseEvent.BUTTON3)); // e.getButton());
e.consume();
} else if (e.getID() == MouseEvent.MOUSE_CLICKED && SwingUtilities.isLeftMouseButton(e)) {
JSlider slider = l.getView();
int v = slider.getValue();
if (slider.getMinimum() == v) {
slider.setValue(slider.getMaximum());
} else if (slider.getMaximum() == v) {
slider.setValue(slider.getMinimum());
}
}
}
@Override protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends JSlider> l) {
l.getView().repaint();
}
}
参考リンク
- JSliderのトラックをクリックしても値の変更が発生しないように設定する
- Nimbus Defaults (The Java™ Tutorials > Creating a GUI With JFC/Swing > Modifying the Look and Feel)