Summary

JPopupMenuの表示位置で軽量・重量ポップアップを切り替えるのではなく、常に重量ポップアップを使用するよう設定します。

Source Code Examples

JPopupMenu popup0 = makePopupMenu();
// popup0.setLightWeightPopupEnabled(true); // Default
JLabel label0 = makeLabel("setLightWeightPopupEnabled: true", Color.ORANGE);
label0.setComponentPopupMenu(popup0);

JPopupMenu popup1 = makePopupMenu();
popup1.setLightWeightPopupEnabled(false);
JLabel label1 = makeLabel("setLightWeightPopupEnabled: false", Color.PINK);
label1.setComponentPopupMenu(popup1);

JComponent glass = new JPanel(new GridLayout(3, 1, 10, 10)) {
  private final Color backgroundColor = new Color(0x64_64_64_C8, true);
  @Override protected void paintComponent(Graphics g) {
    g.setColor(backgroundColor);
    g.fillRect(0, 0, getWidth(), getHeight());
    super.paintComponent(g);
  }
};
glass.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
glass.setOpaque(false);
glass.add(label0);
glass.add(label1);
View in GitHub: Java, Kotlin

Explanation

  • JComboBox#setLightWeightPopupEnabled(boolean)
    • GlassPaneに配置されたJComboBoxのドロップダウンリスト全体が親JFrame内で表示可能で軽量ポップアップが使用されるとGlassPaneの奥に表示される
    • JComboBoxで使用するドロップダウンリスト(javax.swing.plaf.basic.BasicComboPopupJPopupMenuを継承)にJComboBox#setLightWeightPopupEnabled(false)を指定することでそのドロップダウンリストが常に重量ポップアップで開くよう設定
  • JPopupMenu#setLightWeightPopupEnabled(boolean)
    • GlassPaneに配置されたコンポーネントにJComponent#setComponentPopupMenu(...)で設定されたJPopupMenu全体が親JFrame内で表示可能で軽量ポップアップが使用されるとGlassPaneの奥に表示される
    • JPopupMenuJPopupMenu#setLightWeightPopupEnabled(false)を指定してそれが常に重量ポップアップとして開くよう設定

// Java 9:
PopupFactory.setSharedInstance(new PopupFactory() {
  @Override public Popup getPopup(
      Component owner, Component contents, int x, int y)
      throws IllegalArgumentException {
    // @param isHeavyWeightPopup true if Popup should be heavy-weight,
    // protected Popup getPopup(..., boolean isHeavyWeightPopup) ...
    return super.getPopup(owner, contents, x, y, true);
  }
});

Reference

Comment