我想知道如何使用JLabel组件的paintComponent()方法旋转矩形图像并正确设置其新的宽度和高度?
我尝试过旋转(请参见附图),但图像的比例变大,而JLabel的比例保持不变,这使得图像超出了JLabel的边界或其他什么问题:S。所以我的问题是如何以更优化的方式动态地设置图像的新宽度和高度到组件中?
我想知道如何使用JLabel组件的paintComponent()方法旋转矩形图像并正确设置其新的宽度和高度?
我尝试过旋转(请参见附图),但图像的比例变大,而JLabel的比例保持不变,这使得图像超出了JLabel的边界或其他什么问题:S。所以我的问题是如何以更优化的方式动态地设置图像的新宽度和高度到组件中?
对MadProgrammers的评论和链接点赞。
使用链接中的方法(稍作修改,省略了对GraphicsConfiguration
、drawRenderImage(..)
的使用,并更改了变量名):
//https://dev59.com/SVHTa4cB1Zd3GeqPU9AL
public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int originalWidth = image.getWidth();
int originalHeight = image.getHeight();
int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = rotatedBI.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotatedBI;
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RotateImage {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MyRotatableImage(createImage(), -45));
frame.pack();
frame.setVisible(true);
}
});
}
public static BufferedImage createImage() {
BufferedImage img = new BufferedImage(100, 50, BufferedImage.TRANSLUCENT);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Calibri", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
String text = "Hello world";
int textWidth = fm.stringWidth(text);
g2d.drawString(text, (img.getWidth() / 2) - textWidth / 2, img.getHeight() / 2);
g2d.dispose();
return img;
}
}
class MyRotatableImage extends JPanel {
private BufferedImage transformedImage;
public MyRotatableImage(BufferedImage img, int angle) {
transformedImage = createTransformedImage(img, angle);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(transformedImage, 0, 0, null);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(transformedImage.getWidth(), transformedImage.getHeight());
}
//https://dev59.com/SVHTa4cB1Zd3GeqPU9AL
public static BufferedImage createTransformedImage(BufferedImage image, double angle) {
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int originalWidth = image.getWidth();
int originalHeight = image.getHeight();
int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = rotatedBI.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotatedBI;
}
}
参考资料:
repaint(int x,int y,int w,int h)
来优化绘图过程,可以参考这里:Refining the Design。 - David Kroukamp好的,所以您希望JLabel保持其尺寸并调整图像大小。
您可能已经在使用仿射变换,因此可以使用一些三角函数和min / max来查找旋转图像的AABB。适当缩放(我假设您已经使用仿射变换进行旋转)
编辑:
AABB = 轴对齐边界框,其边缘对应于旋转图像的最小/最大x,y坐标。只是更简洁地说事情。
好的,我尝试了David Kroukamp给我的示例。谢谢你,David,你指引了我正确的方向。我认为这是一个非常好的片段可以借鉴。
public static BufferedImage rotateImage(Image image, int angle)
{
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int originalWidth = image.getWidth(null);
int originalHeight = image.getHeight(null);
int newWidth = (int) Math.floor(originalWidth * cos + originalHeight * sin);
int newHeight = (int) Math.floor(originalHeight * cos + originalWidth * sin);
BufferedImage rotatedBI = new BufferedImage(newWidth, newHeight, BufferedImage.TRANSLUCENT);
Graphics2D g2d = rotatedBI.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate((newWidth - originalWidth) / 2, (newHeight - originalHeight) / 2);
g2d.rotate(angle, originalWidth / 2, originalHeight / 2);
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
return rotatedBI;
}
我测试了这个代码片段,结果图像及其组件的比例确实非常动态地改变了。 但是我得到的结果组件宽度总是比内部图像略宽:S
例如,这里是我旋转45度角的图像版本。
...从蓝色背景中可以看出,它的宽度并不完全适合周围的白色图像...实际上,我正在寻找某种标准的Java图像处理旋转解决方案,但我找不到 :(所以我必须深入挖掘问题,至少找出如何解决'更宽的效果'并避免每次重绘都创建新的BufferedImage对象...
好吧,经过我的研究,我尝试编写一些自己的旋转代码。在这里:
>已测试
public static void rotateImage(Graphics g, Image image,int tilt,JComponent component)
{
// create the transform, note that the transformations happen
// in reversed order (so check them backwards)
AffineTransform at = new AffineTransform();
//5. modify component scale ...
double sin = Math.abs(Math.sin(Math.toRadians(tilt)));
double cos = Math.abs(Math.cos(Math.toRadians(tilt)));
int w=image.getWidth(null);
int h=image.getHeight(null);
int newW=(int) Math.floor(w * cos + h * sin);
int newH=(int) Math.floor(h * cos + w * sin);
component.setSize(newW, newH);
int width=component.getWidth();
int height=component.getHeight();
// 4. translate it to the center of the component
at.translate(width / 2, height / 2);
// 3. do the actual rotation
at.rotate(Math.toRadians(tilt));
// 2. just a scale because this image is big
// at.scale(1, 1);
// 1. translate the object so that you rotate it around the
// center (easier :))
at.translate(-image.getWidth(null)/2, -image.getHeight(null)/2);
// draw the image
((Graphics2D) g).drawImage(image, at, null);
}
...所以旋转-30度倾斜的结果图像看起来像这样
我非常希望这个技巧能够帮助你解决问题 :)
感谢大家的帮助