在 JPanel 中强制调用 getPreferredSize()
Force-recall getPreferredSize() in JPanel
在我开始之前,我意识到我可能问错了问题,也许我正在尝试做的是一个非常糟糕的主意。如果是这种情况,请告诉我。
我有一个 class 覆盖 JPanel
方法 getPreferredSize()
和 returns 具有特定宽度和高度的自定义 Dimension
对象。但是,当我在方法中放入 debug println()
语句时,我注意到它只在创建时调用一次,之后就再也没有调用过。我需要调整 JPanel
的大小,因为它的内容发生变化(不,JScrollPane
绝对不是我要找的),但我不知道如何强制调用 getPreferredSize()
方法。
如果有人能向我解释我如何回忆起该方法,将不胜感激。提前谢谢大家!
这是我的代码的 MCVE:
package rotation;
import java.awt.*;
import java.awt.image.*;
import java.swing.*;
import java.swing.event.*;
public class Rotation {
private double theta;
public Rotation() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(new Rectangle(650, 650));
frame.setResizable(false);
Container contentPane = frame.getContentPane();
contentPane.setLayout(null);
BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) image.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, image.getWidth(), image.getHeight());
g2.dispose();
JPanel panel = new JPanel() {
@Override
public Dimension getPreferredSize() {
BufferedImage img = rotate(image, theta);
return new Dimension(img.getWidth(), img.getHeight());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int middleX = getWidth() / 2;
int middleY = getHeight() / 2;
BufferedImage img = rotate(image, theta);
g.drawImage(img, middleX - img.getWidth() / 2, middleY - img.getHeight() / 2, null);
}
};
contentPane.add(panel);
panel.setLocation(0, 0);
panel.setSize(panel.getPreferredSize());
JSlider slider = new JSlider(0, 360, 0);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
theta = slider.getValue();
panel.revalidate();
panel.repaint();
}
});
contentPane.add(slider);
slider.setLocation(0, 600);
slider.setSize(slider.getPreferredSize());
contentPane.revalidate();
contentPane.repaint();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public BufferedImage rotate(BufferedImage image, double angle) {
angle = Math.toRadians(angle);
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
int neww = (int)Math.floor(w * cos + h * sin), newh = (int) Math.floor(h * cos + w * sin);
GraphicsConfiguration gc = getDefaultConfiguration();
BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
Graphics2D g2 = result.createGraphics();
g2.translate((neww - w) / 2, (newh - h) / 2);
g2.rotate(angle, w / 2, h / 2);
g2.drawRenderedImage(image, null);
g2.dispose();
Graphics2D g = (Graphics2D) result.getGraphics();
g.setColor(Color.black);
g.drawRect(0, 0, neww - 1, newh - 1);
return result;
}
public GraphicsConfiguration getDefaultConfiguration() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return gd.getDefaultConfiguration();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Rotation();
}
});
}
}
正如我们之前讨论过的(当您有不同的用户 ID 时),在这种情况下,不使用 JPanel 或 JLabel 来保存精灵要容易得多,而是使用单个绘图 JPanel,并且然后在这个单一绘图 JPanel 中绘制所需的任何一侧的精灵。这是一个使用此精灵 sheet:
的示例
从this site获得。
这又是一个在 JPanel 的 paintComponent 方法中绘图并使用键绑定告诉移动方向的示例。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class Mcve3 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 640;
private static final int TIMER_DELAY = 50;
private int spriteX = 400;
private int spriteY = 320;
private SpriteDirection spriteDirection = SpriteDirection.RIGHT;
private MySprite sprite = null;
private Timer timer = null;
public Mcve3() {
try {
sprite = new MySprite(spriteDirection, spriteX, spriteY);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
setBackground(Color.WHITE);
setKeyBindings(SpriteDirection.LEFT, KeyEvent.VK_LEFT);
setKeyBindings(SpriteDirection.RIGHT, KeyEvent.VK_RIGHT);
setKeyBindings(SpriteDirection.FORWARD, KeyEvent.VK_DOWN);
setKeyBindings(SpriteDirection.AWAY, KeyEvent.VK_UP);
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
private void setKeyBindings(SpriteDirection dir, int keyCode) {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
KeyStroke keyPressed = KeyStroke.getKeyStroke(keyCode, 0, false);
KeyStroke keyReleased = KeyStroke.getKeyStroke(keyCode, 0, true);
inputMap.put(keyPressed, keyPressed.toString());
inputMap.put(keyReleased, keyReleased.toString());
actionMap.put(keyPressed.toString(), new MoveAction(dir, false));
actionMap.put(keyReleased.toString(), new MoveAction(dir, true));
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
sprite.draw(g);
}
private class MoveAction extends AbstractAction {
private SpriteDirection dir;
private boolean released;
public MoveAction(SpriteDirection dir, boolean released) {
this.dir = dir;
this.released = released;
}
@Override
public void actionPerformed(ActionEvent e) {
if (released) {
sprite.setMoving(false);
} else {
sprite.setMoving(true);
sprite.setDirection(dir);
}
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (sprite.isMoving()) {
sprite.tick();
}
repaint();
}
}
private static void createAndShowGui() {
Mcve3 mainPanel = new Mcve3();
JFrame frame = new JFrame("MCVE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MySprite {
private static final String SPRITE_SHEET_PATH = "http://"
+ "orig12.deviantart.net/7db3/f/2010/338/3/3/"
+ "animated_sprite_sheet_32x32_by_digibody-d3479l2.gif";
private static final int MAX_MOVING_INDEX = 4;
private static final int DELTA = 4;
private SpriteDirection direction;
private Map<SpriteDirection, Image> standingImgMap = new EnumMap<>(SpriteDirection.class);
private Map<SpriteDirection, List<Image>> movingImgMap = new EnumMap<>(SpriteDirection.class);
private int x;
private int y;
private boolean moving = false;
private int movingIndex = 0;
public MySprite(SpriteDirection direction, int x, int y) throws IOException {
this.direction = direction;
this.x = x;
this.y = y;
createSprites();
}
public void draw(Graphics g) {
Image img = null;
if (!moving) {
img = standingImgMap.get(direction);
} else {
img = movingImgMap.get(direction).get(movingIndex);
}
g.drawImage(img, x, y, null);
}
private void createSprites() throws IOException {
URL spriteSheetUrl = new URL(SPRITE_SHEET_PATH);
BufferedImage img = ImageIO.read(spriteSheetUrl);
// get sub-images (sprites) from the sprite sheet
// magic numbers for getting sprites from sheet, all obtained by trial and error
int x0 = 0;
int y0 = 64;
int rW = 32;
int rH = 32;
for (int row = 0; row < 4; row++) {
SpriteDirection dir = SpriteDirection.values()[row];
List<Image> imgList = new ArrayList<>();
movingImgMap.put(dir, imgList);
int rY = y0 + row * rH;
for (int col = 0; col < 5; col++) {
int rX = x0 + col * rW;
BufferedImage subImg = img.getSubimage(rX, rY, rW, rH);
if (col == 0) {
// first image is standing
standingImgMap.put(dir, subImg);
} else {
// all others are moving
imgList.add(subImg);
}
}
}
}
public SpriteDirection getDirection() {
return direction;
}
public void setDirection(SpriteDirection direction) {
if (this.direction != direction) {
setMoving(false);
}
this.direction = direction;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean isMoving() {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
if (!moving) {
movingIndex = 0;
}
}
public void tick() {
if (moving) {
switch (direction) {
case RIGHT:
x += DELTA;
break;
case LEFT:
x -= DELTA;
break;
case FORWARD:
y += DELTA;
break;
case AWAY:
y -= DELTA;
}
movingIndex++;
movingIndex %= MAX_MOVING_INDEX;
}
}
public int getMovingIndex() {
return movingIndex;
}
public void setMovingIndex(int movingIndex) {
this.movingIndex = movingIndex;
}
}
enum SpriteDirection {
FORWARD, LEFT, AWAY, RIGHT
}
以及使用您的代码的示例:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class Rotation2 extends JPanel {
private static final int PREF_W = 750;
private static final int PREF_H = PREF_W;
private BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
private double theta = 0.0;
private JSlider slider = new JSlider(0, 360, 0);
public Rotation2() {
Graphics2D g2 = (Graphics2D) image.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, image.getWidth(), image.getHeight());
g2.dispose();
slider.setMajorTickSpacing(90);
slider.setMinorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
theta = Math.toRadians(slider.getValue());
revalidate();
repaint();
}
});
JPanel bottomPanel = new JPanel();
bottomPanel.add(slider);
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
int x = PREF_W / 2;
int y = PREF_H / 2;
g2.rotate(theta, x, y);
int imgX = (PREF_W - image.getWidth()) / 2;
int imgY = (PREF_H - image.getHeight()) / 2;
g2.drawImage(image, imgX, imgY, this);
g2.dispose();
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Rotation2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Rotation2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
在我开始之前,我意识到我可能问错了问题,也许我正在尝试做的是一个非常糟糕的主意。如果是这种情况,请告诉我。
我有一个 class 覆盖 JPanel
方法 getPreferredSize()
和 returns 具有特定宽度和高度的自定义 Dimension
对象。但是,当我在方法中放入 debug println()
语句时,我注意到它只在创建时调用一次,之后就再也没有调用过。我需要调整 JPanel
的大小,因为它的内容发生变化(不,JScrollPane
绝对不是我要找的),但我不知道如何强制调用 getPreferredSize()
方法。
如果有人能向我解释我如何回忆起该方法,将不胜感激。提前谢谢大家!
这是我的代码的 MCVE:
package rotation;
import java.awt.*;
import java.awt.image.*;
import java.swing.*;
import java.swing.event.*;
public class Rotation {
private double theta;
public Rotation() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(new Rectangle(650, 650));
frame.setResizable(false);
Container contentPane = frame.getContentPane();
contentPane.setLayout(null);
BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) image.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, image.getWidth(), image.getHeight());
g2.dispose();
JPanel panel = new JPanel() {
@Override
public Dimension getPreferredSize() {
BufferedImage img = rotate(image, theta);
return new Dimension(img.getWidth(), img.getHeight());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int middleX = getWidth() / 2;
int middleY = getHeight() / 2;
BufferedImage img = rotate(image, theta);
g.drawImage(img, middleX - img.getWidth() / 2, middleY - img.getHeight() / 2, null);
}
};
contentPane.add(panel);
panel.setLocation(0, 0);
panel.setSize(panel.getPreferredSize());
JSlider slider = new JSlider(0, 360, 0);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
theta = slider.getValue();
panel.revalidate();
panel.repaint();
}
});
contentPane.add(slider);
slider.setLocation(0, 600);
slider.setSize(slider.getPreferredSize());
contentPane.revalidate();
contentPane.repaint();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public BufferedImage rotate(BufferedImage image, double angle) {
angle = Math.toRadians(angle);
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
int neww = (int)Math.floor(w * cos + h * sin), newh = (int) Math.floor(h * cos + w * sin);
GraphicsConfiguration gc = getDefaultConfiguration();
BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT);
Graphics2D g2 = result.createGraphics();
g2.translate((neww - w) / 2, (newh - h) / 2);
g2.rotate(angle, w / 2, h / 2);
g2.drawRenderedImage(image, null);
g2.dispose();
Graphics2D g = (Graphics2D) result.getGraphics();
g.setColor(Color.black);
g.drawRect(0, 0, neww - 1, newh - 1);
return result;
}
public GraphicsConfiguration getDefaultConfiguration() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return gd.getDefaultConfiguration();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Rotation();
}
});
}
}
正如我们之前讨论过的(当您有不同的用户 ID 时),在这种情况下,不使用 JPanel 或 JLabel 来保存精灵要容易得多,而是使用单个绘图 JPanel,并且然后在这个单一绘图 JPanel 中绘制所需的任何一侧的精灵。这是一个使用此精灵 sheet:
的示例从this site获得。
这又是一个在 JPanel 的 paintComponent 方法中绘图并使用键绑定告诉移动方向的示例。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class Mcve3 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 640;
private static final int TIMER_DELAY = 50;
private int spriteX = 400;
private int spriteY = 320;
private SpriteDirection spriteDirection = SpriteDirection.RIGHT;
private MySprite sprite = null;
private Timer timer = null;
public Mcve3() {
try {
sprite = new MySprite(spriteDirection, spriteX, spriteY);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
setBackground(Color.WHITE);
setKeyBindings(SpriteDirection.LEFT, KeyEvent.VK_LEFT);
setKeyBindings(SpriteDirection.RIGHT, KeyEvent.VK_RIGHT);
setKeyBindings(SpriteDirection.FORWARD, KeyEvent.VK_DOWN);
setKeyBindings(SpriteDirection.AWAY, KeyEvent.VK_UP);
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
private void setKeyBindings(SpriteDirection dir, int keyCode) {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
KeyStroke keyPressed = KeyStroke.getKeyStroke(keyCode, 0, false);
KeyStroke keyReleased = KeyStroke.getKeyStroke(keyCode, 0, true);
inputMap.put(keyPressed, keyPressed.toString());
inputMap.put(keyReleased, keyReleased.toString());
actionMap.put(keyPressed.toString(), new MoveAction(dir, false));
actionMap.put(keyReleased.toString(), new MoveAction(dir, true));
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
sprite.draw(g);
}
private class MoveAction extends AbstractAction {
private SpriteDirection dir;
private boolean released;
public MoveAction(SpriteDirection dir, boolean released) {
this.dir = dir;
this.released = released;
}
@Override
public void actionPerformed(ActionEvent e) {
if (released) {
sprite.setMoving(false);
} else {
sprite.setMoving(true);
sprite.setDirection(dir);
}
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (sprite.isMoving()) {
sprite.tick();
}
repaint();
}
}
private static void createAndShowGui() {
Mcve3 mainPanel = new Mcve3();
JFrame frame = new JFrame("MCVE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MySprite {
private static final String SPRITE_SHEET_PATH = "http://"
+ "orig12.deviantart.net/7db3/f/2010/338/3/3/"
+ "animated_sprite_sheet_32x32_by_digibody-d3479l2.gif";
private static final int MAX_MOVING_INDEX = 4;
private static final int DELTA = 4;
private SpriteDirection direction;
private Map<SpriteDirection, Image> standingImgMap = new EnumMap<>(SpriteDirection.class);
private Map<SpriteDirection, List<Image>> movingImgMap = new EnumMap<>(SpriteDirection.class);
private int x;
private int y;
private boolean moving = false;
private int movingIndex = 0;
public MySprite(SpriteDirection direction, int x, int y) throws IOException {
this.direction = direction;
this.x = x;
this.y = y;
createSprites();
}
public void draw(Graphics g) {
Image img = null;
if (!moving) {
img = standingImgMap.get(direction);
} else {
img = movingImgMap.get(direction).get(movingIndex);
}
g.drawImage(img, x, y, null);
}
private void createSprites() throws IOException {
URL spriteSheetUrl = new URL(SPRITE_SHEET_PATH);
BufferedImage img = ImageIO.read(spriteSheetUrl);
// get sub-images (sprites) from the sprite sheet
// magic numbers for getting sprites from sheet, all obtained by trial and error
int x0 = 0;
int y0 = 64;
int rW = 32;
int rH = 32;
for (int row = 0; row < 4; row++) {
SpriteDirection dir = SpriteDirection.values()[row];
List<Image> imgList = new ArrayList<>();
movingImgMap.put(dir, imgList);
int rY = y0 + row * rH;
for (int col = 0; col < 5; col++) {
int rX = x0 + col * rW;
BufferedImage subImg = img.getSubimage(rX, rY, rW, rH);
if (col == 0) {
// first image is standing
standingImgMap.put(dir, subImg);
} else {
// all others are moving
imgList.add(subImg);
}
}
}
}
public SpriteDirection getDirection() {
return direction;
}
public void setDirection(SpriteDirection direction) {
if (this.direction != direction) {
setMoving(false);
}
this.direction = direction;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public boolean isMoving() {
return moving;
}
public void setMoving(boolean moving) {
this.moving = moving;
if (!moving) {
movingIndex = 0;
}
}
public void tick() {
if (moving) {
switch (direction) {
case RIGHT:
x += DELTA;
break;
case LEFT:
x -= DELTA;
break;
case FORWARD:
y += DELTA;
break;
case AWAY:
y -= DELTA;
}
movingIndex++;
movingIndex %= MAX_MOVING_INDEX;
}
}
public int getMovingIndex() {
return movingIndex;
}
public void setMovingIndex(int movingIndex) {
this.movingIndex = movingIndex;
}
}
enum SpriteDirection {
FORWARD, LEFT, AWAY, RIGHT
}
以及使用您的代码的示例:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@SuppressWarnings("serial")
public class Rotation2 extends JPanel {
private static final int PREF_W = 750;
private static final int PREF_H = PREF_W;
private BufferedImage image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_ARGB);
private double theta = 0.0;
private JSlider slider = new JSlider(0, 360, 0);
public Rotation2() {
Graphics2D g2 = (Graphics2D) image.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, image.getWidth(), image.getHeight());
g2.dispose();
slider.setMajorTickSpacing(90);
slider.setMinorTickSpacing(10);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
theta = Math.toRadians(slider.getValue());
revalidate();
repaint();
}
});
JPanel bottomPanel = new JPanel();
bottomPanel.add(slider);
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
int x = PREF_W / 2;
int y = PREF_H / 2;
g2.rotate(theta, x, y);
int imgX = (PREF_W - image.getWidth()) / 2;
int imgY = (PREF_H - image.getHeight()) / 2;
g2.drawImage(image, imgX, imgY, this);
g2.dispose();
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Rotation2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Rotation2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}