Repaint () не работает после добавления дополнительных компонентов в JPanel в Swing, Java - PullRequest
0 голосов
/ 23 апреля 2019

Я начинаю с Java и хочу сделать простую игру в понг, чтобы разобраться в способах отображения вещей в Java. Я создал 2 класса, которые расширяют JPanel и вызывают функцию repaint() каждые 16,6 миллисекунды. Я добавил оба в JPanel, который я добавил в рамку, но только компонент, который я добавил, отображается первым.

Я попытался revalidate() после repaint() в обоих классах и убедился, что таймер действительно работает и что его метод actionPerformed() действительно вызывается.

Это основной метод:

public class Main {
  public static void main(String[] args){
    JFrame frame = new JFrame("Pong");
    //...
    JPanel mainPanel = new JPanel();

    mainPanel.add(new Player());
    mainPanel.add(new Ball(frameWidth/2, frameHeight/2 -40));

    frame.add(mainPanel);
  }
}

Это важный код для классов (он в основном одинаков для них обоих):

public class Player extends JPanel {

  public Player(){
    setPreferredSize(new Dimension(Main.frameWidth, Main.frameHeight));
    setBackground(Color.BLACK);

    new Timer(1000/60, new ActionListener(){
      public void actionPerformed(ActionEvent e){
        update();
        repaint();
      }
    }).start();
  }
//...
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}

(Конечно, я упустил такие вещи, как @Override или ненужные функции для сокращения кода)

Этот код рисует только проигрыватель, хотя я хочу, чтобы он отображал все компоненты mainPanel.

Это пример, который вы можете (надеюсь) запустить. Мне пришлось разделить его на 3 файла, так как я сосу на анонимных классах:

Main.java

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {

  public static void main(String[] args){
    JFrame frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 800);

    JPanel mainPanel = new JPanel();

    mainPanel.add(new Player());
    mainPanel.add(new Ball());

    frame.add(mainPanel);

    frame.setVisible(true);
  }
}
///////
Player.java
//////
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Player extends JPanel{
  private int x = 20, y = 300, width = 20, height = 100;
  public Player(){
    setPreferredSize(new Dimension(800, 800));
    setBackground(Color.BLACK);

    new Timer(1000/60, new ActionListener(){
      @Override
      public void actionPerformed(ActionEvent e){
        repaint();
      }
    }).start();
  }


  @Override
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}
//////
Ball.java
//////
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Ball extends JPanel{
  private int x = 20, y = 300, width = 20, height = 100;
  public Ball(){
    setPreferredSize(new Dimension(800, 800));
    setBackground(Color.BLACK);
    new Timer(1000/60, new ActionListener(){
      @Override
      public void actionPerformed(ActionEvent e){
        repaint();
      }
    }).start();
  }

  @Override
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}

Ответы [ 2 ]

1 голос
/ 23 апреля 2019

В методе paintComponent() класса Player вы рисуете одинаково Rectangle каждый раз.Чтобы добиться анимации, каждый раз, когда вы рисуете прямоугольник, вам нужно изменить либо его размер, либо местоположение, либо и то, и другое.Что вы ожидаете от Player?Должен ли он двигаться вверх и вниз по левому краю окна?Вы видели урок под названием Как использовать Swing Timers , который является частью Oracle Учебник по Java ?

EDIT

Теперь я вижу, что Player скрывает Ball из-за менеджера компоновки по умолчанию JPanel.Приведенный ниже код, по сути, является кодом, который вы опубликовали, но я установил GridLayout в качестве менеджера макета для mainPanel.Кроме того, файл исходного кода Java может содержать более одного класса, но ровно один класс должен быть public.Следовательно, в приведенном ниже коде только класс Main равен public.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Pong");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel mainPanel = new JPanel(new GridLayout(0, 2));
        mainPanel.add(new Player());
        mainPanel.add(new Ball());
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

class Player extends JPanel {

    public Player() {
        setBorder(BorderFactory.createLineBorder(Color.RED, 2, false));
        setPreferredSize(new Dimension(800, 800));
        setBackground(Color.BLACK);

        new Timer(1000 / 60, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        }).start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.WHITE);
        g.fillRect(20, 100, 20, 100);
    }
}

class Ball extends JPanel {

    public Ball() {
        setBorder(BorderFactory.createLineBorder(Color.CYAN, 2, false));
        setPreferredSize(new Dimension(800, 800));
        setBackground(Color.BLACK);
        new Timer(1000 / 60, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        }).start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.WHITE);
        g.fillRect(300, 300, 10, 10);
    }
}

А вот снимок экрана графического интерфейса ...

Main

0 голосов
/ 23 апреля 2019

Я только что понял, что, если я расширяю свое окно вручную, появляется второй JPanel под тем, который отвечает за Игрока!Это значит, что мне нужно как-то установить положение панелей, верно?

@ Abra

...