【问题标题】:Drawing directly on screen直接在屏幕上绘图
【发布时间】:2011-03-04 02:34:26
【问题描述】:

是否可以在 Java 中直接在屏幕上绘制形状和内容,以便我的桌面保持可见并且我可以单击形状下方的任何内容?我正在使用 Windows XP。谢谢。

【问题讨论】:

  • 你是指桌面屏幕本身还是窗口?

标签: java windows-xp


【解决方案1】:

是的,这是可能的。但这不是一项简单的任务。

如果您正在寻找“桌面小部件”:

请参阅this 和this link* 了解半透明和异形窗户

有关更多实验性 GUI 信息,请参阅 this link。

您可能需要JNA 或JNI 来创建这些窗口/效果,还需要提供“点击”功能。

*需要 Java 6u10。您基本上可以在框架内在中绘制任何您想要的东西,设置链接中提到的属性,并且在您没有绘制(或绘制透明像素)的任何地方都可以看到桌面。

(我会考虑使用与 Java 不同的语言/框架,因为桌面小部件在 Java 中并不容易实现 [甚至可能是 JavaFX?])

【讨论】:

    【解决方案2】:

    我有一个非常奇怪的程序。有一类,DirectPaintingDevice。这里是;解释在代码下面:

    package direct_painting_device;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Toolkit;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.function.Consumer;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public final class DirectPaintingDevice {
        public final Graphics2D graphics;
        private BufferedImage image;
        private final ArrayList<JFrame> frames = new ArrayList<>(0);
        private final ArrayList<Runnable> actions = new ArrayList<>(0);
    
        public DirectPaintingDevice() {
            Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
            this.image = new BufferedImage(screen.width, screen.height,
                    BufferedImage.TYPE_INT_ARGB);
            this.graphics = this.image.createGraphics();
            Color color = this.graphics.getColor();
            this.graphics.setColor(new Color(0, true));
            this.graphics.fillRect(0, 0, screen.width, screen.height);
            this.graphics.setColor(color);
        }
    
        public synchronized void update() {
            this.frames.forEach(JFrame::dispose);
            this.frames.clear();
            ArrayList<Point> done_points = new ArrayList<>(0);
            for (int x = 0; x < this.image.getWidth(); x++) {
                for (int y = 0; y < this.image.getHeight(); y++) {
                    if (this.image.getRGB(x, y) >> 24 == 0
                            || done_points.contains(new Point(x, y))) {
                        continue;
                    }
                    final int cx = x;
                    final int cy = y;
                    int w;
                    for (w = 0; w < this.image.getWidth() - x
                            && this.image.getRGB(x + w, y) >> 24 == this.image
                                    .getRGB(x, y) >> 24; w++) {
                        // Empty loop
                    }
                    int h;
                    outer: for (h = 0; h < this.image.getHeight() - y; h++) {
                        for (int cw = 0; cw < w; cw++) {
                            if (this.image.getRGB(x + cw, h + y) >> 24 != this.image
                                    .getRGB(x, y) >> 24) {
                                break outer;
                            }
                        }
                        for (int i = 0; i < w; i++) {
                            done_points.add(new Point(i + x, h + y));
                        }
                    }
                    final int cw = w;
                    final int ch = h;
                    JFrame frame = new JFrame();
                    frame.setUndecorated(true);
                    frame.setDefaultCloseOperation(0);
                    frame.setSize(w, h);
                    frame.setLocation(x, y);
                    frame.setOpacity((int) (1 - ((double) (this.image.getRGB(x, y) >> 24) / 505)));
                    frame.toFront();
                    frame.setAlwaysOnTop(true);
                    frame.add(new JPanel() {
                        private static final long serialVersionUID = 6246612303574731899L;
    
                        public void paintComponent(Graphics g) {
                            g.drawImage(DirectPaintingDevice.this.image
                                    .getSubimage(cx, cy, cw, ch), 0, 0, null);
                        }
                    });
                    frame.setVisible(true);
                    System.out.println("Created Frame : [" + x + ", " + y + ", "
                            + w + ", " + h + "];");
                    this.frames.add(frame);
                }
            }
            this.actions.forEach(Runnable::run);
        }
    
        public synchronized void allFrames(Consumer<JFrame> action) {
            synchronized (this) {
                this.frames.forEach(action);
            }
        }
    
        public synchronized void exec(Consumer<Graphics2D> action) {
            new Thread(() -> {
                synchronized (DirectPaintingDevice.this) {
                    action.accept(DirectPaintingDevice.this.graphics);
                }
            }).start();
        }
    
        public void onUpdate(Runnable action) {
            this.actions.add(action);
        }
    
        public synchronized void setImage(BufferedImage image) {
            this.image = image;
        }
    
        public static void main(String... args) throws IOException {
            DirectPaintingDevice device = new DirectPaintingDevice();
            device.graphics.setColor(Color.BLACK);
            device.graphics.fillRect(0, 0, 50, 50);
            device.graphics.fillRect(0, 50, 50, 50);
            device.graphics.fillRect(0, 100, 50, 50);
            device.graphics.fillRect(50, 0, 50, 50);
            device.graphics.fillRect(50, 100, 50, 50);
            device.graphics.fillRect(100, 0, 50, 50);
            device.graphics.fillRect(100, 50, 50, 50);
            device.graphics.fillRect(100, 100, 50, 50);
            device.graphics.fillRect(0, 70, 100, 10);
            device.graphics.fillRect(70, 0, 10, 100);
            device.update();
        };
    }
    

    创建一个DirectPaintingDevice,并使用device.graphics... 使用Graphics2D 对象绘制事物。然后,使用device.update(); 更新窗口。它创建了很多矩形 JFrame。

    但是,请记住,此代码非常缓慢且滞后。

    【讨论】:

    • 这是一个答案还是一个新问题?
    • 如果我的原始问题缺少细节,我很抱歉,但我试图创建一个鼠标透明形状,而不是有孔的形状。我不认为孔算作形状的一部分......虽然有趣的黑客;)
    • 我明白了。嗯,孔不算作形状的一部分。这会创建一堆覆盖图形指示的区域的 JFrame,因此任何孔实际上不存在(即它们只是孔,而不是透明的 JFrame)
    • @Martynas 只是另一个注意事项,如果你创建了一个 `JPanel
    • @Martynas 另一个旁注;如果您在某个位置创建JComponent 并从中抛出错误,它将完全透明(甚至JFrame 背景也没有显示!)当然,这是一个相当愚蠢的方法,它会发送垃圾邮件堆栈跟踪不断。它也相当慢。
    猜你喜欢
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2014-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多