旋转球失去锋利和颜色

package testIDE; import java.awt.BorderLayout; import java.awt.Graphics2D; import java.awt.GridBagLayout; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import Utils.MyJFrame; public class ExampleClass { public static void main(String[] args) { JFrame ballRotate = new BallRotate(); } } class BallRotate extends MyJFrame { ArrayList degree = new ArrayList(); BufferedImage backGroundImage = getBufferedImage("testIDE/buttonDefaultImage.jpg"); JLabel backGroundLabel = new JLabel(new ImageIcon(backGroundImage)); BufferedImage footballImage = getBufferedImage("testIDE/Tennis_Ball.png"); int x = 0; public BallRotate() { footballImage=getScaledImage(250, 250, footballImage); BufferedImage rotatedImage = footballImage; setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new GridBagLayout()); setLabel(); add(backGroundLabel); pack(); centeringWindow(); setVisible(true); setArray(); while (true) { setDelay(60); rotatedImage = rotateImage(rotatedImage, x); setMyFuckingLabel(rotatedImage); x += 10; if (x == 10000) { break; } } } private void setArray() { for (int i = 0; i <= 360; i += 40) { degree.add(i); } } private void setLabel() { JPanel footBallPanel = new JPanel(new BorderLayout()); JLabel footBallLabel = new JLabel(new ImageIcon(footballImage)); footBallPanel.add(footBallLabel); borderingJPanel(footBallPanel, null, null); backGroundLabel.setLayout(new GridBagLayout()); backGroundLabel.add(footBallPanel); } private BufferedImage rotateImage(BufferedImage buffImage, int degree) { BufferedImage rotatedImage = null; AffineTransform affineTransform = AffineTransform.getRotateInstance( Math.toRadians(15*Math.PI), buffImage.getWidth() / 2, buffImage.getHeight() / 2); System.out.println(degree*Math.toRadians(1)); rotatedImage = new BufferedImage(buffImage.getWidth(), buffImage.getHeight(), buffImage.getType()); Graphics2D g = (Graphics2D) rotatedImage.getGraphics(); g.setTransform(affineTransform); g.drawImage(buffImage, 0, 0, null); return rotatedImage; } public void setMyLabel(BufferedImage rotatedBuffImage) { JLabel backgroundlabel = (JLabel) getContentPane().getComponent(0); JPanel footBallPanel = (JPanel) backgroundlabel.getComponent(0); JLabel footBallLabel = (JLabel) footBallPanel.getComponent(0); footBallLabel.setIcon(new ImageIcon(rotatedBuffImage)); } } 

在此处输入图像描述在此处输入图像描述在此处输入图像描述

如你所见,我的旋转网球失去了他的形状和着色。 似乎颜色也在旋转。 为什么? 有没有办法防止这种情况? 我发布了生成上述对话框的代码。

谢谢你的帮助。

所以一大堆问题……

  • 在一个步骤中缩放图像绝不是一个好主意(除非您只缩放50%)。 Java也不是特别擅长。 你可以雇佣一些技巧,比如使用多步骤(在示例中演示)或使用像imgscalr这样的外部库。 有关详细信息,请参阅Image.getScaledInstance()的Perils 。
  • 您应该避免将效果应用于相同的图像倍增时间,这只会使更改复杂化并降低图像的质量。 相反,尽可能保持主图像尽可能接近原始图像并使用它,因此您始终从相同的起点开始。
  • Swing不是线程安全的。 这意味着三件事。 首先,你不应该在可能阻塞它的事件调度线程的上下文中做任何事情,比如无限循环。 其次,您应该只在EDT的上下文中更改UI组件的状态,第三,您应该确保从EDT的上下文中创建UI。 有关详细信息,请参阅Swing和初始线程中的 并发性 …
  • 除了直线水平线或垂直线之外的任何东西看起来都很漂亮……在默认渲染设置下是普通的。 您将需要提供一些RenderingHints来增强结果

这就提出了如何在Swing中制作动画的问题? 好吧,你有两个基本选项,你可以使用某种Thread ,这需要你手动将更新同步回EDT,或者你可以使用Swing javax.swing.Timer ,它允许你定期调度回调这是在美国东部时间范围内触发的。 看看如何使用Swing Timers了解更多详情……

RotateBall

 import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics2D; import java.awt.GridBagLayout; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class BallRotate { public static void main(String[] args) { new BallRotate(); } public BallRotate() { 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 BufferedImage master; private JLabel ball; private BufferedImage rotatedImage; private float angle = 0; private float delta = 5; public TestPane() { setLayout(new GridBagLayout()); try { master = ImageIO.read(getClass().getResource("/Ball.png")); master = getScaledInstanceToFit(master, new Dimension(250, 250)); } catch (IOException ex) { ex.printStackTrace(); } ImageIcon icon = new ImageIcon(getRotatedImage(0)); ball = new JLabel(icon); add(ball); Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { angle += delta; // ball.setIcon(new ImageIcon(getRotatedImage(delta))); getRotatedImage(angle); ball.repaint(); System.out.println(angle); } }); addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { timer.start(); } }); } @Override public Dimension getPreferredSize() { return new Dimension(400, 400); } protected BufferedImage getRotatedImage(float degree) { if (rotatedImage == null) { rotatedImage = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB); } AffineTransform affineTransform = AffineTransform.getRotateInstance( Math.toRadians(degree), rotatedImage.getWidth() / 2, rotatedImage.getHeight() / 2); Graphics2D g = (Graphics2D) rotatedImage.getGraphics(); g.setBackground(new Color(255, 255, 255, 0)); g.clearRect(0, 0, rotatedImage.getWidth(), rotatedImage.getHeight()); g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); g.setTransform(affineTransform); g.drawImage(master, 0, 0, null); g.dispose(); return rotatedImage; } } public static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor) { return getScaledInstance(img, dScaleFactor, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); } protected static BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) { BufferedImage imgScale = img; int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor); int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor); // System.out.println("Scale Size = " + iImageWidth + "x" + iImageHeight); if (dScaleFactor < 1.0d) { imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); } return imgScale; } protected static BufferedImage getScaledDownInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; if (targetHeight > 0 || targetWidth > 0) { int w, h; if (higherQuality) { // Use multi-step technique: start with original size, then // scale down in multiple passes with drawImage() // until the target size is reached w = img.getWidth(); h = img.getHeight(); } else { // Use one-step technique: scale directly from original // size to target size with a single drawImage() call w = targetWidth; h = targetHeight; } do { if (higherQuality && w > targetWidth) { w /= 2; if (w < targetWidth) { w = targetWidth; } } if (higherQuality && h > targetHeight) { h /= 2; if (h < targetHeight) { h = targetHeight; } } // if (w <= 0) w = 1; // if (h <= 0) h = 1; BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; } while (w != targetWidth || h != targetHeight); } else { ret = new BufferedImage(1, 1, type); } return ret; } public static double getScaleFactor(int iMasterSize, int iTargetSize) { return (double) iTargetSize / (double) iMasterSize; } public static double getScaleFactorToFit(Dimension original, Dimension toFit) { double dScale = 1d; if (original != null && toFit != null) { double dScaleWidth = getScaleFactor(original.width, toFit.width); double dScaleHeight = getScaleFactor(original.height, toFit.height); dScale = Math.min(dScaleHeight, dScaleWidth); } return dScale; } public static double getScaleFactorToFit(BufferedImage img, Dimension size) { double dScale = 1; if (img != null) { int imageWidth = img.getWidth(); int imageHeight = img.getHeight(); dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size); } return dScale; } public static BufferedImage getScaledInstanceToFit(BufferedImage img, Dimension size) { double scaleFactor = getScaleFactorToFit(img, size); return getScaledInstance(img, scaleFactor); } }