Итак, ваша основная проблема сводится к следующим строкам ...
this.setLayout(new BorderLayout());
//...
//===== Background =====
puzzleBackground = new ImageIcon("MyBackground.jpg");
setContentPane(new JLabel(puzzleBackground));
Можете ли вы сказать мне, что на самом деле используется менеджер компоновки? Неправильно. Диспетчер макетов теперь null
, потому что JLabel
на самом деле не имеет диспетчера по умолчанию.
Таким образом, «простой» ответ будет состоять в том, чтобы переместить вызов setLayout
ниже уровня вызова setContentPane
, но это будет недальновидный ответ, так как JLabel
вычисляет его предпочтение на основе значка и свойств текста только не дочерние компоненты.
Лучшим решением было бы сделать что-то, продемонстрированное в Как установить фоновое изображение в JPanel (см. Второй пример)
Это означает, что если изображение меньше, чем требуемое пространство, компоненты исчезнут с экрана.
Я прошел и немного почистил код, только с целью заставить работать макет
![Simple layout](https://i.stack.imgur.com/Bx5JM.png)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainWindow extends JFrame implements ActionListener {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MainWindow() {
super("Welcome");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
this.setLayout(new BorderLayout());
menu = new JPanel();
menu.setLayout(new GridBagLayout());
exit = new JButton("Exit");
exit.addActionListener(this);
start_Game = new JButton("Start to play");
exit.addActionListener(this);
start_Game.addActionListener(this);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(menu, BorderLayout.EAST);
pack();
setVisible(true);
}
public static void main(String args[]) {
MainWindow a = new MainWindow();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
}
}
}
Я также хотел бы отметить, что расширение непосредственно от JFrame
также недальновидно, оно блокирует вас в одноразовом контейнере, и вы фактически не добавляете в класс никаких новых функциональных возможностей.
Пример лучшей структуры ...
Ниже приведен простой пример, возможно, лучшей структуры. В нем отсутствует понятие «контроллер», который контролирует вещи и «модель», которая поддерживает информацию о состоянии, которая используется пользовательским интерфейсом для отображения «вещей», но дает отправную точку
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String args[]) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Welcome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MainPane extends JPanel {
public MainPane() {
setLayout(new BorderLayout());
// This is just a filler, it can be removed, but it helps prove the point
add(new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
});
add(new MenuPane(), BorderLayout.EAST);
}
}
public class MenuPane extends JPanel {
private JButton exit;
private JButton start_Game;
private JPanel menu;
public MenuPane() {
menu = new JPanel();
menu.setLayout(new GridBagLayout());
ActionHandler actionHandler = new ActionHandler();
exit = new JButton("Exit");
exit.addActionListener(actionHandler);
start_Game = new JButton("Start to play");
start_Game.addActionListener(actionHandler);
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = gbc.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(exit, gbc);
menu.add(start_Game, gbc);
}
public class ActionHandler implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == exit) {
System.exit(0);
} else {
//open start up window.
// This should be used to notifiy a controller class
// that some new action needs to take place, the controller
// is then responsible for making it happen
}
}
}
}
}