Ваша основная проблема прямо здесь ...
Graphics2D g2d = (Graphics2D) g;
g2d.translate(getWidth() / 2, getHeight() / 2);
AffineTransform at = AffineTransform.getTranslateInstance(0, 0);
Контекст Graphics
, передаваемый вашему компоненту, является общим ресурсом, он передается ВСЕМ компонентам, окрашенным во время цикла рисования, это означает, что когда вы изменяете такие вещи, как исходная точка и поворот, это влияет на ВСЕ компоненты, окрашенные после это.
Вместо этого вам следует создать копию состояния Graphics
, прежде чем применять изменения, при этом исходное состояние не изменится
Graphics2D g2d = (Graphics2D) g.create();
g2d.translate(getWidth() / 2, getHeight() / 2);
AffineTransform at = AffineTransform.getTranslateInstance(0, 0);
//...
g2d.dispose();
Ваша вторая ошибка ...
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
update();
}
}, 0, (long) Math.round(motion.getFrameTime() * 1000));
Swing не является поточно-ориентированным, и обновление пользовательского интерфейса или состояния, от которого зависит пользовательский интерфейс, может привести к неожиданным и трудным для диагностики результатам.
В этом случае у вас есть два варианта: использовать Swing Timer
или SwingWorker
в зависимости от ваших потребностей.
Взгляните на Параллельность в Swing для более подробной информации
Другая проблема - at.rotate(Math.toRadians(90), Math.toRadians(90), Math.toRadians(90));
. Это просто не имеет смысла.
В документации указано
public void rotate(double theta,
double anchorx,
double anchory)
* +1032 * сцепляется это преобразование с преобразованием, который вращается вокруг координаты опорной точки. это
операция эквивалентна переводу координат, так что
точка привязки находится в начале координат (S1), затем вращая их вокруг нового
происхождение (S2) и, наконец, перевод, так что промежуточный источник
восстанавливается до координат исходной точки привязки (S3). это
операция эквивалентна следующей последовательности вызовов:
translate(anchorx, anchory); // S3: final translation
rotate(theta); // S2: rotate around anchor
translate(-anchorx, -anchory); // S1: translate anchor to origin Rotating by a positive angle theta rotates points on the
положительная ось X в направлении положительной оси Y. Обратите внимание также на обсуждение
обработки поворотов на 90 градусов выше.
Параметры:
theta
- угол
вращение в радианах
anchorx
- координата X
опорная точка вращения
anchory
- координата Y вращения
опорная точка
Что это говорит о том, что второй и третий параметры фактически являются точкой, вокруг которой происходит вращение. В вашем случае at.rotate(Math.toRadians(90), 0, 0);
, вероятно, то, что вам действительно нужно.
Использование Graphics#create
![Happy, happy, joy, joy](https://i.stack.imgur.com/LCUhT.gif)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 {
private double angle;
public TestPane() {
setLayout(new GridBagLayout());
for (int index = 0; index < 5; index++) {
add(new JButton("Here"));
}
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
angle += 0.01;
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
//Graphics2D g2d = (Graphics2D) g;
g2d.translate(getWidth() / 2, getHeight() / 2);
AffineTransform at = AffineTransform.getTranslateInstance(0, 0);
at.rotate(Math.toRadians(90), 0, 0);
g2d.drawRect(-50, -50, 100, 100);
g2d.setColor(Color.RED);
g2d.rotate(angle, 0, 0);
g2d.drawRect(-100, -100, 200, 200);
g2d.dispose();
}
}
}
Не используется Graphics#create
![Boowho](https://i.stack.imgur.com/GeSFv.gif)
О, где, о, где мои кнопки - вероятно, повернутые на 90 градусов вокруг центральной точки контейнера, основываясь на изменениях, которые вы внесли в контекст Graphics
, так что теперь они, вероятно, за пределами экрана