Swing/MiniMap のバックアップ(No.1)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/MiniMap へ行く。
- 1 (2019-08-12 (月) 20:49:42)
- 2 (2019-08-31 (土) 15:12:48)
- 3 (2021-04-22 (木) 21:53:16)
- 4 (2021-05-12 (水) 06:37:19)
- category: swing folder: MiniMap title: JEditorPaneのミニマップを表示する tags: [JEditorPane, JScrollPane, JScrollBar, ImgeIcon, LayoutManager] author: aterai pubdate: 2019-08-12T20:46:57+09:00 description: JEditorPaneのミニマップをImageIconで作成し、これをLayoutManagerを使用してJScrollPane上に重ねて表示します。 image: https://drive.google.com/uc?id=1_Ix_ksss07Sfpz-vM0rEWJ_yorOS9dX8
概要
JEditorPane
のミニマップをImageIcon
で作成し、これをLayoutManager
を使用してJScrollPane
上に重ねて表示します。
Screenshot
Advertisement
サンプルコード
private final JEditorPane editor = new JEditorPane();
private final JScrollPane scroll = new JScrollPane(editor);
private final JLabel label = new JLabel() {
private transient MouseInputListener handler;
@Override public void updateUI() {
removeMouseListener(handler);
removeMouseMotionListener(handler);
super.updateUI();
handler = new MiniMapHandler();
addMouseListener(handler);
addMouseMotionListener(handler);
}
@Override public void paintComponent(Graphics g) {
super.paintComponent(g);
Container c = SwingUtilities.getAncestorOfClass(JViewport.class, editor);
if (!(c instanceof JViewport) || editor == null) {
return;
}
JViewport vport = (JViewport) c;
Rectangle vrect = vport.getBounds(); // scroll.getViewportBorderBounds();
Rectangle erect = editor.getBounds();
Rectangle crect = SwingUtilities.calculateInnerArea(this, new Rectangle());
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
double sy = crect.getHeight() / erect.getHeight();
AffineTransform at = AffineTransform.getScaleInstance(1d, sy);
// paint Thumb
Rectangle thumbRect = new Rectangle(vrect);
thumbRect.y = vport.getViewPosition().y;
Rectangle r = at.createTransformedShape(thumbRect).getBounds();
int y = crect.y + r.y;
g2.setColor(THUMB_COLOR);
g2.fillRect(0, y, crect.width, r.height);
g2.setColor(THUMB_COLOR.darker());
g2.drawRect(0, y, crect.width - 1, r.height - 1);
g2.dispose();
}
};
private class MiniMapHandler extends MouseInputAdapter {
@Override public void mousePressed(MouseEvent e) {
processMiniMapMouseEvent(e);
}
@Override public void mouseDragged(MouseEvent e) {
processMiniMapMouseEvent(e);
}
protected final void processMiniMapMouseEvent(MouseEvent e) {
Point pt = e.getPoint();
Component c = (Component) e.getComponent();
BoundedRangeModel m = scroll.getVerticalScrollBar().getModel();
int brm = m.getMaximum() - m.getMinimum();
int iv = (int) (.5 - m.getExtent() * .5 + pt.y * brm / (double) c.getHeight());
m.setValue(iv);
}
}
// ...
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.getVerticalScrollBar().getModel().addChangeListener(e -> label.repaint());
JPanel pp = new JPanel(new BorderLayout(0, 0));
pp.add(label, BorderLayout.NORTH);
JScrollPane minimap = new JScrollPane(pp);
minimap.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
minimap.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
Box box = Box.createHorizontalBox();
box.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
box.add(Box.createHorizontalGlue());
box.add(button);
JPanel p = new JPanel() {
@Override public boolean isOptimizedDrawingEnabled() {
return false;
}
};
p.setLayout(new BorderLayout(0, 0) {
@Override public void layoutContainer(Container parent) {
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int width = parent.getWidth();
int height = parent.getHeight();
int top = insets.top;
int bottom = height - insets.bottom;
int left = insets.left;
int right = width - insets.right;
Component ec = getLayoutComponent(parent, BorderLayout.EAST);
if (Objects.nonNull(ec)) {
Dimension d = ec.getPreferredSize();
JScrollBar vsb = scroll.getVerticalScrollBar();
int vsw = vsb.isVisible() ? vsb.getSize().width : 0;
ec.setBounds(right - d.width - vsw, top, d.width, bottom - top);
}
Component cc = getLayoutComponent(parent, BorderLayout.CENTER);
if (Objects.nonNull(cc)) {
cc.setBounds(left, top, right - left, bottom - top);
}
}
}
});
p.add(minimap, BorderLayout.EAST);
p.add(scroll);
View in GitHub: Java, Kotlin解説
JEditorPane
の縮小画像からImageIcon
を生成してJLabel
に設定、さらにスクロールバーを非表示にしたJScrollPane
に配置してミニマップを作成JEditorPane
を配置したJScrollPane
とミニマップを配置したJScrollPane
を重ねて配置するLayoutManager
を使用- ミニマップとして使用する
JLabel
にMouseListener
を追加してマウスで表示位置を変更可能に設定
参考リンク
- JLabelとIconで作成した検索位置表示バーをマウスで操作する
- Component上に重ねて配置したダイアログの表示状態をアニメーション付きで切り替える
- JTabbedPaneのサムネイルをJToolTipで表示