Hallo, ich habe ein JPanel auf dem etwas gezeichnet wird und bei einem bestimmten Event soll ein zweites Panel über das erste drüber gelegt werden. Dabei ist das zweite JPanel durchsichtig (also opacity des Hintergrunds = 0.5) und man soll das erste Panel noch sehen. An sich klappt das auch ganz gut, aber es gibt noch 2 Probleme:
1. Wenn ich nicht die vordefinierte Größe des JFrames nutze, sprich die Größe des Frames wird manuell geändert, werden im hinteren Panel die Sachen alle doppelt gezeichnet.
2. Wenn ich die größe des Frames verändere, während das zweite Panel angezeigt wird, wird dann nur noch das vordere Panel gezeichnet, ich hätte ja aber gerne, dass das hintere auch weiterhin sichtbar ist.
Der Code:
[CODE lang="java" title="Hinteres JPanel"]public class GamePanel extends JPanel {
private final static int PILLAR_DISTANCE = 300;
private final GameFrame frame;
private Player player;
private List<Obstacle> pillars;
private ResultPanel resultPanel; // das vordere Pane
private JLabel scoreLabel;
private int score;
public GamePanel(Dimension d, final GameFrame frame) {
this.frame = frame;
setSize(d);
setLayout(null);
init();
setVisible(true);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.draw(g);
pillars.forEach(p -> p.draw(g));
}
public void onResize() {
player.setY(getHeight() / 2 - player.getHeight() / 2);
pillars.forEach(p -> p.resize(getSize()));
resultPanel.setSize(getSize());
resultPanel.onResize();
}
public void addPillar() {
pillars.add(new Obstacle(pillars.get(pillars.size() - 1).getX() + PILLAR_DISTANCE, getSize()));
}
private void init() {
resultPanel = new ResultPanel(getSize(), this);
resultPanel.setVisible(false);
add(resultPanel);
scoreLabel = new JLabel();
scoreLabel.setFont(new Font("Impact", Font.BOLD, 40));
scoreLabel.setBounds(40, 40, 150, 40);
scoreLabel.setVisible(true);
add(scoreLabel);
initGameObjects();
}
private void initGameObjects() {
score = 0;
scoreLabel.setText("" + score);
pillars = Collections.synchronizedList(new ArrayList<>());
player = new Player("rsc/flappy_bird/player.png");
player.setSize(84, 65);
player.setY(getHeight() / 2 - player.getHeight() / 2);
player.setX((int) (getWidth() * 0.3));
int x = PILLAR_DISTANCE;
for (int i = 0; i < 10; i++) {
pillars.add(new Obstacle(x + 500, getSize()));
x += PILLAR_DISTANCE;
}
pillars.forEach(p -> p.resize(getSize()));
repaint();
}
...
}[/CODE]
[CODE lang="java" title="Vorderes JPanel"]public class ResultPanel extends JPanel {
private final GamePanel panel; // das hintere Panel
private JButton restartBtn;
private JLabel crashedLabel;
public ResultPanel(Dimension d, final GamePanel panel) {
this.panel = panel;
setSize(d);
setLayout(null);
setBackground(new Color(1, 1, 1, 0.5f));
init();
}
public void onResize() {
restartBtn.setBounds(getWidth() / 2 - 50, (getHeight() / 2 - 20), 100, 40);
crashedLabel.setBounds(getWidth() / 2 - 150, (getHeight() / 5), 300, 50);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
public void activate() {
setVisible(true);
restartBtn.setVisible(true);
crashedLabel.setVisible(true);
}
private void init() {
restartBtn = new JButton("restart");
restartBtn.setBounds(getWidth() / 2 - 50, (getHeight() / 2 - 20), 100, 40);
restartBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
panel.reset();
restartBtn.setVisible(false);
crashedLabel.setVisible(false);
}
});
add(restartBtn);
restartBtn.setVisible(false);
crashedLabel = new JLabel("YOU CRASHED");
crashedLabel.setFont(new Font("Impact", Font.BOLD, 50));
crashedLabel.setBounds(getWidth() / 2 - 150, (getHeight() / 5), 300, 50);
crashedLabel.setVisible(false);
add(crashedLabel);
repaint();
}
}[/CODE]
Und zur Sicherheit noch das JFrame:
1. Wenn ich nicht die vordefinierte Größe des JFrames nutze, sprich die Größe des Frames wird manuell geändert, werden im hinteren Panel die Sachen alle doppelt gezeichnet.
2. Wenn ich die größe des Frames verändere, während das zweite Panel angezeigt wird, wird dann nur noch das vordere Panel gezeichnet, ich hätte ja aber gerne, dass das hintere auch weiterhin sichtbar ist.
Der Code:
[CODE lang="java" title="Hinteres JPanel"]public class GamePanel extends JPanel {
private final static int PILLAR_DISTANCE = 300;
private final GameFrame frame;
private Player player;
private List<Obstacle> pillars;
private ResultPanel resultPanel; // das vordere Pane
private JLabel scoreLabel;
private int score;
public GamePanel(Dimension d, final GameFrame frame) {
this.frame = frame;
setSize(d);
setLayout(null);
init();
setVisible(true);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.draw(g);
pillars.forEach(p -> p.draw(g));
}
public void onResize() {
player.setY(getHeight() / 2 - player.getHeight() / 2);
pillars.forEach(p -> p.resize(getSize()));
resultPanel.setSize(getSize());
resultPanel.onResize();
}
public void addPillar() {
pillars.add(new Obstacle(pillars.get(pillars.size() - 1).getX() + PILLAR_DISTANCE, getSize()));
}
private void init() {
resultPanel = new ResultPanel(getSize(), this);
resultPanel.setVisible(false);
add(resultPanel);
scoreLabel = new JLabel();
scoreLabel.setFont(new Font("Impact", Font.BOLD, 40));
scoreLabel.setBounds(40, 40, 150, 40);
scoreLabel.setVisible(true);
add(scoreLabel);
initGameObjects();
}
private void initGameObjects() {
score = 0;
scoreLabel.setText("" + score);
pillars = Collections.synchronizedList(new ArrayList<>());
player = new Player("rsc/flappy_bird/player.png");
player.setSize(84, 65);
player.setY(getHeight() / 2 - player.getHeight() / 2);
player.setX((int) (getWidth() * 0.3));
int x = PILLAR_DISTANCE;
for (int i = 0; i < 10; i++) {
pillars.add(new Obstacle(x + 500, getSize()));
x += PILLAR_DISTANCE;
}
pillars.forEach(p -> p.resize(getSize()));
repaint();
}
...
}[/CODE]
[CODE lang="java" title="Vorderes JPanel"]public class ResultPanel extends JPanel {
private final GamePanel panel; // das hintere Panel
private JButton restartBtn;
private JLabel crashedLabel;
public ResultPanel(Dimension d, final GamePanel panel) {
this.panel = panel;
setSize(d);
setLayout(null);
setBackground(new Color(1, 1, 1, 0.5f));
init();
}
public void onResize() {
restartBtn.setBounds(getWidth() / 2 - 50, (getHeight() / 2 - 20), 100, 40);
crashedLabel.setBounds(getWidth() / 2 - 150, (getHeight() / 5), 300, 50);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
public void activate() {
setVisible(true);
restartBtn.setVisible(true);
crashedLabel.setVisible(true);
}
private void init() {
restartBtn = new JButton("restart");
restartBtn.setBounds(getWidth() / 2 - 50, (getHeight() / 2 - 20), 100, 40);
restartBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
panel.reset();
restartBtn.setVisible(false);
crashedLabel.setVisible(false);
}
});
add(restartBtn);
restartBtn.setVisible(false);
crashedLabel = new JLabel("YOU CRASHED");
crashedLabel.setFont(new Font("Impact", Font.BOLD, 50));
crashedLabel.setBounds(getWidth() / 2 - 150, (getHeight() / 5), 300, 50);
crashedLabel.setVisible(false);
add(crashedLabel);
repaint();
}
}[/CODE]
Und zur Sicherheit noch das JFrame:
Java:
public class GameFrame extends JFrame {
private GamePanel panel; // hinteres JPanel
public GameFrame() {
setSize(new Dimension(800, 600));
setLayout(null);
panel = new GamePanel(getSize(), this);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
panel.setSize(getSize());
panel.onResize();
}
});
addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
// hier wird u.a. das Event getriggert, mit dem das vordere JPanel aktiviert wird
}
});
add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}