簡體   English   中英

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

[英]JPopupMenu in JFrame using AWTUtilities.setWindowOpaque(window, false) using synth L&F not appearing

這個讓我頗為困惑。 基本上,我正在使用自定義Synth L&F使用透明形狀的窗口來開發多窗口應用程序。 應用程序的JDialog部分從父框架調用JFrame / JDialog組件。 在這些組件中,我有彈出菜單和組合框,問題是使用該應用程序的某些人會遇到在調用時沒有出現的彈出菜單。 沒有例外,代碼執行良好,包括彈出菜單“ show”方法。

除了Mac OSX上似乎沒有問題之外,我試圖將其固定在特定於OS的細節上。 某些Windows用戶(例如本人)不會遇到任何問題,其他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:

<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”下)添加默認背景,例如:

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

至少會顯示彈出菜單,但是仍然無法正確呈現。 我已經在三個獨立的Windows XP虛擬機上嘗試了此方法,但都遇到了相同的問題。 另外,我認為我沒有提到它,但是它是基於JDK 7構建的,並且在所有情況下都可以在等效的JRE上運行。 我本人在Windows 7 Ultimate 64位上沒有遇到任何問題,另一個使用Windows 7 Premium 64位的用戶確實遇到了同樣的問題。


一些進展,如果出現以下情況,則彈出菜單組件的paint方法無法調用:

AWTUtilities.setWindowOpaque(window, false) 

被設置。 在調用“ show”方法后手動調用repaint,updateUI,revalidate將使彈出菜單呈現正常。 對於combox元素,設置自定義UI並覆蓋“ createPopup”方法,並帶有擴展javax.swing.plaf.basic.BasicComboPopup的類,該類在顯示時調用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)項的解決方法。 這似乎是一個錯誤,但是如果我做錯了什么,可以讓我知道:)

干杯

喬納森

在這里回答了類似的問題。 希望對發現此線程的其他人有所幫助,我也將解決方法放在這里。

基本上,每當您需要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;
    }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM