Java机器人类 - 在绘制后获得Pixel颜色

时间:2016-06-28 13:56:33

标签: java swing graphics rgb awtrobot

我需要为我的小ms绘画应用创建一个 colorPicker 工具。 我最初问过如何从我的Graphics 2D实现切换到Graphics2D - &gt; BufferedImage一个(然后它很容易获得像素)但我已经建议让像素颜色被认为是机器人类。< / p>

首先,这是我的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;

}

它运作得很好。

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

我这样做:(将此方法添加到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次,但在某些区域仍然会丢失它。

我还尝试用机器人#screenCap将整个事物包装到bufferedImage中,但这甚至无法远程工作。

我在这里做错了什么?

非常感谢。

EDIT1:

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

Several separated lines. I used a bigger brush size for visibility

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;

 }
}

1 个答案:

答案 0 :(得分:2)

  

我的小画画应用

嗯,它不是一个油漆应用程序。它只是绘制一条线。每当您尝试绘制第二条线时,第一条线将被移除。

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

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

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

  3. 查看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对象的值。

    4. 我所做的只是从您的类中复制相关的代码片段并删除不相关的代码以保持代码简单直接。任何人都可以做到这一点。

      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()方法中使用Graphics对象完成绘画只是暂时的,直到下次调用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]