Чтобы понять, почему это не работает, вам нужно понять, как на самом деле работает система окраски
Просто глядя на этот фрагмент, должно быть очевидно, что что-то не так.
public class Main extends JFrame implements ActionListener {
//...
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
Вы объявили метод с именем paintComponent
, но вызываете супер метод paintComponents
(обратите внимание на s
в конце).
Кроме того, когда вы «думаете», что переопределяете метод, вы должны использовать атрибут #Override
, это приведет к ошибке компилятора, если вы сделали что-то не так
public class Main extends JFrame implements ActionListener {
//...
@Overrride
public void paintComponent (Graphics g) {
super.paintComponents(g);
//...
}
}
Приведенный выше код теперь не будет компилироваться, поскольку JFrame
не объявляет метод paintComponent
.
Как правило, следует избегать расширения непосредственно из JFrame
(или других контейнеров верхнего уровня), они являются составными компонентами и имеют сложную иерархию и функциональность.
Лучше всего начать с JPanel
![Simple structure](https://i.stack.imgur.com/cec13.png)
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
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("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
public TestPane() {
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
paintPane = new PaintPane();
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
g1.drawOval(3, 5, 45, 46); // The ball
g1.fillOval(20, 30, 40, 40);
}
}
}
Вам нужно время, чтобы взглянуть на Рисование в Swing и Выполнение пользовательской живописи для получения более подробной информации.
Некоторые другие понятия, которые вы могли бы потратить на изучение:
Также я подумываю использовать функцию, которая делает это x=x+
; и y=y+1
при нажатии влево или вправо.
Хорошо, вот где "модель" в MVC будет играть свою роль.
Итак, начнем с определения основных свойств, которые, как мы ожидаем, будет поддерживать модель ...
public interface ShapeModel {
public Point getPoint();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
Здесь поддерживается Point
в качестве местоположения и ChangeListener
в качестве шаблона наблюдателя, который уведомляет заинтересованные стороны об изменении состояния модели.
Зачем начинать с interface
? Как общая концепция, вы всегда должны предпочитать код для интерфейса вместо реализации. В этом случае один из аспектов interface
, который не был определен, - как обновляется Point
? Это не представляет большого интереса для большинства сторон, которые хотят работать с моделью, они просто хотят знать, когда она изменяется, мутация модели может быть выражена либо непосредственно через реализацию, либо с помощью «изменяемого» * 1071 *, который происходит от interface
Далее мы определяем реализацию по умолчанию ...
public class DefaultShapeModel implements ShapeModel {
private Point point = new Point(40, 40);
private List<ChangeListener> listeners = new ArrayList<>(25);
@Override
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
fireStateChanged();
}
protected void fireStateChanged() {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
@Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
}
Это определяет, как должна обновляться краска.
Наконец, мы обновляем TestPane
и PaintPane
для поддержки модели ...
public class TestPane extends JPanel {
JButton left;
JButton right;
JPanel paintPane;
private DefaultShapeModel model;
public TestPane() {
model = new DefaultShapeModel();
JButton left = new JButton("left");
left.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
Point p = model.getPoint();
p.x--;
if (p.x > 0) {
p.x = 0;
}
model.setPoint(p);
}
});
JButton right = new JButton("right");
right.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Point p = model.getPoint();
p.x++;
if (p.x + 40 > paintPane.getWidth()) {
p.x = paintPane.getWidth() - 40;
}
model.setPoint(p);
}
});
paintPane = new PaintPane(model);
setLayout(new BorderLayout());
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
add(paintPane);
}
}
public class PaintPane extends JPanel {
private ShapeModel model;
public PaintPane(ShapeModel model) {
this.model = model;
this.model.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
});
}
public ShapeModel getModel() {
return model;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g1 = (Graphics2D) g;
Point p = getModel().getPoint();
g1.fillOval(p.x, p.y, 40, 40);
g1.setColor(Color.WHITE);
g1.drawOval(p.x, p.y, 40, 40);
}
}