Java JPanel-用新的较小图像替换当前显示的图像时出现问题
我正在尝试创建一个图形组件,允许我在选定的图像上绘制一个矩形(必须使用拖放操作绘制矩形):该组件的目的是获取绘制的矩形的坐标和大小;第二个目标是提供一个可以轻松集成到图形用户界面中的组件 的作者创建了Java JPanel-用新的较小图像替换当前显示的图像时出现问题,java,image,swing,Java,Image,Swing,我正在尝试创建一个图形组件,允许我在选定的图像上绘制一个矩形(必须使用拖放操作绘制矩形):该组件的目的是获取绘制的矩形的坐标和大小;第二个目标是提供一个可以轻松集成到图形用户界面中的组件 的作者创建了JLabel的子类以绘制图像,然后他们向该子类的实例添加了MouseInputAdapter,以处理矩形的绘制 我受到这个例子的启发,不同的是我创建了一个JPanelclass的子类:我将它命名为FigurePanelclass。然后我做了一些更改,以提供以下功能: 如果图像大于FigurePan
JLabel
的子类以绘制图像,然后他们向该子类的实例添加了MouseInputAdapter
,以处理矩形的绘制
我受到这个例子的启发,不同的是我创建了一个JPanel
class的子类:我将它命名为FigurePanel
class。然后我做了一些更改,以提供以下功能:
- 如果图像大于
的实例,则必须显示滚动条李>FigurePanel
- 如果图像小于
,则此图像必须放置在面板的中心李>图面板的实例
- 当用户绘制矩形时,它不应超出图像的限制
FigurePanel
类的源代码
package imageselectionproject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;
public class FigurePanel extends JPanel
{
private Image backgroundImage = null;
private Rectangle imageLimits = new Rectangle(0, 0, getWidth(), getHeight());
private Rectangle currentRect = null;
private Rectangle rectToDraw = null;
private final Rectangle previousRectDrawn = new Rectangle();
public FigurePanel()
{
setOpaque(true);
SelectionListener listener = new SelectionListener();
addMouseListener(listener);
addMouseMotionListener(listener);
}
@Override
public Dimension getPreferredSize()
{
return backgroundImage == null ? super.getPreferredSize() : new Dimension(backgroundImage.getWidth(this), backgroundImage.getHeight(this));
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g); //paints the background and image
if (backgroundImage != null)
{
g.drawImage(backgroundImage, imageLimits.x, imageLimits.y, this);
}
// If currentRect exists, paint a box on top.
if (currentRect != null)
{
// Draw a rectangle on top of the image.
g.setXORMode(Color.white); // Color of line varies
// depending on image colors
g.drawRect(rectToDraw.x, rectToDraw.y,
rectToDraw.width - 1, rectToDraw.height - 1);
System.out.println(rectToDraw);
}
}
public void setImage(Image image)
{
int x = 0;
int y = 0;
if (image != null)
{
backgroundImage = image;
// The following instructions are used to center the image on the panel.
/*x = (getSize().width - image.getWidth(this)) / 2;
y = (getSize().height - image.getHeight(this)) / 2;
if (x < 0) x = 0;
if (y < 0) y = 0;*/
}
else
{
backgroundImage = null;
}
currentRect = null;
setSize(getPreferredSize());
imageLimits.setBounds(x, y, getWidth(), getHeight());
System.out.println("imageLimits = " + imageLimits);
repaint();
}
private void updateDrawableRect()
{
int x = currentRect.x;
int y = currentRect.y;
int width = currentRect.width;
int height = currentRect.height;
// Make the width and height positive, if necessary.
if (width < 0)
{
width = 0 - width;
x = x - width + 1;
if (x < 0)
{
width += x;
x = 0;
}
}
if (height < 0)
{
height = 0 - height;
y = y - height + 1;
if (y < 0)
{
height += y;
y = 0;
}
}
// The rectangle should not extend beyond the boundaries of the image.
if (x < imageLimits.x)
{
width -= (imageLimits.x - x);
x = imageLimits.x;
}
else if ((x + width) > imageLimits.x + imageLimits.width)
{
width = imageLimits.x + imageLimits.width - x;
}
if (y < imageLimits.y)
{
height -= (imageLimits.y - y);
y = imageLimits.y;
}
if ((y + height) > imageLimits.y + imageLimits.height)
{
height = imageLimits.y + imageLimits.height - y;
}
// Update rectToDraw after saving old value.
if (rectToDraw != null)
{
previousRectDrawn.setBounds(rectToDraw.x, rectToDraw.y,
rectToDraw.width, rectToDraw.height);
rectToDraw.setBounds(x, y, width, height);
}
else
{
rectToDraw = new Rectangle(x, y, width, height);
}
}
private class SelectionListener extends MouseInputAdapter
{
@Override
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
currentRect = new Rectangle(x, y, 0, 0);
updateDrawableRect();
repaint();
}
@Override
public void mouseDragged(MouseEvent e)
{
updateSize(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e)
{
updateSize(e.getX(), e.getY());
}
/*
* Update the size of the current rectangle
* and call repaint. Because currentRect
* always has the same origin, translate it
* if the width or height is negative.
*
* For efficiency (though
* that isn't an issue for this program),
* specify the painting region using arguments
* to the repaint() call.
*
*/
void updateSize(int x, int y)
{
currentRect.setSize(x - currentRect.x, y - currentRect.y);
updateDrawableRect();
Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
repaint(totalRepaint.x, totalRepaint.y,
totalRepaint.width, totalRepaint.height);
}
}
}
package imageselectionproject;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
public class FigurePanelTest extends JFrame
{
public FigurePanelTest()
{
FigurePanel imagePanel = new FigurePanel();
JScrollPane imageScrollPane = new JScrollPane();
imageScrollPane.setPreferredSize(new Dimension(420, 250));
imageScrollPane.setViewportView(imagePanel);
JButton imageButton = new JButton("Load Image");
imageButton.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed(ActionEvent evt)
{
JFileChooser fc = new JFileChooser();
int returnValue = fc.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
System.out.println(selectedFile.getName());
try
{
Image image = ImageIO.read(selectedFile.getAbsoluteFile());
imagePanel.setImage(image);
imageScrollPane.getViewport().setViewPosition(new Point(0, 0));
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
);
Container container = getContentPane();
container.setLayout(new FlowLayout());
container.add(imageScrollPane);
container.add(imageButton);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
这是主要的
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new FigurePanelTest().setVisible(true);
}
});
}
对于Andrew,一个单一的程序:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.MouseInputAdapter;
public class TestDrawPanel {
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new FigurePanelTest().setVisible(true);
}
});
}
}
class FigurePanelTest extends JFrame {
public FigurePanelTest() {
final FigurePanel imagePanel = new FigurePanel();
final JScrollPane imageScrollPane = new JScrollPane();
imageScrollPane.setPreferredSize(new Dimension(420, 250));
imageScrollPane.setViewportView(imagePanel);
JButton imageButton = new JButton("Load Image");
imageButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JFileChooser fc = new JFileChooser();
int returnValue = fc.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
System.out.println(selectedFile.getName());
try {
Image image = ImageIO.read(selectedFile.getAbsoluteFile());
imagePanel.setImage(image);
imageScrollPane.getViewport()
.setViewPosition(new Point(0, 0));
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
Container container = getContentPane();
container.setLayout(new FlowLayout());
container.add(imageScrollPane);
container.add(imageButton);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class FigurePanel extends JPanel {
private Image backgroundImage = null;
private Rectangle imageLimits = new Rectangle(0, 0, getWidth(), getHeight());
private Rectangle currentRect = null;
private Rectangle rectToDraw = null;
private final Rectangle previousRectDrawn = new Rectangle();
public FigurePanel() {
setOpaque(true);
SelectionListener listener = new SelectionListener();
addMouseListener(listener);
addMouseMotionListener(listener);
}
@Override
public Dimension getPreferredSize() {
return backgroundImage == null ? super.getPreferredSize()
: new Dimension(backgroundImage.getWidth(this),
backgroundImage.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // paints the background and image
if (backgroundImage != null) {
g.drawImage(backgroundImage, imageLimits.x, imageLimits.y, this);
}
// If currentRect exists, paint a box on top.
if (currentRect != null) {
// Draw a rectangle on top of the image.
g.setXORMode(Color.white); // Color of line varies
// depending on image colors
g.drawRect(rectToDraw.x, rectToDraw.y, rectToDraw.width - 1,
rectToDraw.height - 1);
System.out.println(rectToDraw);
}
}
public void setImage(Image image) {
int x = 0;
int y = 0;
if (image != null) {
backgroundImage = image;
// The following instructions are used to center the image on the
// panel.
/*
* x = (getSize().width - image.getWidth(this)) / 2; y =
* (getSize().height - image.getHeight(this)) / 2;
*
* if (x < 0) x = 0; if (y < 0) y = 0;
*/
} else {
backgroundImage = null;
}
currentRect = null;
setSize(getPreferredSize());
imageLimits.setBounds(x, y, getWidth(), getHeight());
System.out.println("imageLimits = " + imageLimits);
repaint();
}
private void updateDrawableRect() {
int x = currentRect.x;
int y = currentRect.y;
int width = currentRect.width;
int height = currentRect.height;
// Make the width and height positive, if necessary.
if (width < 0) {
width = 0 - width;
x = x - width + 1;
if (x < 0) {
width += x;
x = 0;
}
}
if (height < 0) {
height = 0 - height;
y = y - height + 1;
if (y < 0) {
height += y;
y = 0;
}
}
// The rectangle should not extend beyond the boundaries of the image.
if (x < imageLimits.x) {
width -= (imageLimits.x - x);
x = imageLimits.x;
} else if ((x + width) > imageLimits.x + imageLimits.width) {
width = imageLimits.x + imageLimits.width - x;
}
if (y < imageLimits.y) {
height -= (imageLimits.y - y);
y = imageLimits.y;
}
if ((y + height) > imageLimits.y + imageLimits.height) {
height = imageLimits.y + imageLimits.height - y;
}
// Update rectToDraw after saving old value.
if (rectToDraw != null) {
previousRectDrawn.setBounds(rectToDraw.x, rectToDraw.y,
rectToDraw.width, rectToDraw.height);
rectToDraw.setBounds(x, y, width, height);
} else {
rectToDraw = new Rectangle(x, y, width, height);
}
}
private class SelectionListener extends MouseInputAdapter {
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
currentRect = new Rectangle(x, y, 0, 0);
updateDrawableRect();
repaint();
}
@Override
public void mouseDragged(MouseEvent e) {
updateSize(e.getX(), e.getY());
}
@Override
public void mouseReleased(MouseEvent e) {
updateSize(e.getX(), e.getY());
}
/*
* Update the size of the current rectangle and call repaint. Because
* currentRect always has the same origin, translate it if the width or
* height is negative.
*
* For efficiency (though that isn't an issue for this program), specify
* the painting region using arguments to the repaint() call.
*/
void updateSize(int x, int y) {
currentRect.setSize(x - currentRect.x, y - currentRect.y);
updateDrawableRect();
Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
repaint(totalRepaint.x, totalRepaint.y, totalRepaint.width,
totalRepaint.height);
}
}
}
导入java.awt.Color;
导入java.awt.Container;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
导入java.awt.Graphics;
导入java.awt.Image;
导入java.awt.Point;
导入java.awt.Rectangle;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.MouseEvent;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.swing.JButton;
导入javax.swing.JFileChooser;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.event.MouseInputAdapter;
公共类TestDrawPanel{
公共静态void main(字符串参数[]){
/*创建并显示表单*/
invokeLater(new Runnable()){
公开募捐{
新的FigurePanelTest().setVisible(true);
}
});
}
}
类图PanelTest扩展了JFrame{
公众人物广告{
最终FigurePanel imagePanel=新FigurePanel();
final JScrollPane imageScrollPane=新JScrollPane();
设置PreferredSize(新维度(420250));
imageScrollPane.setViewportView(imagePanel);
JButton imageButton=新JButton(“加载图像”);
addActionListener(新建ActionListener()){
@凌驾
已执行的公共无效操作(操作事件evt){
JFileChooser fc=新的JFileChooser();
int returnValue=fc.showOpenDialog(null);
if(returnValue==JFileChooser.APPROVE\u选项){
File selectedFile=fc.getSelectedFile();
System.out.println(selectedFile.getName());
试一试{
Image=ImageIO.read(selectedFile.getAbsoluteFile());
imagePanel.setImage(图像);
imageScrollPane.getViewport()
.setViewPosition(新点(0,0));
}捕获(IOE异常){
e、 printStackTrace();
}
}
}
});
Container=getContentPane();
container.setLayout(新的FlowLayout());
container.add(imageScrollPane);
容器。添加(图像按钮);
设置大小(600400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
类FigurePanel扩展了JPanel{
私有图像backgroundImage=null;
私有矩形imageLimits=新矩形(0,0,getWidth(),getHeight());
私有矩形currentRect=null;
私有矩形rectToDraw=null;
私有最终矩形PreviousRectDrawed=新矩形();
公共数字面板(){
set不透明(true);
SelectionListener=新建SelectionListener();
addMouseListener(监听器);
addMouseMotionListener(listener);
}
@凌驾
公共维度getPreferredSize(){
return backgroundImage==null?super.getPreferredSize()
:新尺寸(backgroundImage.getWidth(此),
backgroundImage.getHeight(this));
}
@凌驾
受保护组件(图形g){
super.paintComponent(g);//绘制背景和图像
if(backgroundImage!=null){
g、 drawImage(backgroundImage,imageLimits.x,imageLimits.y,this);
}
//如果currentRect存在,请在顶部绘制一个框。
if(currentRect!=null){
//在图像顶部绘制一个矩形。
g、 setXORMode(Color.white);//线条的颜色不同
//取决于图像颜色
g、 drawRect(rectToDraw.x,rectToDraw.y,rectToDraw.width-1,
rectToDraw.height-1);
System.out.println(rectToDraw);
}
}
公共void setImage(图像){
int x=0;
int y=0;
如果(图像!=null){
背景图像=图像;
//以下说明用于将图像居中放置在屏幕上
//小组。
/*
*x=(getSize().width-image.getWidth(this))/2;y=
*(getSize().height-image.getHeight(this))/2;
*
*如果(x<0)x=0;如果(y<0)y=0;
*/
}否则{
backgroundImage=null;
}
currentRect=null;
设置大小(getPreferredSize());
setBounds(x,y,getWidth(),getHeight());
System.out.println(“imageLimits=“+imageLimits”);
重新油漆();
}
私有void updateDrawableRect(){
int x=currentRect.x;
int y=当前矩形y;
int width=currentRect.width;
int height=currentRect.height;
//加宽
if (backgroundImage != null) {
imageLimits.x = (this.getWidth() - backgroundImage.getWidth(this)) / 2;
imageLimits.y = (this.getHeight() - backgroundImage.getHeight(this)) / 2;
g.drawImage(backgroundImage, imageLimits.x, imageLimits.y, this);
}