Java机器人类-获取像素颜色后';重画

Java机器人类-获取像素颜色后';重画,java,swing,graphics,rgb,awtrobot,Java,Swing,Graphics,Rgb,Awtrobot,我需要为我的小ms paint应用程序创建一个颜色选择器工具。 我最初问如何从图形2D实现切换到图形2D-->BuffereImage实现(然后很容易获得像素),但有人建议我在robot类中获得像素颜色 首先,这是我的MCEVE:NB。它不能是一个类,它不会保存 import java.awt.*; import javax.swing.*; public class Runner { public static void main(String[] args){ JFrame M

我需要为我的小ms paint应用程序创建一个颜色选择器工具。 我最初问如何从图形2D实现切换到图形2D-->BuffereImage实现(然后很容易获得像素),但有人建议我在robot类中获得像素颜色

首先,这是我的MCEVE:NB。它不能是一个类,它不会保存

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;

}
而且效果很好

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

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

呼叫示例:

//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将整个过程包装到一个BuffereImage中,但这甚至无法远程工作

我做错了什么

多谢各位

编辑1:

有人怀疑在第二条线被画出来后,一条线如何能留在屏幕上。我将提供一个屏幕截图:

NBB。这是因为Canvas的实例是在JFrame内部创建为Runnable的,所以更改被保存,从而避免了对形状和ArrayList的需要

我还将添加一个完整版本的代码,该代码打印错误的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;

 }
}
我的小ms绘画应用程序

嗯,这不是一个绘画应用程序。它所做的只是画一条线。无论何时尝试绘制第二条线,第一条线都将被删除

因此,你需要做的第一步是决定你希望这幅画如何工作。有两种常见的方法:

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

  • 直接绘制到
    缓冲区图像
    ,然后
    绘制组件(…)
    方法可以只绘制
    缓冲区图像

  • 查看这两种方法的工作示例,并给出使用每种方法的优缺点

    相反,有人建议我在机器人类中使用像素颜色

    这取决于你想使用哪种绘画方法

    如果使用
    Draw-on-Component
    方法,则可以使用
    MouseInfo
    Robot
    获得像素颜色:

    PointerInfo pi = MouseInfo.getPointerInfo();
    Point p = pi.getLocation();
    System.out.println( robot.getPixelColor(p.x, p.y) );
    
    如果使用
    在图像上绘制
    方法,则可以从
    缓冲区图像
    获取像素颜色:

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

    您仍然没有发布SSCCE。你发布的代码没有划清界限。即使它确实画了一条线,你希望我们如何(精确地)点击一条像素线

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

    以下是正确的SSCCE。注:

  • createAndShowGUI()
    main()
    方法对于所有SSCCE都是相同的。区别在于“DrawingPanel代码/类”将更改以演示您的问题

  • 定制的绘画是硬编码的。您不需要尝试解决mouseMoved/mouseDragged逻辑(除非这是问题所在)。所有你关心的是有不同的颜色点击

  • 只需使用一个简单的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的,所以更改被保存,从而避免了对形状和ArrayList的需要

    这种说法是完全错误的。在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]
    

    我删除了
    robot
    标记,因为您谈论的是一些Java类而不是物理机器人:)除此之外,您是否检查了发送给
    robot
    的正确坐标?您是否检查了
    PointerInfo
    使用的坐标系?如果您使用了错误的坐标系,您的位置可能在画布/面板之外,因此返回了错误的值。是的,我有。坐标是正确的。非常感谢您的阅读和帮助。变量名不应该以大写字母开头。不要称你的班级为“画布”。这是一个AWT类名,令人困惑。使用更好的描述性类名。
    首先,这是我的MCVE:
    -这不是MCVE。代码应该在一个类文件中,我们可以复制/粘贴/编译/执行。我的类名不是Canvas,我从意大利语翻译了代码以使其不可理解,这是我发现的最接近的东西。很抱歉,这是我能到达的最接近MCVE的地方,我还不知道如何将所有内容放在同一个类中,请创建单独的
    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]