как добавить mouseClicked в скрипт

У меня есть алгоритм заливки, и я хочу добавить к этому mouseClicked, но я не знаю, как это сделать, потому что у меня много ошибок.

Вот мой код. Я хочу получить позицию x, y от mouseClicked и передать ее «floodFill (изображение, x, y, желтый);»

Может кто-нибудь помочь мне? Спасибо

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

class AnimationFiller
{
 // draw a black square with a pen width of 1 pixels
  static void drawSquare(BufferedImage image)
  {
    java.awt.Graphics2D gr=(java.awt.Graphics2D) image.getGraphics(); 

    gr.setColor(new java.awt.Color(0,0,0));  // black
    gr.setStroke(new java.awt.BasicStroke(1));  // set pen width to 1 pixel
    gr.drawRect(0, 0, 296, 264);  // (x,y,w,h);
  }
  // implements the flood fill algorithm
  public static void floodFill(BufferedImage image, int x,int y, int fillColor)
  {
    java.util.ArrayList<Point> examList=new java.util.ArrayList<>();

    int initialColor=image.getRGB(x,y);
    examList.add(new Point(x,y));

    while (examList.size()>0)
    {
      Point p = examList.remove(0);  // get and remove the first point in the list
      if (image.getRGB(p.x,p.y)==initialColor) 
      {
        x = p.x;  y = p.y;
        image.setRGB(x, y, fillColor);  // fill current pixel

        examList.add(new Point(x-1,y));        // check west neighbor
        examList.add(new Point(x+1,y));        // check east neighbor
        examList.add(new Point(x,y-1));        // check north neighbor
        examList.add(new Point(x,y+1));        // check south neighbor
      }
    }

  }

  public static int packRgb(int r,int g,int b)
  {
    return (r*256+g)*256+b;
  }

  static JLabel _imageLabel;
  public static void main(String[] args) throws Exception
  {
    // read bmp image from file
    final BufferedImage image = ImageIO.read(new File("picture.bmp"));

    drawSquare(image);
    final JLabel imageLabel = new JLabel();
    _imageLabel = imageLabel;  // make it global
    imageLabel.setIcon(new ImageIcon(image));


    javax.swing.JFrame window = new javax.swing.JFrame();
    window.setResizable(false);
    window.setTitle("Kolorowanka");
    window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);

    window.add(imageLabel);

    window.pack();
    window.setVisible(true);

    // fill the image with yellow color
    final int yellow = packRgb(255,255,0);
    imageLabel.addMouseListener(new MouseListener() {
    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        floodFill(image, e.getX(), e.getY(), yellow);
        imageLabel.setIcon(new ImageIcon(image));
    }
});

  }
}

person user2037133    schedule 03.02.2013    source источник
comment
Логика алгоритма заливки не эффективна. Вы используете рекурсивный подход, и это определенно не удастся для больших изображений. Посетите эту страницу, чтобы узнать о лучших алгоритмах.   -  person Extreme Coders    schedule 03.02.2013


Ответы (2)


Вы можете добавить событие mouseClicked следующим образом:

imageLabel.addMouseListener(new MouseListener() {
    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        floodFill(image, e.getX(), e.getY(), yellow);
    }
});

Если вы хотите использовать некоторые поля вне анонимного класса, вы должны определить его как final. Например:

final BufferedImage image = ...

А также

final int yellow = packRgb(255, 255, 0);

Пожалуйста, ознакомьтесь с полем final, прежде чем писать следующие части вашего проекта. Примеры источников:

person Michał Ziober    schedule 03.02.2013
comment
Спасибо, работает хорошо. Но иногда, когда я много раз нажимал на картинку, моя программа вылетала, и я не мог ее закрыть, потому что все еще занят. Вы знаете, в чем проблема? [Отредактированный код в первом вопросе] - person user2037133; 03.02.2013
comment
@user2037133 user2037133 Программа вылетает из-за того, что новые клики также отправляются на обработку. Что вам нужно сделать, так это удалить прослушиватель мыши после того, как вы получите точку щелчка, заполнить изображение и затем снова подключить прослушиватель. - person Extreme Coders; 03.02.2013
comment
Ваш алгоритм очень медленный, потому что вы используете методы getRGB/setRGB. Вам следует избегать этого метода работы с пикселями. См. эту статью: java-tips.org/java-se-tips/java.awt.geom/. Он показывает, как получить все пиксели. Работайте над таблицей и после этого обновляйте изображение. Также вы можете заблокировать следующий клик, пока текущий клик не будет обработан. - person Michał Ziober; 03.02.2013

Это реализация алгоритма заливки строкой сканирования, который я написал пару месяцев назад.

boundaries — стек, startX, startY — координаты начальной точки. Массив pixels содержит значение RGB всех пикселей в изображении. Массив был получен с использованием PixelGrabber на исходном изображении.

Использование всех остальных переменных подразумевается.

boundaries.push(new Point(startX,startY));
//Now we have the starting positions for coloring in the above and lower lines
//coloring is done in right directions only

while(!boundaries.isEmpty()) //Loop as many times till no starting positions are found
{
    //Now begin coloring
    Point pt=boundaries.pop();
    //This is the starting point for coloring towards right direction
    int x=pt.x;
    int y=pt.y;

    //First go as far left as possible until a different colored pixel is found
    while(x>=0)
    {
        if(pixels[y*WIDTH+x]!=pickPointPreviousColor) break;
        x--;
    }
    x++;

    //Now extend right
    while (x<=WIDTH)
    {
        if(pixels[y*WIDTH+x]==pickPointPreviousColor)
            pixels[y*WIDTH+x]=colorToFill;
        else
        {
            upperLineCountingStarted = false;
            lowerLineCountingStarted=false;
            break;
        }

        if(y>0 && upperLineCountingStarted==false && pixels[(y-1)*WIDTH+x]==pickPointPreviousColor)
        {
            boundaries.push(new Point(x,y-1));
            upperLineCountingStarted=true;
        }

        else if(y>0 && upperLineCountingStarted==true && pixels[(y-1)*WIDTH+x]!=pickPointPreviousColor)
            upperLineCountingStarted=false;

        if(y<HEIGHT && lowerLineCountingStarted==false && pixels[(y+1)*WIDTH+x]==pickPointPreviousColor)
        {
            boundaries.push(new Point(x,y+1));
            lowerLineCountingStarted=true;
        }
        else if(y<HEIGHT && lowerLineCountingStarted==true && pixels[(y+1)*WIDTH+x]!=pickPointPreviousColor)
            lowerLineCountingStarted=false;

        x++;
    }
}
person Extreme Coders    schedule 03.02.2013