JFrame中的JPopupMenu使用AWTUtilities.setWindowOpaque(window,false),使用合成器L&F不显示

这个让我很困惑。 基本上我正在使用定制的Synth L&F使用透明形状的窗口开发多窗口应用程序。 应用程序的JDialog部分从父框架调用JFrame / JDialog组件。 在这些组件中,我有弹出菜单和combobox,问题是一些使用应用程序的人会遇到调用时没有出现的弹出菜单。 没有例外,代码执行正常,包括弹出菜单’show’方法。

除了在Mac OSX上似乎没有问题之外,我已经尝试将这个问题归结为操作系统细节。 像我这样的一些Windows用户没有遇到任何问题,其他人做….

此外,我已经找到了设置窗口不透明度的有问题的代码行:

 AWTUtilities.setWindowOpaque(window, false) 

如果我删除此LOC,则弹出窗口显示正常。 另外用以下内容替换此LOC:

 window.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.0f)); 

产生同样的问题。 另一件事是,如果我使用默认的L&F弹出窗口渲染正常。

只是为了确认JFrameJDialog组件的问题是相同的,并且只是想知道是否有其他人遇到过这个问题或者可能指出我可能的原因。

干杯

测试源重现:

 import com.sun.awt.AWTUtilities; import javax.swing.*; import javax.swing.plaf.synth.SynthLookAndFeel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestFrame extends JFrame{ public TestFrame(){ super.setTitle("Test Frame"); JButton btnDialog = new JButton("Open Dialog"); btnDialog.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TestDialog dialog = new TestDialog(TestFrame.this, true); dialog.setVisible(true); } }); super.add(btnDialog, BorderLayout.CENTER); super.pack(); super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); super.setVisible(true); } public static void main(String[] args){ initLookAndFeel(); new TestFrame(); } public static void initLookAndFeel() { SynthLookAndFeel lookAndFeel = new SynthLookAndFeel(); try { lookAndFeel.load(TestFrame.class.getResourceAsStream("/testskin.xml"), TestFrame.class); UIManager.setLookAndFeel(lookAndFeel); } catch (Exception e) { e.printStackTrace(); } } public static class TestDialog extends JDialog{ public TestDialog(Frame owner, boolean modal) { super(owner, modal); JComboBox petList = new JComboBox(new String[] { "Bird", "Cat", "Dog", "Rabbit", "Pig" }); super.add(petList, BorderLayout.CENTER); super.setUndecorated(true); AWTUtilities.setWindowOpaque(this, false); super.pack(); } } } 

和testskin.xml:

                             

如上所述删除:

 AWTUtilities.setWindowOpaque(window, false) 

使combobox弹出菜单渲染好,另外为所有样式添加默认背景(在style =“backingStyle”下),例如:

    

至少会使弹出菜单出现,但它仍然没有正确渲染。 我在三个单独的Windows XP虚拟机上试过这个,都遇到了同样的问题。 另外,不要认为我是mentiod这个,但它是在JDK 7上构建的,并且在所有情况下都运行在等效的JRE上。 我自己在Windows 7终极64位体验没有问题,另一个用户使用Windows 7高级64位确实遇到了同样的问题。


一些进展,如果出现以下情况,弹出菜单组件的paint方法将无法调用:

 AWTUtilities.setWindowOpaque(window, false) 

已设定。 手动调用repaint,updateUI,调用’show’方法后重新validation将使弹出菜单呈现正常。 对于设置自定义UI并覆盖’createPopup’方法的combox元素,使用扩展javax.swing.plaf.basic.BasicComboPopup的类,在show上调用repaint / updateUI / revalidate,例如:

  public class ComboPopup extends BasicComboPopup { public ComboPopup( JComboBox combo ) { super(combo); } @Override public void show(Component invoker, int x, int y) { super.show(invoker, x, y); this.updateUI(); } } 

将使combox菜单呈现正常。 但是,由于弹出窗口是在私有方法中创建的,因此我还没有为弹出窗口找到submneu(JMenu)项目的解决方法。 这似乎是一个错误,但如果我做错了可能有人让我知道:)

干杯

乔纳森

我在这里回答了类似的问题。 希望它对找到这个post的其他人有帮助,我也会把我的解决方法放在这里。

基本上,只要你需要一个HeavyWeightPopup就会出现你的问题 – 一个不适合目标窗口的弹出窗口。 解决方法是在显示任何弹出窗口后调用重绘。 只需在启动应用程序时调用以下代码即可。

 PopupFactory.setSharedInstance(new PopupFactory() { @Override public Popup getPopup(Component owner, final Component contents, int x, int y) throws IllegalArgumentException { Popup popup = super.getPopup(owner, contents, x, y); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { contents.repaint(); } }); return popup; } });