Java setting background from JAR and making it transparent

后端 未结 2 1786
醉梦人生
醉梦人生 2021-01-14 17:17

Be patient I\'m still a beginner, no rude comments please.

So the goal of this question is so I learn how to set the background of my already transparent JFrame to b

相关标签:
2条回答
  • 2021-01-14 17:59

    My first guess in "SystemInfo/black.png" can't be referenced as File because it's an embedded/internal resource, residing within your application Jar.

    In order to read it (via ImageIO) you will need to use something more like...

    ImageIO.read(getClass().getResource("SystemInfo/black.png"))
    

    Instead.

    Secondly, blurring the image probably won't result in the effect you are looking for, as it won't have any effect of the how the content behind your window is actually painted.

    Instead, you will need to capture the section of the screen below your window and blur that.

    You can achieve this by using Robot, but will need to make the window invisible when you grab the screen shot.

    It will also not be a "live" update.

    0 讨论(0)
  • 2021-01-14 18:19

    Java can blur an image using the code you have - the problem is that Java does not see the image 'underneath' your window so it will be blurring a blank image.

    Window translucency is achieved through the native operating system. To get a blur effect, I don't see an easy way. And by that I mean it's going to be pretty darn difficult. A couple of things you might try:

    • Use java.awt.Robot to capture what's underneath the Window, then use blur on that. Pitfalls: you need to hide your window for a few milliseconds while taking the capture which might be noticeable by the user, and you need to do this every time the background changes which will probably involve polling.
    • Use native code or at least some calls to native libraries through JNA. You'll need to do this for each operating system you want to support. For Mac, this might start you off. For Windows, maybe start looking at the DWM API, maybe something with DwmEnableBlurBehindWindow can work.

    But ultimately, given that these techniques are pretty advanced and you said you are a beginner (though you managed with the blurring using Image I/O OK) you might just want to settle with translucent windows.


    (Edit: add example for Windows)

    For Windows, you can use JNA to call DwmEnableBlurBehindWindow and it works great. You must have Java 7 or later for this to work.

    Example:

    package dwmtest;
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.GradientPaint;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Paint;
    import java.util.Arrays;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    
    import com.sun.jna.Native;
    import com.sun.jna.Structure;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.ptr.IntByReference;
    import com.sun.jna.win32.StdCallLibrary;
    import com.sun.jna.win32.W32APIOptions;
    
    public class DwmWindow extends JFrame
    {
        public static void main(String... args)
        throws Exception
        {
            JFrame.setDefaultLookAndFeelDecorated(true);
    
            DwmWindow f = new DwmWindow();
            f.setSize(600, 500);
            f.setBackground(new Color(0,0,0,0));
            f.setTitle("Hello");
            TranslucentPanel panel = new TranslucentPanel();
            panel.setLayout(new BorderLayout());
            JLabel label = new JLabel("My background is blurry!");
            label.setFont(new Font("Dialog", Font.BOLD, 48));
            panel.add(label, BorderLayout.CENTER);
            f.add(panel);
            f.setDefaultCloseOperation(EXIT_ON_CLOSE);
            f.setVisible(true);
    
            HWND hwnd = new HWND(Native.getWindowPointer(f));
            Dwmapi.DWM_BLURBEHIND pBlurBehind = new Dwmapi.DWM_BLURBEHIND();
            pBlurBehind.dwFlags = Dwmapi.DWM_BB_ENABLE;
            pBlurBehind.fEnable = true;
            pBlurBehind.fTransitionOnMaximized = false;
            Dwmapi.INSTANCE.DwmEnableBlurBehindWindow(hwnd, pBlurBehind);
        }
    
        private static class TranslucentPanel extends JPanel
        {
            @Override
            protected void paintComponent(Graphics g) 
            {
                if (g instanceof Graphics2D) {
                    final int R = 240;
                    final int G = 240;
                    final int B = 240;
    
                    Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0), 0.0f, getHeight(), new Color(R, G, B, 255), true);
                    Graphics2D g2d = (Graphics2D)g;
                    g2d.setPaint(p);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                }
            }
        }
    
        public static interface Dwmapi extends StdCallLibrary
        {
            Dwmapi INSTANCE = (Dwmapi)Native.loadLibrary("Dwmapi", Dwmapi.class, W32APIOptions.UNICODE_OPTIONS);
    
            int DWM_BB_ENABLE = 0x00000001;
    
            boolean DwmEnableBlurBehindWindow(HWND hWnd, DWM_BLURBEHIND pBlurBehind);
    
            public static class DWM_BLURBEHIND extends Structure 
            {
                public int dwFlags;
                public boolean fEnable;
                public IntByReference hRgnBlur;
                public boolean fTransitionOnMaximized;
    
                @Override
                protected List getFieldOrder() 
                {
                    return Arrays.asList("dwFlags", "fEnable", "hRgnBlur", "fTransitionOnMaximized");
                }
            }
        }
    }
    

    If you have an Aero-capable Windows machine you will get a blurry background:

    Blurry Java window

    If you don't have Aero capability it will fall back to just being translucent without the blurriness.

    The alpha values of the panel's background control which areas are see through and which not. A more sophisticated background painted in the panel could create effects like holes or other patterns. If you need a uniformly translucent background instead of the gradient effect, use a simple background color with an appropriate alpha value instead.

    0 讨论(0)
提交回复
热议问题