Swing/SliderTicksPosition のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/SliderTicksPosition へ行く。
- 1 (2022-07-18 (月) 09:28:08)
- 2 (2022-07-18 (月) 19:22:13)
- 3 (2022-07-20 (水) 07:49:14)
- 4 (2022-12-31 (土) 17:26:18)
- category: swing folder: SliderTicksPosition title: JSliderの目盛り表示位置をトラック上部に変更する tags: [JSlider, JLayer] author: aterai pubdate: 2022-07-18T09:24:25+09:00 description: 水平JSliderの目盛りをトラック上部に表示し、つまみの矢印も上向きに描画するよう変更します。 image: https://drive.google.com/uc?id=1Jm5tHOewLJQ6ExRVgFWdzBBTezrNjzZA
概要
水平JSlider
の目盛りをトラック上部に表示し、つまみの矢印も上向きに描画するよう変更します。
Screenshot
Advertisement
サンプルコード
class VerticalFlipLayerUI extends LayerUI<JComponent> {
@Override public void paint(Graphics g, JComponent c) {
if (c instanceof JLayer) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setTransform(getAffineTransform(c.getSize()));
super.paint(g2, c);
g2.dispose();
} else {
super.paint(g, c);
}
}
@Override public void installUI(JComponent c) {
super.installUI(c);
if (c instanceof JLayer) {
JLayer<?> l = (JLayer<?>) c;
l.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK
| AWTEvent.MOUSE_WHEEL_EVENT_MASK
| AWTEvent.KEY_EVENT_MASK);
}
}
@Override public void uninstallUI(JComponent c) {
if (c instanceof JLayer) {
((JLayer<?>) c).setLayerEventMask(0);
}
super.uninstallUI(c);
}
@Override public void eventDispatched(AWTEvent e, JLayer<? extends JComponent> l) {
if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent) e;
Point2D pt = me.getPoint();
try {
pt = getAffineTransform(l.getSize()).inverseTransform(pt, null);
} catch (NoninvertibleTransformException ex) {
ex.printStackTrace();
UIManager.getLookAndFeel().provideErrorFeedback(me.getComponent());
}
// Horizontal: me.translatePoint((int) pt.getX() - me.getX(), 0);
me.translatePoint(0, (int) pt.getY() - me.getY());
l.repaint();
}
super.eventDispatched(e, l);
}
private AffineTransform getAffineTransform(Dimension d) {
AffineTransform at = AffineTransform.getTranslateInstance(0d, d.height);
at.scale(1d, -1d);
return at;
}
}
View in GitHub: Java, Kotlin解説
VerticalFlipLayerUI
JLayer
を使用して水平JSlider
とその内部のMouseEvent
の上下を反転- ラベルの数字も上下反転してしまう
UpArrowThumbSliderUI
BasicSliderUI
のcalculateTrackRect()
、calculateTickRect()
、calculateLabelRect()
をオーバーライドしてこの3
つの領域の描画位置を入れ替える- つまみの矢印は
BasicSliderUI#paintThumb()
をオーバーライドしてその場で上下反転描画 MetalLookAndFeel
やWindowsLookAndFeel
ではつまみだけ反転するのは難しい?
class UpArrowThumbSliderUI extends BasicSliderUI {
protected UpArrowThumbSliderUI(JSlider slider) {
super(slider);
}
@Override protected void calculateTrackRect() {
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
int centerSpacing = thumbRect.height;
if (slider.getPaintTicks()) {
centerSpacing -= getTickLength();
}
if (slider.getPaintLabels()) {
centerSpacing -= getHeightOfTallestLabel();
}
trackRect.x = contentRect.x + trackBuffer;
trackRect.y = contentRect.y + (contentRect.height + centerSpacing + 1) / 2;
trackRect.width = contentRect.width - (trackBuffer * 2);
trackRect.height = thumbRect.height;
} else {
super.calculateTrackRect();
}
}
@Override protected void calculateTickRect() {
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
tickRect.x = trackRect.x;
// tickRect.y = trackRect.y + trackRect.height;
tickRect.y = trackRect.y;
tickRect.width = trackRect.width;
tickRect.height = slider.getPaintTicks() ? getTickLength() : 0;
} else {
super.calculateTickRect();
}
}
@Override protected void calculateLabelRect() {
if (slider.getPaintLabels()) {
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
labelRect.width = tickRect.width + (trackBuffer * 2);
labelRect.height = getHeightOfTallestLabel();
labelRect.x = tickRect.x - trackBuffer;
labelRect.y = tickRect.y - labelRect.height;
} else {
super.calculateLabelRect();
}
} else {
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
labelRect.x = tickRect.x;
labelRect.y = tickRect.y; // + tickRect.height;
labelRect.width = tickRect.width;
labelRect.height = 0;
} else {
super.calculateLabelRect();
}
}
}
@Override public void paintThumb(Graphics g) {
Boolean arrowShape = (Boolean) slider.getClientProperty("Slider.paintThumbArrowShape");
boolean isArrow = slider.getPaintTicks() && !Boolean.FALSE.equals(arrowShape);
if (isArrow && slider.getOrientation() == SwingConstants.HORIZONTAL) {
Color bc = slider.getBackground();
g.setColor(slider.isEnabled() ? bc : bc.darker());
Rectangle knobBounds = thumbRect;
Graphics2D g2 = (Graphics2D) g.create();
g2.translate(knobBounds.x, knobBounds.y + knobBounds.height);
g2.scale(1d, -1d);
int w = knobBounds.width;
int h = knobBounds.height;
int cw = w / 2;
g2.fillRect(1, 1, w - 3, h - 1 - cw);
Polygon p = new Polygon();
p.addPoint(1, h - cw);
p.addPoint(cw - 1, h - 1);
p.addPoint(w - 2, h - 1 - cw);
g2.fillPolygon(p);
g2.setColor(Color.WHITE);
g2.drawLine(0, 0, w - 2, 0);
g2.drawLine(0, 1, 0, h - 1 - cw);
g2.drawLine(0, h - cw, cw - 1, h - 1);
g2.setColor(Color.BLACK);
g2.drawLine(w - 1, 0, w - 1, h - 2 - cw);
g2.drawLine(w - 1, h - 1 - cw, w - 1 - cw, h - 1);
g2.setColor(Color.GRAY);
g2.drawLine(w - 2, 1, w - 2, h - 2 - cw);
g2.drawLine(w - 2, h - 1 - cw, w - 1 - cw, h - 2);
g2.dispose();
} else {
super.paintThumb(g);
}
}
}
参考リンク
- JSliderの順序を反転
- 垂直
JSlider
の目盛りをデフォルトの右側から左側に変更する場合はJSlider#setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT)
が使用可能
- 垂直