Java的:制作一个窗口的点击(包括文字/图片)(Java: Making a window cli

2019-06-25 19:14发布

我想在Java中创建一个叠加层是透明的总在最前面 ,而我可以点击通过 。 我已经发现了一些类似的 帖子关于这个问题,但即使跟随他们的答案后,我有一个问题。

我的问题是使整个窗口的点击。 我并没有使其与一个JFrame工作的任何问题,但一旦我添加任何成分给它(的JLabel或ImagePanel) 的点击属性不延续到他们。

正如我希望有一个背景图片为我的应用这基本上使得我没用看到如何,每当我点击文字/图像覆盖区域内的窗口得到集中的代码。

在我告诉代码我使用我首先要参考这些 线程基本上描述正是我想要的东西,除了在C#。

我的目标是创建一个透明的PNG图像叠加和顶部,将关键事件改变一些文字。 如果使用的JFrame或任何其他库无所谓。 我只需要它与Windows兼容。

我也想提一提,我已经得到了Java的一些经验,但在使用的JFrame是一个新手。

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import com.sun.jna.platform.WindowUtils;


public class Overlay {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Overlay Window");
        frame.setUndecorated(true);
        frame.setAlwaysOnTop(true);
        frame.getRootPane().putClientProperty("apple.awt.draggableWindowBackground", false);
        frame.setLocation(400, 400);
        frame.getContentPane().setLayout(new java.awt.BorderLayout());

        JLabel textLabel = new JLabel("I'm a label in the window", SwingConstants.CENTER);
        frame.getContentPane().add(textLabel, BorderLayout.CENTER); 
        frame.pack();

        System.setProperty("sun.java2d.noddraw", "true");
        WindowUtils.setWindowTransparent(frame, true);
        WindowUtils.setWindowAlpha(frame, 1.0f);

        //Using AWTUtilities gives the same result as WindowUtils
        //AWTUtilities.setWindowOpaque(frame, false);
        //AWTUtilities.setWindowOpacity(frame, 1.0f);

        frame.setVisible(true);
    }
}

请注意,这个问题是不是在聚焦窗口 (虽然这是问题的结果),但有关的JLabel和ImagePanel不是的点击

Answer 1:

与具有窗口的问题“通过点击”是,它在系统级处理的,标准API的范围之内。 这意味着,任何编写的代码,使窗口的“点击通过”取决于系统。 话虽这么说,完成这个Windows上的过程相当简单。

在Windows 2000及更高版本,通过设置标志WS_EX_LAYERED和WS_EX_TRANSPARENT一个窗口,窗口届时将通过点击。 实施例的代码使用JNA来实现:

public static void main(String[] args) {
    Window w = new Window(null);

    w.add(new JComponent() {
        /**
         * This will draw a black cross on screen.
         */
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(0, getHeight() / 2 - 10, getWidth(), 20);
            g.fillRect(getWidth() / 2 - 10, 0, 20, getHeight());
        }

        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }
    });
    w.pack();
    w.setLocationRelativeTo(null);
    w.setVisible(true);
    w.setAlwaysOnTop(true);
    /**
     * This sets the background of the window to be transparent.
     */
    AWTUtilities.setWindowOpaque(w, false);
    setTransparent(w);
}

private static void setTransparent(Component w) {
    WinDef.HWND hwnd = getHWnd(w);
    int wl = User32.INSTANCE.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
    wl = wl | WinUser.WS_EX_LAYERED | WinUser.WS_EX_TRANSPARENT;
    User32.INSTANCE.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, wl);
}

/**
 * Get the window handle from the OS
 */
private static HWND getHWnd(Component w) {
    HWND hwnd = new HWND();
    hwnd.setPointer(Native.getComponentPointer(w));
    return hwnd;
}


Answer 2:

为什么不利用现有JLayeredPane ? 此博客张贴演示将在JFrame各种各样的叠加,包括文本,图像和动态绘制像素。



Answer 3:

我试图让全“事件透明”(点击率,你称呼它)窗口,但似乎对招一些本地的限制。

检查该窗口例如:

public static void main ( String[] args )
{
    Window w = new Window ( null );

    w.add ( new JComponent ()
    {
        protected void paintComponent ( Graphics g )
        {
            g.setColor ( Color.BLACK );
            g.fillRect ( 0, getHeight () / 2 - 10, getWidth (), 20 );
            g.fillRect ( getWidth () / 2 - 10, 0, 20, getHeight () );
        }

        public Dimension getPreferredSize ()
        {
            return new Dimension ( 100, 100 );
        }

        public boolean contains ( int x, int y )
        {
            return false;
        }
    } );

    AWTUtilities.setWindowOpaque ( w, false );
    AWTUtilities.setWindowOpacity ( w, 0.5f );

    w.pack ();
    w.setLocationRelativeTo ( null );
    w.setVisible ( true );
}

窗口和组件没有任何:

  1. 鼠标监听器
  2. 鼠标移动侦听
  3. 鼠标滚轮侦听
  4. 主要听众

此外,该组件应忽略任何鼠标事件,即使有任何监听器由于改进contains方法。

正如你所看到的 - 在没有什么是在组件上绘制的区域是事件透明,但填充区域是没有的。 Unluckly我没有找到任何解决办法来改变这种行为。 似乎有些“低级”的Java方法是阻塞的事件。

而这仅仅是一个基本的基于JComponent的-例子。 我甚至不说的像标签,按钮等可能有自己的事件侦听器,这可能阻止事件更复杂的Swing组件。



文章来源: Java: Making a window click-through (including text/images)