JScrollBarを半透明にする
Total: 6908
, Today: 1
, Yesterday: 3
Posted by aterai at
Last-modified:
概要
半透明のJScrollBar
を作成して、JViewport
内部に配置します。
Screenshot
Advertisement
サンプルコード
public JComponent makeTranslucentScrollBar(JComponent c) {
JScrollPane scrollPane = new JScrollPane(c) {
@Override public boolean isOptimizedDrawingEnabled() {
return false; // JScrollBar is overlap
}
};
scrollPane.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setComponentZOrder(scrollPane.getVerticalScrollBar(), 0);
scrollPane.setComponentZOrder(scrollPane.getViewport(), 1);
scrollPane.getVerticalScrollBar().setOpaque(false);
scrollPane.setLayout(new ScrollPaneLayout() {
@Override public void layoutContainer(Container parent) {
JScrollPane scrollPane = (JScrollPane) parent;
Rectangle availR = scrollPane.getBounds();
availR.x = availR.y = 0;
Insets insets = parent.getInsets();
availR.x = insets.left;
availR.y = insets.top;
availR.width -= insets.left + insets.right;
availR.height -= insets.top + insets.bottom;
Rectangle vsbR = new Rectangle();
vsbR.width = 12;
vsbR.height = availR.height;
vsbR.x = availR.x + availR.width - vsbR.width;
vsbR.y = availR.y;
if (viewport != null) {
viewport.setBounds(availR);
}
if (vsb != null) {
vsb.setVisible(true);
vsb.setBounds(vsbR);
}
}
});
scrollPane.getVerticalScrollBar().setUI(new BasicScrollBarUI() {
private final Color defaultColor = new Color(220, 100, 100, 100);
private final Color draggingColor = new Color(200, 100, 100, 100);
private final Color rolloverColor = new Color(255, 120, 100, 100);
@Override protected JButton createDecreaseButton(int orientation) {
return new ZeroSizeButton();
}
@Override protected JButton createIncreaseButton(int orientation) {
return new ZeroSizeButton();
}
@Override protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
/* empty */
}
@Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
Color color;
JScrollBar sb = (JScrollBar) c;
if (!sb.isEnabled() || r.width > r.height) {
return;
} else if (isDragging) {
color = draggingColor;
} else if (isThumbRollover()) {
color = rolloverColor;
} else {
color = defaultColor;
}
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(color);
g2.fillRect(r.x, r.y, r.width - 1, r.height - 1);
g2.setPaint(Color.WHITE);
g2.drawRect(r.x, r.y, r.width - 1, r.height - 1);
g2.dispose();
}
@Override protected void setThumbBounds(int x, int y, int width, int height) {
super.setThumbBounds(x, y, width, height);
// scrollbar.repaint(x, 0, width, scrollbar.getHeight());
scrollbar.repaint();
}
});
return scrollPane;
}
View in GitHub: Java, Kotlin解説
上記のサンプルでは、JScrollBar
の増減ボタンのサイズを非表示、トラックを透明、つまみを半透明にして、JViewport
内部に配置しています。
ScrollPaneLayout#layoutContainer(...)
をオーバーライドしてJScrollBar
をJViewport
の内部にオーバーラップするように配置scrollPane.setComponentZOrder(...)
でJScrollBar
とJViewport
のZ
軸の順序を変更
BasicScrollBarUI#createDecreaseButton()
、BasicScrollBarUI#createIncreaseButton()
をオーバーライドして増減ボタンのサイズを0
に設定BasicScrollBarUI#paintTrack()
をオーバーライドしてトラックを非表示- トラックにつまみの残像が残るので
BasicScrollBarUI#setThumbBounds
をオーバーライドしてJScrollBar
全体を再描画
- トラックにつまみの残像が残るので
BasicScrollBarUI#paintThumb()
をオーバーライドして半透明のつまみを描画- つまみ描画のチラつき防止のため
JScrollPane#isOptimizedDrawingEnabled()
がfalse
を返すようにオーバーライド- このサンプルでは横スクロールバーの表示、カラムヘッダの表示に未対応
参考リンク
- "Optimized" Drawing - Painting in AWT and Swing
- JScrollBarをJTable上に重ねて表示するJScrollPaneを作成する
- JScrollBarのArrowButtonを非表示にする