#java #user-interface #flood-fill
#java #пользовательский интерфейс #заливка-заполнение
Вопрос:
Я играл с Java GUI и столкнулся с ошибкой, которую я не могу понять, почему.
Моя программа основана на заливке заливки (цвет заливки внутри строк), но когда я пытаюсь заполнить, я получаю эту ошибку:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.util.Hashtable.get(Unknown Source)
at javax.swing.UIDefaults.getFromHashtable(Unknown Source)
at javax.swing.UIDefaults.get(Unknown Source)
at javax.swing.MultiUIDefaults.get(Unknown Source)
at javax.swing.UIDefaults.getColor(Unknown Source)
at javax.swing.UIManager.getColor(Unknown Source)
at javax.swing.LookAndFeel.installColors(Unknown Source)
at javax.swing.LookAndFeel.installColorsAndFont(Unknown Source)
at javax.swing.plaf.basic.BasicLabelUI.installDefaults(Unknown Source)
at javax.swing.plaf.basic.BasicLabelUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JLabel.setUI(Unknown Source)
at javax.swing.JLabel.updateUI(Unknown Source)
at javax.swing.JLabel.<init>(Unknown Source)
at javax.swing.JLabel.<init>(Unknown Source)
at MapPanel.refreshImage(MapPanel.java:167)
at MapPanel.setImage(MapPanel.java:162)
at MapPanel.floodFill(MapPanel.java:224)
[Эти повторяются совсем немного]
at MapPanel.floodFill(MapPanel.java:231)
at MapPanel.floodFill(MapPanel.java:230)
[Код для строк 230 и 231]
floodFill(newImage, mark, row - 1, col, srcColor, tgtColor);
floodFill(newImage, mark, row 1, col, srcColor, tgtColor);
Изображение обновляется цветом, но не полностью…
Я надеюсь, вы понимаете, что я пытаюсь сказать, я застрял на этом некоторое время, и любая помощь будет благодарна.
Код
// Mouse Listener
public class MouseCapture implements MouseListener
{
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse clicked");
System.out.println(e.getX() "," e.getY());
boolean[][] mark = new boolean[image.getHeight()][image.getWidth()];
for (int row = e.getY() 23; row < image.getHeight(); row ) {
for (int col = e.getX() - 200; col < image.getWidth(); col ) {
floodFill(image, mark, row, col, Color.WHITE, getColor());
}
}
image.setRGB(e.getX(), e.getY() 23, Color.BLACK.getRGB());
refreshImage();
}
}
private void floodFill(BufferedImage newImage, boolean[][] mark, int row, int col, Color srcColor, Color tgtColor)
{
// make sure row and col are inside the image
if (row < 0) return;
if (col < 0) return;
if (row >= newImage.getHeight()) return;
if (col >= newImage.getWidth()) return;
// make sure this pixel hasn't been visited yet
if (mark[row][col]) return;
// make sure this pixel is the right color to fill
if (!(newImage.getRGB(col, row) == (srcColor.getRGB()))) return;
// fill pixel with target color and mark it as visited
image.setRGB(col, row, tgtColor.getRGB());
mark[row][col] = true;
// set drawn image
setImage(newImage);
// recursively fill surrounding pixels
// (this is equivelant to depth-first search)
floodFill(newImage, mark, row - 1, col, srcColor, tgtColor);
floodFill(newImage, mark, row 1, col, srcColor, tgtColor);
floodFill(newImage, mark, row, col - 1, srcColor, tgtColor);
floodFill(newImage, mark, row, col 1, srcColor, tgtColor);
}
Комментарии:
1. вы пробовали мое решение? Приветствия!
2. Отличный пример @Wojciech Kazior, добавлю в свою программу завтра, так как сегодня мой разум изжарен и мне нужно немного поспать (программистам нужен сон: D) Спасибо!
Ответ №1:
Если вы получаете stackOverflowError
при использовании «Заливки заливкой», это означает, что полигон, который вы пытаетесь нарисовать, слишком велик для рекурсивной версии этого алгоритма. Попробуйте использовать версию с реализацией очереди или стека.
import java.util.*;
public class Main {
public static class Position {
private int y;
private int x;
public Position(int y, int x) {
this.y = y;
this.x = x;
}
public int getY() {
return y;
}
public int getX() {
return x;
}
}
public static void floodFill(Position position, int oldColor, int newColor, int[][] image) {
Queue<Position> queue = new LinkedList<Position>();
queue.add(position);
while (queue.size() > 0) {
Position newPosition = queue.poll();
if (newPosition.getY() >= 0 amp;amp; newPosition.getY() < image.length // check bounds
amp;amp; newPosition.getX() >= 0 amp;amp; newPosition.getX() < image[0].length // check bounds
amp;amp; image[newPosition.getY()][newPosition.getX()] == oldColor) {
image[newPosition.getY()][newPosition.getX()] = newColor;
queue.add(new Position(newPosition.getY(), newPosition.getX() - 1));
queue.add(new Position(newPosition.getY(), newPosition.getX() 1));
queue.add(new Position(newPosition.getY() - 1, newPosition.getX()));
queue.add(new Position(newPosition.getY() 1, newPosition.getX()));
}
}
}
public static void main(String[] args) {
int[][] array = new int[20][40]; // 20 rows, 40 columns
for (int y = 0; y < array.length; y ) { // iterate through rows
for (int x = 0; x < array[0].length; x ) // iterate through cols
System.out.print(array[y][x]);
System.out.println();
}
floodFill(new Position(5, 5), 0, 1, array);
for (int y = 0; y < array.length; y ) { // iterate through rows
for (int x = 0; x < array[0].length; x ) // iterate through cols
System.out.print(array[y][x]);
System.out.println();
}
}
}
Вы можете проверить, что это работает. Мы также можем проверять позиции при добавлении их в очередь, но наш код будет менее прозрачным.