java - एयरो(डीडब्ल्यूएम) प्रभावों को ठीक से प्रदर्शित करने के लिए जेफ्रेम में पृष्ठभूमि ड्राइंग को अक्षम करें



swing jframe (1)

महान सवाल

सबसे स्पष्ट जवाब होगा

WindowUtils.setWindowOpaque(this, false);

इससे आप चाहते हैं कि विज़ुअल इफेक्ट देता है, लेकिन दुर्भाग्य से आपको विंडो पर क्लिक करने से रोकता है!

दूसरी बात जो मैंने कोशिश की थी, उस पेंट () विधि को ओवरराइड करना था, जो कि Window.paint() करता है जब opaque ध्वज झूठे पर सेट होता है। उसने कुछ नहीं किया

फिर मैंने प्रतिबिंब का उपयोग करने की कोशिश की Window.opaque को Window.opaque से सेट करने के लिए। Window.opaque को सही Window.opaque से Window.opaque का Window.opaque करने के समान परिणाम दिए गए।

अंत में, मैंने इसे सक्षम करने के लिए जोड़ने की कोशिश की।

Method m = null;
try {
    m = Window.class.getDeclaredMethod("setLayersOpaque", Component.class, Boolean.TYPE);
    m.setAccessible(true);
    m.invoke(null, this, false);
} catch ( Exception e ) {
    //TODO: handle errors correctly
} finally {
    if ( m != null ) {
        m.setAccessible(false);
    }
}

यह काम किया! खिड़की अभी भी माउस घटनाओं के लिए ठीक से जवाब देती है, लेकिन पृष्ठभूमि तैयार नहीं की गई है। ड्राइंग एक बिट ग्लिची है, लेकिन आपको अपने रास्ते पर जाना चाहिए।

जाहिर है यह नाजुक है क्योंकि यह प्रतिबिंब पर निर्भर करता है अगर मैं आप थे, तो मैं क्या Window.setLayersOpaque() पर एक नज़र Window.setLayersOpaque() करता है , और उस तरह की प्रतिलिपि बनाने की कोशिश करता Window.setLayersOpaque() जो प्रतिबिंब पर भरोसा नहीं करता

संपादित करें : setLayersOpaque विधि के निरीक्षण पर, यह वास्तव में पारदर्शी घटकों पर डबल-बफरिंग को अक्षम करने के लिए उबाल हो रहा है। इस विधि को अपने enableAeroEffect() विधि से कॉल करें और आप अपने रास्ते पर हैं:

//original source: Sun, java/awt/Window.java, setLayersOpaque(Component, boolean)
private static void setLayersTransparent(JFrame frame) {
    JRootPane root = frame.getRootPane();
    root.setOpaque(false);
    root.setDoubleBuffered(false);

    Container c = root.getContentPane();
    if (c instanceof JComponent) {
        JComponent content = (JComponent) c;
        content.setOpaque(false);
        content.setDoubleBuffered(false);
    }
    frame.setBackground(new Color(0, 0, 0, 0));
}

मुझे जावा विन्डो पर विंडोज विस्टा / 7 की डीडब्ल्यूएम कार्यक्षमता का उपयोग करने में समस्या हो रही है I मैं अपने फ्रेम की पृष्ठभूमि को एरो शैली का उपयोग करना चाहता हूं ऐसा करने के लिए विंडोज़ एपीआई dwmapi लाइब्रेरी में DwmExtendFrameIntoClientArea समारोह द्वारा प्रदान की dwmapi है। मैंने जेएनए के माध्यम से ठीक से प्रक्रिया को बुलाया है, और यह ऐसा करता है जो करना चाहिए (आप देख सकते हैं कि उदाहरण के लिए जब फ्रेम का आकार बदलता है, अगली बार फिर से रंगना करने से पहले आप इस क्षेत्र में अभी तक पेंट नहीं किए जाने वाले उचित हवाई प्रभाव को देखते हैं, संलग्न छवि देखें)।

लेकिन कहीं (मुझे पता नहीं लगा सकता है कि) एरो प्रभाव से एक पृष्ठभूमि को चित्रित किया जाता है और प्रभाव खो जाता है।

मैंने पहले ही कोशिश की है:

  • false सेट पर अस्पष्टता के साथ एक कस्टम ContentPane का उपयोग करना
  • RootPane और RootPane की अस्पष्टता को झूठी करने के लिए RootPane करना
  • एक Frame का उपयोग किसी JFrame बजाय
  • JFrame / ContentPane का पृष्ठभूमि का रंग काला / पूरी तरह से पारदर्शी सेट करें
  • setLayersOpaque और एक कस्टम संस्करण का उपयोग करें, अधिक विवरण के लिए पहला जवाब देखें

अब तक मैं उस पृष्ठभूमि को हटाने में सफल नहीं हो सका। क्या यह AWT / स्विंग की एक सीमा है? मैं उस पृष्ठभूमि को कैसे हटा सकता हूं या एरो प्रभाव का सही उपयोग कर सकता हूं?

आपकी मदद बहुत ही सराहनिय है।

स्क्रीनशॉट

किसी भी सामग्री के बिना एक फ्रेम का एक स्क्रीनशॉट यहां, रुटपैन, लेयरपेन और कंटैप्टकैन की अस्पष्टता को गलत पर सेट कर रहा है। रीसाइज़िंग करते समय मैंने इसे जल्दी किया आप देख सकते हैं कि जावा पर अभी तक पेंट नहीं किया गया क्षेत्र के लिए प्रभाव ठीक से लागू किया गया है।

http://i55.tinypic.com/v614qo.png (एक नए उपयोगकर्ता के रूप में मैं सीधे छवि पोस्ट नहीं कर सकता ...)

अजीब व्यवहार

आगे की जांच के बाद मैं निम्नलिखित अजीब व्यवहार में आया। यदि विंडो आकार 150x150 है या नीचे सामग्री को पारदर्शी रूप से प्रदर्शित किया जाता है सामान्य विंडो घटकों के लिए यह बहुत ही गंभीर है। यदि आप रंग को ओवरराइड करके सीधे फ्रेम पर paint() विधि सब कुछ अर्द्ध पारदर्शी खींचा जाता है। इसके अतिरिक्त समन्वय प्रणाली थोड़ा सा लगता है, यह प्रतीत होता है कि JFrame का शून्य बिंदु खिड़की के वास्तविक शून्य बिंदु पर सेट है। इस प्रकार स्विंग उन हिस्सों में पेंट करने की कोशिश करता है जहां वास्तव में खिड़की सीमा स्थित है, जो निश्चित रूप से दिखाई नहीं दे रही है।

यह स्क्रीनशॉट देखें: http://d-gfx.kognetwork.ch/java_aero_bug.png

उदाहरण कोड

यह कोड मैं उपयोग करता हूं।

jna.jar और platform.jar आवश्यकता jna.jar जेएनए होमपेज से उपलब्ध है

import com.sun.jna.Function;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;

public class AeroFrame extends JFrame {

    public AeroFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label = new JLabel("Testlabel");
        label.setOpaque(false);

        add(label);

        pack();

        enableAeroEffect();
    }

    private void enableAeroEffect() {
        NativeLibrary dwmapi = NativeLibrary.getInstance("dwmapi");
        HWND aeroFrameHWND = new HWND(Native.getWindowPointer(this));
        MARGINS margins = new MARGINS();
        margins.cxLeftWidth = -1;
        margins.cxRightWidth = -1;
        margins.cyBottomHeight = -1;
        margins.cyTopHeight = -1;
        //DwmExtendFrameIntoClientArea(HWND hWnd, MARGINS *pMarInset)
        //http://msdn.microsoft.com/en-us/library/aa969512%28v=VS.85%29.aspx
        Function extendFrameIntoClientArea = dwmapi.getFunction("DwmExtendFrameIntoClientArea");
        HRESULT result = (HRESULT) extendFrameIntoClientArea.invoke(HRESULT.class,
                new Object[] { aeroFrameHWND, margins});
        if(result.intValue()!=0)
            System.err.println("Call to DwmExtendFrameIntoClientArea failed.");
    }

    /**
     * http://msdn.microsoft.com/en-us/library/bb773244%28v=VS.85%29.aspx
     */
    public class MARGINS extends Structure implements Structure.ByReference {
            public int cxLeftWidth;
            public int cxRightWidth;
            public int cyTopHeight;
            public int cyBottomHeight;
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            JFrame.setDefaultLookAndFeelDecorated(true);

        } catch (Exception e) {
            e.printStackTrace();
        }
        new AeroFrame().setVisible(true);
    }

}