本文介绍了使用AWTUtilities.setWindowOpaque(window,false)使用合成器L& F的JFrame中的JPopupMenu没有出现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This one has me quite puzzled. Basically I am developing a multi window application using transparent shaped windows using a custom Synth L&F. Parts of the application invoke JFrame/JDialog components from the parent frame. Within these components I have pop up menus and comboboxes, the problem is that some people using the applications experience the pop up menus not appearing when invoked. There are no exceptions and the code executes fine including for popup menus 'show' method.

我试图将这一点归结为操作系统细节而没有太大的乐趣,除此之外在mac OSX上似乎不是问题。有些像我这样的Windows用户没有遇到任何问题,有些人会这样做....

I have tried to nail this down to OS specifics without much joy, apart from there doesn't seem to be an issue on mac OSX. Some windows users such as myself experience no problems, others do....

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

Also I have tracked down the offending line of code which sets the window opacity:

AWTUtilities.setWindowOpaque(window, false)

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

If I remove this LOC then the popup windows appear fine. In addition replacing this LOC with :

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

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

produces the same issue. Another thing is that if I use the default L&F the popups render ok.

只是为了确认两个 JFrame 和 JDialog 组件,只是想知道是否有其他人遇到过这个问题或者可能指出我可能的原因。

Just to confirm the issue is the same for both JFrame and JDialog components, and was just wondering if anybody else has either come across this issue or could point me in the direction of the possible cause.

干杯

要重现的测试来源:

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:

and the testskin.xml:

<synth>

    <style id="backingStyle">
        <opaque value="true"/>
        <font name="Dialog" size="14"/>
    </style>
    <bind style="backingStyle" type="region" key=".*"/>

    <style id="ComboBox List Renderer">
        <opaque value="true"/>
        <state value="ENABLED">
            <color type="TEXT_FOREGROUND" value="#000000"/>
        </state>
        <state value="DISABLED">
            <color type="TEXT_FOREGROUND" value="#999999"/>
        </state>
        <state value="SELECTED">
            <color type="TEXT_FOREGROUND" value="#CC6600"/>
            <color type="TEXT_BACKGROUND" value="#FFEEDD"/>
        </state>
    </style>
    <bind style="ComboBox List Renderer" type="name" key="ComboBox.listRenderer" />

    <style id="Combo Box">
        <property key="ComboBox.showPopupOnNavigation" type="boolean" value="true"/>
        <state>
            <color value="#D8D987" type="BACKGROUND"/>
        </state>
    </style>
    <bind style="Combo Box" type="region" key="ComboBox" />

</synth>

如上所述,删除:

AWTUtilities.setWindowOpaque(window, false)

使组合框弹出菜单渲染确定,另外为所有样式添加默认背景(在style =backingStyle下),例如:

makes the combobox pop up menu render ok, in addition adding a default background to all styles (under style="backingStyle") e.g.:

<state>
   <color value="#D8D987" type="BACKGROUND"/>
</state>

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

will at least make the pop menu appear, however it is still not renderd properly. I have tried this on three seperate windows xp virtual machines, all experience the same issues. In addition do not think I mentiod this but it was built on JDK 7, and run on equivalent JRE in all cases. I myself on windows 7 ultimate 64 bit experience no problems, another user using windows 7 premium 64 bit does experience the same issues.

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

Some progress, The paint method for the pop up menu components fails to invoke if:

AWTUtilities.setWindowOpaque(window, false)

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

is set. Manually calling repaint, updateUI, revalidate after calling the 'show' method will make the pop up menu render ok. For combox elements setting a custom UI and overiding the 'createPopup' method, with a class extending javax.swing.plaf.basic.BasicComboPopup that invokes repaint/updateUI/revalidate on show e.g. :

 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)项目的解决方法。这似乎是一个错误,但如果我做错了什么可能有人让我知道:)

will make the combox menu render ok. However I am yet to find a workaround for submneu (JMenu) items for a popup since the popup is created within a private method. This seems like a bug, but if I am doing something wrong could someone let me know :)

干杯

Jonathan

推荐答案

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

I answered a similar question here. Hoping it's helpful to others who find this thread, I'll put my workaround here too.

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

Basically your problem is presenting whenever you need a HeavyWeightPopup -- a popup that doesn't fit within the target window. The workaround is to invoke a repaint after any popup displays. Simply invoke the following code when you launch your application.

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;
    }
});

这篇关于使用AWTUtilities.setWindowOpaque(window,false)使用合成器L&amp; F的JFrame中的JPopupMenu没有出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 12:29