我正在尝试用 Java 开发图像编辑器。我的图像编辑器的 Java 图像实现的一部分是加载图像并绘制一些形状,以及执行旋转、缩放等。
我正在使用 JLabel 加载图像,但有没有办法使用 JLabel 在图像上绘制和应用转换?我在网上找到的所有示例都使用了 JPanel。
你真的需要看看Java2D turorial。您应该在 上绘制图像Graphics2D
并旋转和缩放图像Graphics2D
。
不要使用JLabel
,因为
J-* 组件很重(尽管JLabel
很轻)。您可以在 JLabel 中添加图标,但一般情况下,它们用于稳定的情况,不会频繁和随意更改。在 J-* 组件上绘画会带来太多的变化。
如果添加大量组件,也会降低性能。Graphics
(每个组件都会在属于它的单独对象中绘制自己,并且它的容器会将它们全部绘制出来,并且布局也很重要。)
另一个缺点是有时很难甚至不可能对一个组件或几个组件一起进行一些操作。例如,如果要添加两张图片并将它们分组怎么办?你需要 2JLabel
秒,1 JPanel
(也许)。那么如果你想在这两个图像上画一条线并再次分组呢?
以下是基本步骤:
paint
或paintComponent
方法;Graphics
实例转换为Graphics2D
;Graphics2D
;Graphics2D
;Graphics2D
使用了各种各样的类,例如Graphics2D
, AffineTransform
, RenderingHints
, BufferedImage
,Shape
等,甚至更多的方法。我无法描述这里的一切。只需阅读 Java2D 教程。它为您提供 API 的概述,并告诉您如何执行这些操作。
我正在使用 JLabel 加载图像,但是否可以使用 JLabel 在图像上绘制和应用转换?
不确定你的意思。
但是您可以简单地获取JLabel
(这是正在显示的图像)的图标,对我们转换为的图标执行需要执行的操作,BufferedImage
而不是通过重新应用图标setIcon(..)
。
这是一个简短的示例,希望对您有所帮助:
JLabel
BufferedImage
在旋转-45度之前带有图标/ :
JLabel
获得图标后,通过以下方式旋转并重新应用setIcon(...)
:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Test {
private static JLabel imageLabel;
private static JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
imageLabel = new JLabel(new ImageIcon(createImage()));//set image of JLabel
panel.add(imageLabel);
frame.add(panel);
frame.pack();
frame.setVisible(true);
startImageChangeTimer();//creates a timer which will rotate image after 5 seconds
}
private void startImageChangeTimer() {
Timer timer = new Timer(5000, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent ae) {
//get JLabel Icon and convert to BufferedImage
BufferedImage img = getBufferedImageOfIcon(imageLabel.getIcon(), imageLabel.getWidth(), imageLabel.getHeight());
//rotate the image
img = createTransformedImage(img, -45);
//change the labels image
imageLabel.setIcon(new ImageIcon(img));
frame.pack();//resize frame accrodingly
}
});
timer.setRepeats(false);
timer.start();
}
});
}
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;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
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;
}
}
更新:
我确实倾向于同意@shuangwhywhy。将图像绘制到JPanel
viapaintComponent(Graphics g)
因此您可以简单地调整图像大小并将其设置为JPanel
图像(通过getter 和 setter),然后调用repaint()
以显示更改。
这是简单的图像编辑器
/*Arpana*/
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp()
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
public static void main(String arg[]) {
new ConvolveApp();
class ButtonListener implements ActionListener
public void actionPerformed(ActionEvent e)
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton))
displayPanel.sharpen();
displayPanel.repaint();
else if (button.equals(blurringButton))
displayPanel.blur();
displayPanel.repaint();
else if (button.equals(edButton))
displayPanel.edgeDetect();
displayPanel.repaint();
else if (button.equals(resetButton))
displayPanel.reset();
displayPanel.repaint();
class CPanel extends JLabel
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest;
BufferedImage bi;
Graphics2D big;
CPanel()
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
public void loadImage()
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try
mt.waitForAll();
if (displayImage.getWidth(this) == -1)
System.out.println("No jpg file");
System.exit(0);
public void createBufferedImages()
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
public void sharpen()
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void blur()
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
public void edgeDetect()
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
public void reset()
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
public void update(Graphics g)
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
/* Arpana*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class ConvolveApp extends JFrame {
CPanel displayPanel;
JButton sharpenButton, blurringButton, edButton, resetButton;
public ConvolveApp() {
super();
Container container = getContentPane();
displayPanel = new CPanel();
container.add(displayPanel);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
panel
.setBorder(new TitledBorder(
"Click a Button to Perform the Associated Operation and Reset..."));
sharpenButton = new JButton("Sharpen");
sharpenButton.addActionListener(new ButtonListener());
blurringButton = new JButton("Blur");
blurringButton.addActionListener(new ButtonListener());
edButton = new JButton("Edge Detect");
edButton.addActionListener(new ButtonListener());
resetButton = new JButton("Reset");
resetButton.addActionListener(new ButtonListener());
panel.add(sharpenButton);
panel.add(blurringButton);
panel.add(edButton);
panel.add(resetButton);
container.add(BorderLayout.SOUTH, panel);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(displayPanel.getWidth(), displayPanel.getHeight() + 10);
setVisible(true);
}
public static void main(String arg[]) {
new ConvolveApp();
}
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
if (button.equals(sharpenButton)) {
displayPanel.sharpen();
displayPanel.repaint();
} else if (button.equals(blurringButton)) {
displayPanel.blur();
displayPanel.repaint();
} else if (button.equals(edButton)) {
displayPanel.edgeDetect();
displayPanel.repaint();
} else if (button.equals(resetButton)) {
displayPanel.reset();
displayPanel.repaint();
}
}
}
}
class CPanel extends JLabel {
Image displayImage;
BufferedImage biSrc;
BufferedImage biDest; // Destination image is mandetory.
BufferedImage bi; // Only an additional reference.
Graphics2D big;
CPanel() {
setBackground(Color.black);
loadImage();
setSize(displayImage.getWidth(this), displayImage.getWidth(this));
createBufferedImages();
bi = biSrc;
}
public void loadImage() {
displayImage = Toolkit.getDefaultToolkit().getImage("Arpana.jpg");
MediaTracker mt = new MediaTracker(this);
mt.addImage(displayImage, 1);
try {
mt.waitForAll();
} catch (Exception e) {
System.out.println("Exception while loading.");
}
if (displayImage.getWidth(this) == -1) {
System.out.println("No jpg file");
System.exit(0);
}
}
public void createBufferedImages() {
biSrc = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
big = biSrc.createGraphics();
big.drawImage(displayImage, 0, 0, this);
biDest = new BufferedImage(displayImage.getWidth(this), displayImage
.getHeight(this), BufferedImage.TYPE_INT_RGB);
}
public void sharpen() {
float data[] = { -1.0f, -1.0f, -1.0f, -1.0f, 9.0f, -1.0f, -1.0f, -1.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void blur() {
float data[] = { 0.0625f, 0.125f, 0.0625f, 0.125f, 0.25f, 0.125f,
0.0625f, 0.125f, 0.0625f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void edgeDetect() {
float data[] = { 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
-1.0f };
Kernel kernel = new Kernel(3, 3, data);
ConvolveOp convolve = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
convolve.filter(biSrc, biDest);
bi = biDest;
}
public void reset() {
big.setColor(Color.black);
big.clearRect(0, 0, bi.getWidth(this), bi.getHeight(this));
big.drawImage(displayImage, 0, 0, this);
bi = biSrc;
}
public void update(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
paintComponent(g);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(bi, 0, 0, this);
}
}
我只听说有人使用 JLabels 来完成此任务。我建议将 显示BufferedImage
为 JLabel 的背景。当用户对图像进行编辑时,编辑图像(如果您还没有用于处理图像的库,我强烈推荐imgscalr)并将其重新应用为 JLabel 的背景(如果它不自动更新) .