Вот полный, самостоятельный пример, близкий к тому, что вы ищете. Это демонстрирует использование менеджера компоновки.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
public class DuelingJLabels{
public static void startGui(){
JFrame frame = new JFrame();
JPanel scene = new JPanel();
Actor red = new Actor(Color.RED);
Actor blue = new Actor(Color.BLUE);
//scene.setLayout( null );
scene.add(red.image);
scene.add(blue.image);
//scene.setPreferredSize( new Dimension(512, 512) );
frame.add(scene, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
static class Actor{
int x, y;
JLabel image;
public Actor(Color c){
BufferedImage a = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = a.getGraphics();
g.setColor(c);
g.fillOval(0, 0, 64, 64);
image = new JLabel();
image.setIcon(new ImageIcon(a));
image.setLocation( x, y );
image.setSize( 64, 64);
image.addMouseListener( new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent evt){
x = x+64;
if(x>=448){
x = 0;
y += 64;
}
image.setLocation(x, y);
}
});
}
}
public static void main(String[] args){
EventQueue.invokeLater( DuelingJLabels::startGui );
}
}
Обратите внимание на строку scene.setLayout(null);
Если вы запустите пример с закомментированной строкой, то вы увидите два круга рядом. Это потому, что мы позволяем Swing управлять макетом. scene
- это JPanel с FlowLayout
по умолчанию.
Теперь, когда вы нажимаете на кружки, ничего не происходит *, потому что мы сообщаем новую позицию, но менеджер компоновки сбрасывает позицию. * На самом деле они иногда перемещаются, но если вы инициируете повторную проверку, диспетчер макета перемещает их.
Так что теперь удалите комментарий к scene.setLayout(null);
и обратите внимание на разницу.
- Рамка крошечная, и мы должны вручную изменить ее размер, чтобы увидеть нашу сцену.
- Есть только один круг.
- Если вы нажмете на круг, он начнет двигаться.
Это потому, что мы сказали Swing не использовать менеджер макетов для сцены JPanel. Это означает, что он не будет перемещать компоненты в сцене для нас, и он также не будет корректировать размеры для нас.
Другая закомментированная строка setPreferredSize
заставляет сцену сообщать родительскому компоненту размер, по которому она будет нравится быть в. Если вы раскомментируете эту строку, то JFrame не станет невероятно маленьким. Вы должны использовать это только с пользовательскими компонентами, в противном случае вы можете столкнуться с конфликтом с менеджером макета.
Другой инструмент, который я нашел полезным, это JLayeredPane , потому что он дает вам некоторую глубину. Я также думаю, что пример хорош.
Наконец, еще один метод произвольного размещения произвольной графики - это @Override paintComponent. Таким образом, вы можете нарисовать что угодно и где угодно на вашем компоненте.