Ошибка переполнения стека при использовании JPanel.setLocation с StretchIcon (ImageIcon) в нем

Попытка создать подвижный объект с помощью JPanel, у которого есть ImageIcon, который автоматически растягивается при изменении его размера. Теперь, когда я запускаю приложение, оно правильно активируется и показывает изображение. Однако, когда я нажимаю кнопку, появляется следующее сообщение об ошибке:

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
    at java.awt.Component.setLocation(Unknown Source)
    at tutorial.GridPanel.move(GridPanel.java:51)
    at java.awt.Component.setLocation(Unknown Source)
    at tutorial.GridPanel.move(GridPanel.java:51)
    at java.awt.Component.setLocation(Unknown Source)
    at tutorial.GridPanel.move(GridPanel.java:51)
    (continue many times)

Обнаружили, что это может быть король косвенной рекурсии? вещь, но я просто не могу найти, что вызывает это. Ниже приведен класс GridPanel, который я написал для JPanel.

package tutorial;

import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import darrylbu.icon.StretchIcon;

public class GridPanel extends JPanel
{   
    private BufferedImage image;

    GridPanel() {}
    GridPanel(String path)
    {
        setLayout(null);
        try
        {
            image = ImageIO.read(new File(path));
        }catch(IOException e)
        {
            System.out.println(e);
        }

        addKeyListener(new KeyAdapter()
        {
            public void keyPressed(KeyEvent e)
            {
                System.out.println(e.getKeyChar());
                move(10, 10);
            }
        });
    }

    @Override
        protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        StretchIcon icon = new StretchIcon(image);            
        icon.paintIcon(this, g, 0, 0);
    }

    public void move(int x, int y)
    {
        super.setLocation(getX() + x, getY() + y);
    }
}

setLocation звонит move, который снова звонит вам move, потому что вы его переопределили... кстати. Я бы избегал делать это таким образом. Начнем с того, что нет необходимости создавать новый StretchIcon каждый раз, когда вызывается paintComponent. Вы также можете изменить положение экземпляра icon на панели в зависимости от того, какое местоположение вы предпочитаете, а не пытаться изменить местоположение самой панели, что может иметь ряд нежелательных побочных эффектов.
MadProgrammer 30.05.2019 09:17

@MadProgrammer Никогда не обнаруживал, что я переопределяю метод move. Большое спасибо. Что касается StretchIcon, значит ли это, что я должен объявить что-то вроде private StretchIcon s в классе?

Uduru 30.05.2019 09:28

Это будет хорошим началом. Однако реальный ответ будет сильно зависеть от того, чего вы пытаетесь достичь.

MadProgrammer 30.05.2019 09:41
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Здесь:

public void setLocation(int x, int y)
{
  move (x, y);
}

Это исходный код для Компонент.setLocation(). Как видите, этот метод вызывает move(). Ваша панель переопределяет move() вызов setLocation(). Вот и все: ваша рекурсия не "косвенная", она прямо здесь.

Итак, очевидно: не вызывайте setLocation() из вашего move() метода! Так что весь ваш подход ошибочен на данный момент.

Спасибо, что сказали мне, что я переопределяю функцию move. Никогда не находил этого, и это решило все LOL.

Uduru 30.05.2019 09:31

Другие вопросы по теме