【问题标题】:Java robot class - getting Pixel color after they're paintedJava机器人类 - 绘制后获取像素颜色
【发布时间】:2016-06-28 13:56:33
【问题描述】:

我需要为我的小 ms 绘画应用创建一个 colorPicker 工具。 我最初询问如何从我的 Graphics 2D 实现切换到 Graphics2D-->BufferedImage 之一,(然后很容易获得像素),但有人建议我将像素颜色视为机器人类。

首先,这是我的 MCEVE:注意。它不能是单个类,它不会保存。

import java.awt.*;
import javax.swing.*;

public class Runner {

public static void main(String[] args){

    JFrame Maiframe = new JFrame("Paint");
    Canvas DrawingBoard = new Canvas();
    Maiframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Maiframe.setSize(700, 500);
    Maiframe.add(DrawingBoard);
    Maiframe.setVisible(true);

  }

}



import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;


public class Canvas extends JPanel {

public int xp;  //present x
public int yp;  //present y
public int xo;  //old x
public int yo;  //old y      (Drawing from starting to new point as mouse drags)

public Canvas(){

    super();

    addMouseListener(new MouseAdapter() {   

        @Override
        public void mouseClicked(MouseEvent e) {   
            xo = e.getX();
            yo = e.getY();
            Color col = RGBFinder();
            System.out.println("RGB : Red =" + col.getRed() + "Green" +  col.getGreen() + "Blue" + col.getRed());
        }
    });


    addMouseMotionListener(new MouseMotionAdapter() {  //get coords as mouse drags
        @Override
        public void mouseDragged(MouseEvent e) {

            xp = e.getX();
            yp = e.getY();
            if(SwingUtilities.isLeftMouseButton(e))
            repaint();  //call paintcomponent

        }

        public void mouseMoved(MouseEvent e1){  //keep trak of coords when mouse is not dragging

            xo = e1.getX();
            yo = e1.getY();     
        }
    });

}

public void draw(int x, int y, Graphics g){   //draw the line

    if(xo != 0) 
    g.drawLine(xo, yo, x, y);

    xo = x;    //old x is now present x and so on
    yo = y;     
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    draw(xp, yp, g);    
   }
}

public Color RGBFinder(){

    try{
        robot = new Robot();
    }
    catch(AWTException e){

        System.out.println("Could not create color picker robot");
    }

    PointerInfo pi = MouseInfo.getPointerInfo();
    Point p = pi.getLocation();
    Color pixelColor = robot.getPixelColor(p.x, p.y);

    //also tried robot.getPixelColor(p.getX(), p.getY());
    //also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)

    return pixelColor;

}

而且效果很好。

当鼠标点击时,我需要实现一些东西来获取任何像素的颜色。

我这样做了:(将此方法添加到 Canvas,并从鼠标点击器侦听器中调用它)

public Color RGBFinder(){

    try{
        robot = new Robot();
    }
    catch(AWTException e){

        System.out.println("Could not create color picker robot");
    }

    PointerInfo pi = MouseInfo.getPointerInfo();
    Point p = pi.getLocation();
    Color pixelColor = robot.getPixelColor(p.x, p.y);

    //also tried robot.getPixelColor(p.getX(), p.getY());
    //also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)

    return pixelColor;

}

调用示例:

//replace old mouseListener with this

    addMouseListener(new MouseAdapter() {   

        @Override
        public void mouseClicked(MouseEvent e) {   
            xo = e.getX();
            yo = e.getY();
            Color col = RGBFinder();
            System.out.println(" da tela Red =" + col.getRed() + "Green" +  col.getGreen() + "Blue" + col.getRed());
        }
    });

不幸的是,从这个实现中我得到了未定义的行为。读取的颜色始终为 255、255、255。如果我为孔板着色,那么 10 次中有 9 次正确,但在某些区域仍然丢失。

我也尝试过使用 robot#screenCap 将整个内容包装到 bufferedImage 中,但这甚至无法远程工作。

我在这里做错了什么?

非常感谢。

编辑1:

在绘制第二条线后如何在屏幕上保留一条线存在疑问。我会提供截图:

NBB。之所以可行,是因为 Canvas 的实例是在 JFrame 内部创建到 Runnable 中的,因此可以保存更改,从而避免了对形状和数组列表的需要。

我还将添加打印错误 RGB 结果的代码的完整版本,请记住,这不会按原样保存行。请参考上面两个单独的类进行测试。

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;


public class Canvas extends JPanel{

public int xp;  //present x
public int yp;  //present y
public int xo;  //old x
public int yo;  //old y      (Drawing from starting to new point as mouse drags)
public Robot robot;

public static void main(String[] args){

    JFrame Maiframe = new JFrame("Paint");
    Canvas DrawingBoard = new Canvas();
    Maiframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Maiframe.setSize(700, 500);
    Maiframe.add(DrawingBoard);
    Maiframe.setVisible(true);

  }

public Canvas(){

    super();

            addMouseListener(new MouseAdapter() {   

        @Override
        public void mouseClicked(MouseEvent e) {   
            xo = e.getX();
            yo = e.getY();
            Color col = RGBFinder();
            System.out.println("RGB --> Red =" + col.getRed() + "Green" +  col.getGreen() + "Blue" + col.getRed());
        }
    });

    addMouseMotionListener(new MouseMotionAdapter() {  //get coords as mouse drags
        @Override
        public void mouseDragged(MouseEvent e) {

            xp = e.getX();
            yp = e.getY();
            if(SwingUtilities.isLeftMouseButton(e))
            repaint();  //call paintcomponent

        }

        public void mouseMoved(MouseEvent e1){  //keep trak of coords when mouse is not dragging

            xo = e1.getX();
            yo = e1.getY();     
        }
    });

}

public void draw(int x, int y, Graphics g){   //draw the line

    if(xo != 0) 
    g.drawLine(xo, yo, x, y);

    xo = x;    //old x is now present x and so on
    yo = y;     
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    draw(xp, yp, g);    
   }

 public Color RGBFinder(){

    try{
        robot = new Robot();
    }
    catch(AWTException e){

        System.out.println("Could not create color picker robot");
    }

    PointerInfo pi = MouseInfo.getPointerInfo();
    Point p = pi.getLocation();
    Color pixelColor = robot.getPixelColor(p.x, p.y);

    //also tried robot.getPixelColor(p.getX(), p.getY());
    //also tried to pass coordinates from listener to RGBFinder, and use those, no luck. (event.getX() ...)

    return pixelColor;

 }
}

【问题讨论】:

  • 我删除了robot 标签,因为你在谈论一些Java 类而不是物理机器人:) 除此之外,你是否检查了正确的坐标被发送到robot?您是否检查过PointerInfo 使用的是哪个坐标系?如果您使用了错误的坐标系,您的位置可能在画布/面板之外,从而返回错误的值。
  • 是的,我有。坐标是正确的。非常感谢您的阅读和帮助。
  • 变量名不应以大写字符开头。不要称你为“画布”类。这是一个 AWT 类名,令人困惑。使用更好的描述性类名。
  • First of all, here's my MCVE: - 这不是 MCVE。代码应该在一个类文件中,我们可以复制/粘贴/编译/执行。
  • 我的班级名称不是 Canvas,我从意大利语翻译了代码以使其难以理解,这是我找到的最接近的东西。很抱歉,这已经离 MCVE 很近了,我还不具备将所有内容放在同一个类中的知识,如果你有时间,请创建单独的文件。无论如何,非常感谢您的帮助。

标签: java swing graphics rgb awtrobot


【解决方案1】:

我的小 ms 绘画应用程序

嗯,它不是一个绘画应用程序。它所做的只是画一条线。每当您尝试绘制第二条线时,第一条线将被删除。

因此,您需要做的第一步是决定您希望绘画的工作方式。有两种常见的方法:

  1. 将要绘制的对象存储在ArrayList 中,然后paintComponent(...) 方法将绘制列表中的每个对象。

  2. 直接绘制到BufferedImage,然后paintComponent(...)方法可以只绘制BufferedImage

查看Custom Painting Approaches 了解这两种方法的工作示例,并给出使用每种方法的优缺点。

有人建议我将像素颜色视为机器人类

这取决于您要使用哪种绘画方法。

如果您使用Draw on Component 方法,那么您将使用MouseInfoRobot 来获取像素颜色:

PointerInfo pi = MouseInfo.getPointerInfo();
Point p = pi.getLocation();
System.out.println( robot.getPixelColor(p.x, p.y) );

如果您使用Draw on Image 方法,那么您将从BufferedImage 获取像素颜色:

int rgb = bufferedImage.getRGB(mouseEvent.getX(), mouseEvent.getY());
Color color = new Color( rgb );
System.out.println( color );

最终更新

您还没有发布 SSCCE。您发布的代码不会画线。即使它确实画了一条线,您如何期望我们(准确地)单击单个像素线。

SSCCE 的目的是展示您所询问的概念。您正在询问如何在面板上获取像素的颜色。绘画如何进入面板与问题无关,因此绘画代码应尽可能简单。

以下是正确的 SSCCE。注意:

  1. createAndShowGUI()main() 方法对于所有 SSCCE 都是相同的。不同之处在于 `DrawingPanel 代码/类将更改以展示您的问题。

  2. 自定义绘画是硬编码的。不需要您尝试解决的 mouseMoved/mouseDragged 逻辑(除非这是问题所在)。您所关心的只是有不同的颜色可供点击。

  3. 只需使用简单的 System.out.println(...) 即可显示 Color 对象的值。

我所做的只是从你的课程中复制相关的代码片段并删除不相关的代码以保持代码简单直接。任何人都可以这样做。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DrawingCanvas extends JPanel
{
    private Robot robot;

    public DrawingCanvas()
    {
        addMouseListener(new MouseAdapter()
        {
            @Override
            public void mouseClicked(MouseEvent e)
            {
                try
                {
                    robot = new Robot();
                }
                catch(Exception re) { System.out.println(re); }

                PointerInfo pi = MouseInfo.getPointerInfo();
                Point p = pi.getLocation();
                Color pixelColor = robot.getPixelColor(p.x, p.y);
                System.out.println(pixelColor);
            }
        });

    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        g.setColor( Color.RED );
        g.fillRect(0, 0, 40, 40);

        g.setColor( Color.GREEN );
        g.fillRect(40, 40, 40, 40);

        g.setColor( Color.BLUE );
        g.fillRect(80, 80, 40, 40);
    }

    private static void createAndShowGUI()
    {
        JPanel panel = new DrawingCanvas();
        JFrame frame = new JFrame("DrawingCanvas");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.setSize(200, 200);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() ); // Java 8 only
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

只需复制/粘贴/编译/执行即可查看代码是否有效。

我会让你弄清楚为什么你的代码似乎不起作用。

NBB。之所以可行,是因为 Canvas 的实例是在 JFrame 中创建到 Runnable 中的,因此可以保存更改,从而避免了对形状和数组列表的需要。

这种说法是完全错误的。在paintComponent() 方法中使用图形对象完成的绘制只是暂时的,直到下一次调用paintComponent() 方法。

例如在 frame.setVisible() 语句后添加如下代码:

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        Graphics g = panel.getGraphics();
        g.setColor( Color.YELLOW );
        g.fillRect(120, 120, 40, 40);
    }
});

调整框架大小时,黄色方块会消失。对于永久绘画,您需要使用我在原始答案中建议的两种方法之一。

编辑 2:

这是我分别点击红色、绿色、蓝色、背景时得到的输出:

C:\Java>java DrawingCanvas
java.awt.Color[r=255,g=0,b=0]
java.awt.Color[r=0,g=255,b=0]
java.awt.Color[r=0,g=0,b=255]
java.awt.Color[r=238,g=238,b=238]

【讨论】:

  • 您好,我当然已经去掉了一些代码,以便于阅读。它有效,当我画一条线时,它存储在 g 对象中,所以当我画第二条线时它不会被擦除。我尝试了第一种方法,但不知何故不起作用。我得到错误的颜色。 (这就是问题中的问题)。我想采用第二种方法,但我不知道如何在缓冲图像上绘图。
  • , it's stored in the g object, so it doesn't get erased when I draw the second one - 不,不是。图形对象中没有存储任何内容。您可以将信息存储在 ArrayList 或 BufferedImage 中。 I have tried the first approach, but it somehow does not work. - 发布一个正确的 SSCCE 来证明问题。 but I can't figure out how to draw on the buffered image - 这就是我向您提供链接的原因。
  • 但是当我画的时候线条并没有消失。我没有使用 arrayList 也没有使用 bufferedImages。完整的代码在我的问题中,包括 SSCCE 的代码。机器人读取错误的颜色。
  • 您在上一个问题中没有得到太多帮助。我想在这里提供帮助,但由于您没有发布正确的 MCVE/SSCCE,我无法提供更多帮助。
  • 请告诉我您需要什么来提供帮助。我缺乏在同一个班级完成所有这些工作的知识。
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2011-07-06
  • 2014-04-08
  • 1970-01-01
  • 2011-11-30
  • 2017-01-23
相关资源
最近更新 更多