カスタムスクロールバーを使用するためにスクロールペインセットを使用しています。とりわけ、スクロールバーの親指にリスナーをインストールして、マウスが親指領域に入ると色や境界線を変更できるようにしたいと考えていました。BasicScrollBarUI (カスタム スクロールバー UI で拡張) を検索したところ、メソッド installListeners() が見つかったので、それをオーバーライドして、サム領域のもう 1 つのリスナーを呼び出すようにしました。
SSCCE:
public class TestScrollBar extends JFrame {
public TestScrollBar() {
JPanel innerPanel = new JPanel();
innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.Y_AXIS));
for (int i=1; i<=10; i++) {
innerPanel.add(new JLabel("Label "+i));
innerPanel.add(Box.createRigidArea(new Dimension(0, 20)));
}
JScrollPane scrollPane = new JScrollPane(innerPanel);
scrollPane.setPreferredSize(new Dimension(innerPanel.getPreferredSize().width, innerPanel.getPreferredSize().height/2));
scrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI());
this.setLayout(new BorderLayout());
this.add(Box.createRigidArea(new Dimension(0, 20)), BorderLayout.NORTH);
this.add(Box.createRigidArea(new Dimension(0, 20)), BorderLayout.SOUTH);
this.add(Box.createRigidArea(new Dimension(20, 0)), BorderLayout.EAST);
this.add(Box.createRigidArea(new Dimension(20, 0)), BorderLayout.WEST);
this.add(scrollPane, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestScrollBar frame = new TestScrollBar();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
スクロールバー用のシンプルなカスタム UI:
public class CustomScrollBarUI extends BasicScrollBarUI {
@Override
protected void installListeners() {
super.installListeners();
scrollbar.addMouseListener(new CustomListener());
}
protected class CustomListener extends MouseAdapter {
public void mouseEntered(MouseEvent e) {
if (getThumbBounds().contains(e.getX(), e.getY())) {
System.out.println("THUMB");
}
}
}
}
リスナーは、マウスが右または左から親指領域に入ると正常に動作しますが、常に上または下側では機能するとは限りません。これらの面では、親指がボタンの 1 つに触れている場合にのみ機能します。たとえば、スクロールバーが一番上にある場合、リスナーは、マウスが下からではなく上のボタンからサム領域に入ったときにのみ (左右を除いて) 動作します。スクロールバーが減少ボタンに触れると、反対のことが起こります (右/左/下側でのみ機能し、上では機能しません)。親指がボタンのいずれにも触れずにその間のどこかにある場合、左右の側面のみが機能します。コードを実行すると、これらすべてを確認できます。
また、(独自のリスナーを作成する代わりに) 既存のリスナーの 1 つ、BasicScrollBarUI.TrackListener を使用しようとしました。ここでは、親指領域のみをリッスンするメソッドを追加しましたが、結果はまったく同じです。
public class CustomScrollBarUI extends BasicScrollBarUI {
@Override
protected TrackListener createTrackListener(){
return new TrackListener();
}
protected class TrackListener extends BasicScrollBarUI.TrackListener {
public void mouseEntered(MouseEvent e) {
currentMouseX = e.getX();
currentMouseY = e.getY();
if (getThumbBounds().contains(currentMouseX, currentMouseY)) {
System.out.println("THUMB");
}
}
}
}