本文介绍了如何在Jframe中的jpanel中添加imagepanel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试添加一个将 JPanel 扩展到另一个 JPanel 的图像面板.这对我来说效果不佳.图像面板的绘制功能不会在 Jpanel 内部调用,但在 JFrame 中可以正常工作.任何想法或帮助将不胜感激.
I'm trying to add an imagepanel which extends JPanel to another JPanel. Which is not working well for me. The paint function of image panel don't get invoked inside Jpanel but works fine in JFrame. Any ideas or help will be appreciated.
推荐答案
让我们从...开始
- 不要使用
getGraphics
.这不是如何执行自定义绘画.getGraphics
可能返回 null
并且充其量只是一个快照,在下一个绘制周期发生时将被丢弃. JPanel
已经有 getWidth
、getHeight
和 setSize
方法,你永远不需要重写它们.相反,您应该重写 getPreferredSize
并返回父布局管理器可以使用的大小提示.- 如果你创建了一个
Graphics
上下文,你应该 dispose
它.在您的 paint
方法中,您使用 gh.create
,这会消耗资源,并且在某些系统下,直到 Graphics
上下文被释放,它可能实际上没有画任何东西. - 不要覆盖
paint
,而是使用 paintComponent
- 请勿修改剪辑矩形.说真的,这会给您带来比您想象的更多的问题.
- 不要在没有充分理由的情况下使用
null
布局管理器. JPanel
有一个 setBounds
方法,而在一般情况下,你不应该使用它,因为你已经扔掉了布局管理器,你应该使用它.
- Don't use
getGraphics
. This is not how to perform custom painting. getGraphics
may return null
and is, at best, a snapshot, which will be discard when the next paint cycle occurs.
JPanel
already has getWidth
, getHeight
and setSize
methods, you should never have a need to overridden them. Instead, you should override getPreferredSize
and return a size hint back that the parent layout manager can use.
- If you create a
Graphics
context, you should dispose
of it. In your paint
method, you use gh.create
, this is consuming resources and under some systems, until the Graphics
context is disposed, it may not actually paint anything.
- Don't override
paint
, instead use paintComponent
- DO NOT modify the clip rectangle. Seriously, this is going to cause you more issues then you can imagine.
- Don't use
null
layout managers without EXTREMELY good reason.
JPanel
has a setBounds
method, while, under normal circumstances, you shouldn't need to use it, since you've thrown away the layout manager, you should use it.
基本上,您已经放弃了 JPanel
的所有内部工作,这些工作使绘制系统知道它应该实际绘制您的面板
Basically, you've discard all the inner workings of the JPanel
that enable the paint system to know that it should actually paint your panel
更新示例
举个例子……
我没有使用剪辑,而是使用遮罩技术,并在源图像上遮盖我想要的形状.我还缓冲了结果,这应该使它更保守的内存以及更快的渲染
Instead of using the clip, I use a masking technique, and mask the shape I want over the source image. I also buffer the result, which should make it more memory conservative as well as render faster
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class ImagePaneExample {
public static void main(String[] args) {
new ImagePaneExample();
}
public ImagePaneExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
BufferedImage img = ImageIO.read(new File("C:\hold\thumbnails\2005-09-29-3957.jpeg"));
ImagePane imgPane = new ImagePane();
imgPane.setImage(img);
imgPane.setRounded(true);
imgPane.setBorder(new EmptyBorder(20, 20, 20, 20));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(imgPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
public class ImagePane extends JPanel {
private BufferedImage img;
private BufferedImage renderImg;
private boolean rounded;
public ImagePane() {
}
public void setRounded(boolean value) {
if (value != rounded) {
rounded = value;
renderImg = null;
firePropertyChange("rounded", !rounded, rounded);
repaint();
}
}
public boolean isRounded() {
return rounded;
}
public void setImage(BufferedImage value) {
if (value != img) {
BufferedImage old = img;
img = value;
renderImg = null;
firePropertyChange("image", old, img);
repaint();
}
}
public BufferedImage getImage() {
return img;
}
@Override
public Dimension getPreferredSize() {
Dimension size = img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
Insets insets = getInsets();
size.width += (insets.left + insets.right);
size.height += (insets.top + insets.bottom);
return size;
}
protected void applyQualityRenderHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
protected BufferedImage getImageToRender() {
if (renderImg == null) {
BufferedImage source = getImage();
if (source != null) {
if (isRounded()) {
BufferedImage mask = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, mask.getWidth(), mask.getHeight());
g2d.setBackground(new Color(255, 255, 255, 255));
g2d.fillRoundRect(0, 0, mask.getWidth(), mask.getHeight(), 40, 40);
g2d.dispose();
BufferedImage comp = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = comp.createGraphics();
applyQualityRenderHints(g2d);
g2d.setBackground(new Color(255, 255, 255, 0));
g2d.clearRect(0, 0, source.getWidth(), source.getHeight());
g2d.drawImage(source, 0, 0, this);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
g2d.drawImage(mask, 0, 0, this);
g2d.dispose();
renderImg = comp;
} else {
renderImg = source;
}
}
}
return renderImg;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage img = getImageToRender();
System.out.println(img);
if (img != null) {
Insets insets = getInsets();
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int x = ((width - img.getWidth()) / 2);
int y = ((height - img.getHeight()) / 2);
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
}
我建议您阅读一下使用 Swing 创建 UI,在特别是关于布局管理器的部分,以及 执行自定义绘画 和 在 AWT 和 Swing 中绘画
I'd recommend some more reading through Creating a UI with Swing, in particular the section on layout managers, as well as Performing Custom Painting and Painting in AWT and Swing
这篇关于如何在Jframe中的jpanel中添加imagepanel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!