Swing/NotPopupOverlapTaskBar のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/NotPopupOverlapTaskBar へ行く。
- 1 (2023-01-30 (月) 06:07:14)
- 2 (2023-09-25 (月) 17:12:03)
- category: swing folder: NotPopupOverlapTaskBar title: JPopupMenuがTaskBarと重ならないように表示位置を調整する tags: [JPopupMenu, TaskBar] author: aterai pubdate: 2023-01-30T06:05:32+09:00 description: JPopupMenuがTaskBarと重なる場合、マウスカーソル位置がその右下隅になるよう表示位置を調整し、内部のJMenuItemの配置も反転します。 image: https://drive.google.com/uc?id=1qKrSZUuSGcLCP3cebYbv07ITdlv5w2_I
概要
JPopupMenu
がTaskBar
と重なる場合、マウスカーソル位置がその右下隅になるよう表示位置を調整し、内部のJMenuItem
の配置も反転します。
Screenshot
Advertisement
サンプルコード
List<Component> list = Arrays.asList(
new JMenuItem("JMenuItem 1"),
new JMenuItem("JMenuItem 2"),
new JMenuItem("JMenuItem 3"),
new JMenuItem("JMenuItem 4"),
new JMenuItem("JMenuItem 5"));
JPopupMenu popup = new JPopupMenu() {
@Override public void show(Component c, int x, int y) {
Point popupLocation = getInvokerOrigin(x, y, c.getLocationOnScreen());
Rectangle scrBounds = getScreenBounds(c, popupLocation);
Dimension popupSize = getPreferredSize();
long popupBottomY = (long) popupLocation.y + (long) popupSize.height;
Point p = new Point(x, y);
removeAll();
if (popupBottomY > scrBounds.y + scrBounds.height) {
p.translate(-popupSize.width, -popupSize.height);
for (int i = list.size() - 1; i >= 0; i--) {
add(list.get(i));
}
} else {
list.forEach(this::add);
}
super.show(c, p.x, p.y);
}
};
list.forEach(popup::add);
setComponentPopupMenu(popup);
View in GitHub: Java, Kotlin解説
JPopupMenu
の親コンポーネントが表示されているGraphicsConfiguration
を取得JPopupMenu#getCurrentGraphicsConfiguration(Point)
を参考
GraphicsConfiguration getCurrentGraphicsConfiguration2(Component c, Point p) {
GraphicsConfiguration gc = null;
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gd = ge.getScreenDevices();
for (GraphicsDevice graphicsDevice : gd) {
if (graphicsDevice.getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
GraphicsConfiguration dgc = graphicsDevice.getDefaultConfiguration();
if (dgc.getBounds().contains(p)) {
gc = dgc;
break;
}
}
}
// If not found, and we have invoker, ask invoker about his gc
if (gc == null && c != null) {
gc = c.getGraphicsConfiguration();
}
return gc;
}
- 取得した
GraphicsConfiguration
からスクリーン領域を取得しTaskBar
などの余白を除去
private static Rectangle getScreenBounds(Component c, Point popupLocation) {
Rectangle scrBounds;
GraphicsConfiguration gc = getCurrentGraphicsConfiguration2(c, popupLocation);
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (gc != null) {
// If we have GraphicsConfiguration use it to get screen bounds
scrBounds = gc.getBounds();
} else {
scrBounds = new Rectangle(toolkit.getScreenSize());
}
Insets scrInsets = toolkit.getScreenInsets(gc);
scrBounds.x += scrInsets.left;
scrBounds.y += scrInsets.top;
scrBounds.width -= scrInsets.left + scrInsets.right;
scrBounds.height -= scrInsets.top + scrInsets.bottom;
return scrBounds;
}
JPopupMenu#show(...)
をオーバーライドして取得したスクリーン領域の外にJPopupMenu
の下辺が表示される場合は、マウスカーソル位置がJPopupMenu
の右下隅になるよう表示位置を調整- 左上隅から右下隅にマウスカーソル配置が変更されるので
JPopupMenu
内部のJMenuItem
の配置もマウスカーソル移動距離が短くなるよう昇順から降順に変更 JPopupMenu#show(...)
内などで参照されているpopupPostionFixDisabled
はpopupPositionFixDisabled
のtypo
?
- 左上隅から右下隅にマウスカーソル配置が変更されるので