Java Swing Drawing (Проблема с PaintComponent)

Это мое первое сообщение на этом форуме, поэтому заранее извините, если я ошибусь в форматировании или размещении этикета здесь.

Я довольно новичок в программировании на Java Swing, и я пытался создать простую игру Tower Defense для личного проекта, но у меня возникли проблемы с рисованием изображений в моем приложении. Я просматривал многие руководства по Java как на этом форуме, так и в Oracle, но мне так и не удалось найти решение, которое помогло бы исправить это, поэтому я прибегаю к просьбе о себе.

public static void main(String[] args) 
{
    new DotO();
}

public DotO()
{
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();             
        }
    });
}

private void createAndShowGUI()
{
    backgroundPanel = new JPanel();
    setBorder(BorderFactory.createLineBorder(Color.black));
    loadBackground();  
    setBackground(Color.white);  

    //1. Create the frame.
    JFrame frame = new JFrame("Defense Of The Origin");

    //2. Optional: What happens when the frame closes?
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //4. Size the frame.
    frame.setSize(SIZEX, SIZEY);

    //5. Show it.
    frame.setVisible(true);

    //3. Add Background Panel
    frame.add(backgroundPanel);  
}

private void loadBackground()  
{  
    String fileName = "resources/Background.jpg";  
    try  
    {  
        URL url = getClass().getResource(fileName);  
        backgroundImage = ImageIO.read(url);  
    }  
    catch(MalformedURLException mue)  
    {  
        System.out.println("url: " + mue.getMessage());  
    }  
    catch(IOException ioe)  
    {  
        System.out.println("read: " + ioe.getMessage());  
    }
}

@Override
protected void paintComponent(Graphics g)  
{  
    System.out.println("painted");
    super.paintComponent(g);  
    int w = getWidth();  
    int h = getHeight();
    g.drawImage(backgroundImage, 0, 0, w, h, this);  
    System.out.println("it's working");
}

Рамка открывается без проблем в предпочтительном размере, но ничто не рисуется на рамке. Все, что я вижу, это серое пространство, и когда я помещаю System.out.print в метод paintComponent, он не отображается в консоли, поэтому я знаю, что приложение никогда не запускает метод paintComponent. Любой совет будет принята с благодарностью!

1 ответ

Решение

Это очевидно принадлежит классу

class DotO extends JPanel { ... }

Однако в вашем createAndShowGUI Метод, вы создаете новую панель и добавляете эту панель в рамку. На этой панели paintComponent метод не переопределен.

С другой стороны, вы никогда не создаете "видимый" экземпляр DotO, Вы только создаете экземпляр DotO, но никогда не добавляйте его в кадр или около того.

Одним из решений было бы опустить backgroundPanelи вместо

frame.add(backgroundPanel);

ты можешь позвонить

// Add "this" to the panel. "this" is the DotO instance
// where the `paintComponent` method is overridden
frame.add(this);

Вы должны рассмотреть возможность вытащить создание GUI из DotO класс, и сделать создание кадра в main метод, как это:

public static void main(String[] args) 
{
    SwingUtilities.invokeLater(new Runnable() 
    {
        public void run() 
        {
            createAndShowGUI();             
        }
    });
}

private static void createAndShowGUI() 
{
    //1. Create the frame.
    JFrame frame = new JFrame("Defense Of The Origin");

    //2. Optional: What happens when the frame closes?
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //4. Size the frame.
    frame.setSize(SIZEX, SIZEY);

    //5. Show it.
    frame.setVisible(true);

    // Here, create an instance of "DotO", and add it to the frame!
    frame.add(new DotO());
}

// In the DotO constructor, only do what has to be done
// specifically for this DotO instance:
public DotO()
{
    setBorder(BorderFactory.createLineBorder(Color.black));
    loadBackground();  
    setBackground(Color.white);  
}

Но это можно рассматривать как деталь сейчас.


РЕДАКТИРОВАТЬ в ответ на комментарий:

Чтобы нарисовать несколько изображений, вы можете просто загрузить и нарисовать их как фоновое изображение (но по понятным причинам после фонового изображения).

Можно дать много дополнительных рекомендаций здесь. Хотя, строго говоря, это не цель сайта "Вопрос + ответ", но должна быть достигнута путем чтения учебных пособий и примеров кода.

Итак, пуристы Q&A: Пожалуйста, оставьте сейчас, некоторые вещи без ответа впереди:


Я знаю, что Swing - это "сладкий яд": с несколькими строками кода у вас есть первый кадр с изображением. Но это не значит, что вам не нужно планировать и думать заранее при создании игры. Вы не можете просто "написать больше кода" и надеяться, что "что-то хорошее" выйдет.

Таким образом, я бы рекомендовал вам сначала подумать о том, какой должна быть структура вашей игры. Какие у вас будут занятия? Какова должна быть ответственность каждого класса, с точки зрения полей и методов, которые будет иметь класс?

Конечно, не неправильно писать "тестовые фрагменты" для определенных функций. Например, тестовый фрагмент для загрузки и отображения фонового изображения;-) Но вы не можете создать игру, только написав много кода с нуля в одном классе.

Иногда здесь указывается, что нужно описать словами, чего вы хотите достичь. В качестве примера (очень "сжатый", чтобы проиллюстрировать точку):

Я хочу башню, которая имеет определенный диапазон и может стрелять и может быть нарисована на экране

Это может помочь приблизительно получить структуру:

  • Существительные являются классами
  • Прилагательные / Атрибуты являются полями
  • Глаголы - это методы

давая класс как

class Tower {
    float range;
    void shoot() {...}
    void paintInto(Graphics g) {...}
}

(Это действительно только очень грубое руководство!)

Кроме того, будет много деталей для рассмотрения. Например, вы заметите, что было бы полезно изменить loadBackground() метод в нечто вроде

private void loadImage(String fileName)  
{  
    ...
}

метод, который можно назвать

background = loadImage("resources/Background.jpg");
tower = loadImage("resources/Tower.jpg");

Но опять же: это то, чему вы можете научиться из руководств и примеров кода (и которые вы (надеюсь) сделаете автоматически рано или поздно)

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