Java Swing:如何获取JFrame像素的颜色

我正在尝试为(x,y)组件的选定像素获取Swing JFrame的颜色。

例如,我想知道的给定的颜色JFrame在他们的(0,0)点。

原因是我的组件是一个部分透明的覆盖层,在JPanel下面。对于不透明的像素,鼠标事件应由叠加层处理。对于透明像素,应将鼠标事件转发到JPanel下方。

这是这样做的方法吗?

回答:

我想说(希望这样做会带来更好的性能),也许,如果您愿意采用这种Image方法,则最好创建一个尺寸为1x1像素的图像,然后转换其创建的图形以匹配所请求的图形点。并将此图像重新用于相同Component(甚至GraphicsConfiguration)的后续采样。

我通过创建以下方法进行了一些性能测试:

  1. 所谓的一种方法,getColorAtClipped它设置的创建剪辑Graphics的的Image要绘制所以并不是所有操作都有。
  2. 一种称为的方法getColorAtRelocation,该方法将组件的位置临时设置在需要采样的位置,然后(实际上使其更快)创建尺寸为1x1的图像并在其上绘制父对象。尽管此方法对于Swing而言并不是真正的线程安全方法,因为它需要设置Component来回的位置。它还要求printAll父级Container,这意味着Component要绘制更多。
  3. 然后调用一种方法getColorAtTranslation,该方法创建一个1x1图像并转换其Graphics实例,以便所需的位置实际上将绘制在(0,0)处,这是图像中真正的唯一像素。事实证明,对于这前三种方法,该方法是最快的。
  4. 那么,为什么不为以后的样本重用相同的资源呢?…这导致我进入最终方法:一个包含所有参与样本的必需资源的类:ComponentColorSampler在以下代码中调用的一个类

回答:

本节中的代码用于测试上述方法的性能。如果不正确,请在评论中让我知道,但是请注意,我对每种方法进行了大约300万次采样,以期避免附带的延迟。测试方法的每百万个样本中,我会打印一些时间,然后重新启动该过程以测试另外一百万个,最多3个。

import java.awt.Color;

import java.awt.Component;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Point;

import java.awt.image.BufferedImage;

import java.lang.reflect.InvocationTargetException;

import java.util.Objects;

import java.util.function.IntBinaryOperator;

import java.util.function.Supplier;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.SwingUtilities;

public class Main {

public static Color getColorAtClipped(final Component comp, final Point p) {

final BufferedImage bimg = comp.getGraphicsConfiguration().createCompatibleImage(comp.getWidth(), comp.getHeight());

final Graphics2D g2d = (Graphics2D) bimg.createGraphics();

g2d.setClip(p.x, p.y, 1, 1);

comp.printAll(g2d);

g2d.dispose();

final Color c = new Color(bimg.getRGB(p.x, p.y), true);

bimg.flush();

return c;

}

public static Color getColorAtRelocation(final Component comp, final Point p) {

final Point loc = comp.getLocation();

final BufferedImage bimg = comp.getGraphicsConfiguration().createCompatibleImage(1, 1);

comp.setLocation(loc.x - p.x, loc.y - p.y);

final Graphics2D g2d = (Graphics2D) bimg.createGraphics();

//g2d.setClip(0, 0, 1, 1);

comp.getParent().printAll(g2d);

comp.setLocation(loc);

g2d.dispose();

final Color c = new Color(bimg.getRGB(0, 0), true);

bimg.flush();

return c;

}

public static Color getColorAtTranslation(final Component comp, final Point p) {

final BufferedImage bimg = comp.getGraphicsConfiguration().createCompatibleImage(1, 1);

final Graphics2D g2d = (Graphics2D) bimg.createGraphics();

g2d.translate(-p.x, -p.y);

//g2d.setClip(0, 0, 1, 1);

comp.printAll(g2d);

g2d.dispose();

final Color c = new Color(bimg.getRGB(0, 0), true);

bimg.flush();

return c;

}

public static class ComponentColorSampler<C extends Component> implements AutoCloseable, IntBinaryOperator, Supplier<C> {

private final C comp;

private final BufferedImage bimg;

private final Graphics2D g2d;

private int x, y;

public ComponentColorSampler(final C comp) {

this.comp = Objects.requireNonNull(comp);

bimg = comp.getGraphicsConfiguration().createCompatibleImage(1, 1);

g2d = bimg.createGraphics();

//g2d.setClip(0, 0, 1, 1);

x = y = 0;

}

@Override

public C get() {

return comp;

}

@Override

public int applyAsInt(final int x, final int y) {

g2d.clearRect(0, 0, 1, 1);

g2d.translate(this.x - x, this.y - y);

this.x = x;

this.y = y;

comp.printAll(g2d);

return bimg.getRGB(0, 0);

}

public Color sample(final int x, final int y) {

return new Color(applyAsInt(x, y), true);

}

@Override

public void close() {

g2d.dispose();

bimg.flush();

}

}

public static class DrawPanel extends JPanel {

private final int x, y;

private Color c;

public DrawPanel(final int x, final int y) {

this.x = x;

this.y = y;

c = Color.BLUE;

}

@Override

protected void paintComponent(final Graphics g) {

super.paintComponent(g);

g.setColor(c);

g.fillRect(x, y, 1, 1);

}

public void setColor(final Color c) {

this.c = Objects.requireNonNull(c);

paintImmediately(0, 0, getWidth(), getHeight()); //Not sure yet.

repaint(); //Just to be sure now.

}

}

//@SuppressWarnings("SleepWhileInLoop")

public static boolean checkValid(final DrawPanel dp, final Supplier<Color> sampler) throws InterruptedException, InvocationTargetException {

for (final Color c: new Color[]{Color.BLUE, Color.RED, Color.BLACK, Color.WHITE, Color.BLACK, Color.CYAN}) {

SwingUtilities.invokeAndWait(() -> dp.setColor(c));

Thread.sleep(250); //Let it some time to change (not sure if needed).

if (!Objects.equals(c, sampler.get()))

return false;

}

return true;

}

public static long checkTime(final Supplier<Color> sampler) {

final long start = System.currentTimeMillis();

for (int i = 0; i < 1000000; ++i)

sampler.get();

return System.currentTimeMillis() - start;

}

public static void main(final String[] args) throws InterruptedException, InvocationTargetException {

final Point p = new Point(100, 100);

final DrawPanel contents = new DrawPanel(p.x, p.y);

contents.setPreferredSize(new Dimension(200, 200));

final JFrame frame = new JFrame("Printed!");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.getContentPane().add(contents);

frame.pack();

frame.setLocationRelativeTo(null);

frame.setResizable(false);

frame.setVisible(true);

final ComponentColorSampler<Component> sampler = new ComponentColorSampler<>(contents);

final Supplier<Color> clipped = () -> getColorAtClipped(contents, p),

relocation = () -> getColorAtRelocation(contents, p),

translation = () -> getColorAtTranslation(contents, p),

samplerSampler = () -> sampler.sample(p.x, p.y);

System.out.println("#### Validity checks...");

for (int i = 0; i < 3; ++i) {

System.out.println("Batch " + (i + 1) + ':');

System.out.println("> Clipped: " + checkValid(contents, clipped) + '.');

System.out.println("> Relocation: " + checkValid(contents, relocation) + '.');

System.out.println("> Translation: " + checkValid(contents, translation) + '.');

System.out.println("> Sampler: " + checkValid(contents, samplerSampler) + '.');

}

System.out.println("#### Timings...");

for (int i = 0; i < 3; ++i) {

System.out.println("Batch " + (i + 1) + ':');

System.out.println("> Clipped: " + checkTime(clipped) + "ms.");

System.out.println("> Relocation: " + checkTime(relocation) + "ms.");

System.out.println("> Translation: " + checkTime(translation) + "ms.");

System.out.println("> Sampler: " + checkTime(samplerSampler) + "ms.");

}

System.out.println("#### Done.");

}

}

回答:

程序输出:

#### Validity checks...

Batch 1:

> Clipped: true.

> Relocation: true.

> Translation: true.

> Sampler: true.

Batch 2:

> Clipped: true.

> Relocation: true.

> Translation: true.

> Sampler: true.

Batch 3:

> Clipped: true.

> Relocation: true.

> Translation: true.

> Sampler: true.

#### Timings...

Batch 1:

> Clipped: 34668ms.

> Relocation: 22737ms.

> Translation: 5416ms.

> Sampler: 1152ms.

Batch 2:

> Clipped: 38521ms.

> Relocation: 22805ms.

> Translation: 5451ms.

> Sampler: 1156ms.

Batch 3:

> Clipped: 38275ms.

> Relocation: 22864ms.

> Translation: 5415ms.

> Sampler: 1163ms.

#### Done.

因此,对于一百万个样本,第一种方法大约需要37秒,第二种方法大约需要22秒,第三种方法大约需要5秒,最后一种方法恰好超过1秒(对于一百万个样本)。ComponentColorSampler在这些测试中最快的实现也是如此(每毫秒约865个样本),并且可以在任何测试上运行Component。有效性检查只是为了稍微验证所采样的颜色是否具有正确的值。

:这些测试不是Swing /线程安全的,但是指出了正确使用它们(例如,在事件调度线程上执行采样)的性能。

以上是 Java Swing:如何获取JFrame像素的颜色 的全部内容, 来源链接: utcz.com/qa/400623.html

回到顶部