Java drawImage()在调整JPanel大小时调用
我正在尝试使用Java6/7编写一个可重用的JPanel图像查看器。如果在调整大小期间JPanel(视口原点)的左上角没有移动,我可以使用mouseDragged实现图像拖动,也可以调整JPanel的大小来裁剪或显示图像。注意:我不想调整图像大小以适应面板。我希望在调整面板大小以进行裁剪时,图像保持固定在屏幕上 如果我拖动帧的左边缘,从而移动视口原点,则在调整大小操作期间会出现相当大的图像抖动,即使在调整大小期间动态重新计算图像原点也是如此。这似乎是由于调用paintComponent()与通过调用drawImage()实际渲染图像之间的视口原点发生了变化。有没有关于如何消除上述抖动的想法?提前谢谢 以下两个类应演示该行为:Java drawImage()在调整JPanel大小时调用,java,swing,Java,Swing,我正在尝试使用Java6/7编写一个可重用的JPanel图像查看器。如果在调整大小期间JPanel(视口原点)的左上角没有移动,我可以使用mouseDragged实现图像拖动,也可以调整JPanel的大小来裁剪或显示图像。注意:我不想调整图像大小以适应面板。我希望在调整面板大小以进行裁剪时,图像保持固定在屏幕上 如果我拖动帧的左边缘,从而移动视口原点,则在调整大小操作期间会出现相当大的图像抖动,即使在调整大小期间动态重新计算图像原点也是如此。这似乎是由于调用paintComponent()与通过
/***** ImageViewer.java *****/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import javax.imageio.ImageIO;
public class ImageViewer extends JFrame
{
private ImagePanel canvas;
private BufferedImage theImage;
private JFileChooser theChooser;
public ImageViewer( BufferedImage bi )
{
canvas= new ImagePanel( );
add( canvas, BorderLayout.CENTER );
JPanel control= new JPanel();
JButton loadBtn= new JButton( "Load Image" );
control.add( loadBtn );
add( control, BorderLayout.NORTH );
loadBtn.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e )
{ doLoad(); }
});
theChooser= new JFileChooser();
}
public void doLoad()
{
File iFile = null;
int retVal = theChooser.showOpenDialog(this);
if (retVal == JFileChooser.APPROVE_OPTION) {
iFile = theChooser.getSelectedFile();
try {
theImage = ImageIO.read(iFile);
} catch (FileNotFoundException ie) {
System.err.println("File not found");
System.exit(1);
} catch (IOException ie) {
System.err.println("IOException");
System.exit(1);
}
canvas.setImage( theImage );
repaint();
}
}
/**
* @param args
*/
public static void main(String[] args)
{
BufferedImage bImage= null;
ImageViewer theApp= new ImageViewer( bImage );
theApp.setDefaultCloseOperation(EXIT_ON_CLOSE);
theApp.pack();
theApp.setVisible( true );
}
}
/***** ImagePanel.java *****/
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.JPanel;
public class ImagePanel extends JPanel
{
private BufferedImage theImage;
private Dimension preferredSize;
private double scaleF = 1.0; // image scaling factor
private Point2D.Double deltaLoc; // dx, dy in scaled units for image upper
// left corner from origin to current loc
// inside or outside viewport
private Point panelLastLoc; // last location of upper left corner of the
// viewport in screen coordinates
private int lastX;
private int lastY;
private PanelState state = PanelState.IDLE;
public enum PanelState
{
IDLE, RESIZING, PMOVING, IMOVING
};
public ImagePanel()
{
setBackground(Color.GRAY);
preferredSize = new Dimension(400, 400);
addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent he)
{
doComponentChanged(he);
}
});
addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
public void ancestorMoved(HierarchyEvent he)
{
doComponentMoved();
}
public void ancestorResized(HierarchyEvent he)
{
doAncestorResizing();
}
});
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce)
{
doComponentResized();
}
});
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me)
{
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
state = PanelState.IMOVING;
lastX = me.getX();
lastY = me.getY();
}
public void mouseReleased(MouseEvent me)
{
setCursor(Cursor.getDefaultCursor());
state = PanelState.IDLE;
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent me)
{
doImageMoved(me);
}
});
}
public ImagePanel(BufferedImage bi)
{
theImage = bi;
preferredSize = new Dimension(theImage.getWidth(), theImage.getHeight());
}
public Dimension getPreferredSize()
{
return preferredSize;
}
private void doComponentChanged(HierarchyEvent he)
{
if (isShowing()) {
panelLastLoc = getLocationOnScreen();
}
state = PanelState.IDLE;
}
private void doImageMoved(MouseEvent me)
{
if (!isShowing() || theImage == null)
return;
switch (state)
{
case RESIZING:
error("IMOVING->RESIZING");
break;
case PMOVING:
error("IMOVING->PMOVING");
break;
case IDLE:
error("IMOVING->IDLE");
break;
case IMOVING:
if (contains(me.getX(), me.getY())) {
int dx = me.getX() - lastX;
int dy = me.getY() - lastY;
lastX = me.getX();
lastY = me.getY();
deltaLoc.x += dx;
deltaLoc.y += dy;
repaint();
}
return;
}
}
private void doComponentMoved()
{
if (!isShowing() || theImage == null)
return;
switch (state)
{
case RESIZING:
return;
case IMOVING:
error("IMOVING->PMOVING");
break;
case PMOVING:
case IDLE:
panelLastLoc = getLocationOnScreen();
state = PanelState.PMOVING;
}
return;
}
private void doAncestorResizing()
{
if (!isShowing() || theImage == null)
return;
switch (state)
{
case IMOVING:
error("IMOVING->RESIZING");
return;
case RESIZING:
case PMOVING:
case IDLE:
Point cLoc = getLocationOnScreen();
state = PanelState.RESIZING;
if (theImage != null) {
deltaLoc.x -= cLoc.x - panelLastLoc.x;
deltaLoc.y -= cLoc.y - panelLastLoc.y;
}
panelLastLoc = cLoc;
}
}
private void doComponentResized()
{
Point cLoc = getLocationOnScreen();
switch (state)
{
case RESIZING:
state = PanelState.IDLE;
break;
case IMOVING:
error("IMOVING->RESIZED");
break;
case PMOVING:
state = PanelState.IDLE;
break;
case IDLE:
break;
}
if (theImage != null) {
deltaLoc.x -= cLoc.x - panelLastLoc.x;
deltaLoc.y -= cLoc.y - panelLastLoc.y;
}
panelLastLoc = cLoc;
}
public void setImage(BufferedImage nI)
{
theImage = nI;
scaleF = 1.0;
state = PanelState.IDLE;
deltaLoc = new Point2D.Double(Math.round((getWidth() - theImage.getWidth()) / 2.0),
Math.round((getHeight() - theImage.getHeight()) / 2.0));
panelLastLoc = getLocationOnScreen();
}
private void error(String em)
{
System.err.println(em);
System.exit(1);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (theImage == null)
return;
/*
* Check if the viewport has resized or moved. The check below is
* performed on every repaint.
*/
Point cLoc = getLocationOnScreen();
Dimension cDim = getSize();
if (state == PanelState.RESIZING || state == PanelState.IDLE) {
deltaLoc.x -= cLoc.x - panelLastLoc.x;
deltaLoc.y -= cLoc.y - panelLastLoc.y;
}
/*
System.err.println("image left edge= "
+ Math.round(cLoc.x + deltaLoc.x) + "; state= " + state
+ "; cDim= " + cDim + "; cLoc= " + cLoc + "; pLLoc= "
+ panelLastLoc + "; dLoc= " + deltaLoc);
*/
// In all cases update panelLastLoc
panelLastLoc = cLoc;
g2.drawImage(theImage, (int) Math.round(deltaLoc.x),
(int) Math.round(deltaLoc.y), null);
}
}
您是否尝试过覆盖图像上的
paintComponent
以调用repaint
(或者revalidate
)呢?这将确保在更改后屏幕上显示任何内容之前调用drawImage
另请参见。您是否尝试过覆盖
paintComponent
以调用图像上的重新绘制
(或者重新验证
)?这将确保在更改后屏幕上显示任何内容之前调用drawImage
另请参见。不是答案,而是我想与大家分享的失败尝试。如果必须的话,请投反对票 我想我会很聪明,试着用一个带有JLabel/ImageIcon的JScrollPane来为我做这个动作,但它仍然不起作用。例如
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class ImageViewer2 extends JPanel {
private static final int SP_WIDTH = 500;
private static final int SP_HEIGHT = SP_WIDTH;
private JLabel viewportView = new JLabel();
private JViewport viewport = new JViewport();
private JScrollPane scrollpane = new JScrollPane();
private Point viewLocOnScrn = null;
public ImageViewer2() {
viewport.setView(viewportView);
scrollpane.setViewport(viewport);
viewport.setBackground(Color.gray);
viewport.addComponentListener(new MyComponentListener());
scrollpane.setPreferredSize(new Dimension(SP_WIDTH, SP_HEIGHT));
scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
viewport.addMouseListener(mouseAdapter);
viewport.addMouseMotionListener(mouseAdapter);
JButton loadImageBtn = new JButton(new LoadImageAction("Load Image"));
JPanel topPanel = new JPanel();
topPanel.add(loadImageBtn);
setLayout(new BorderLayout());
add(scrollpane, BorderLayout.CENTER);
add(topPanel, BorderLayout.PAGE_START);
}
private class MyComponentListener extends ComponentAdapter {
@Override
public void componentMoved(ComponentEvent compEvt) {
compEvtOccurred(compEvt);
}
@Override
public void componentResized(ComponentEvent compEvt) {
compEvtOccurred(compEvt);
}
private void compEvtOccurred(ComponentEvent compEvt) {
Point newViewLocOnScn = viewportView.getLocationOnScreen();
if (viewLocOnScrn != null && !newViewLocOnScn.equals(viewLocOnScrn)) {
Point scrollPaneLocOnScrn = scrollpane.getLocationOnScreen();
int x = scrollPaneLocOnScrn.x - viewLocOnScrn.x;
int y = scrollPaneLocOnScrn.y - viewLocOnScrn.y;
viewport.setViewPosition(new Point(x, y));
}
}
}
private class MyMouseAdapter extends MouseAdapter {
private Point delta;
@Override
public void mousePressed(MouseEvent mEvt) {
Point mousePt = mEvt.getPoint();
Point viewPos = viewport.getViewPosition();
delta = new Point(viewPos.x + mousePt.x, viewPos.y + mousePt.y);
}
@Override
public void mouseDragged(MouseEvent e) {
if (delta == null ) {
return;
}
Point p = e.getPoint();
viewport.setViewPosition(new Point(delta.x - p.x, delta.y - p.y));
viewLocOnScrn = viewportView.getLocationOnScreen();
}
@Override
public void mouseReleased(MouseEvent e) {
delta = null;
}
}
private class LoadImageAction extends AbstractAction {
public LoadImageAction(String text) {
super(text);
}
@Override
public void actionPerformed(ActionEvent actEvt) {
JFileChooser jfc = new JFileChooser("img003.jpg");
int jfcResult = jfc.showOpenDialog(ImageViewer2.this);
if (jfcResult == JFileChooser.APPROVE_OPTION) {
File file = jfc.getSelectedFile();
try {
BufferedImage bufImg = ImageIO.read(file);
ImageIcon icon = new ImageIcon(bufImg);
viewportView.setIcon(icon);
Dimension vpSize = viewport.getSize();
int vpX = (bufImg.getWidth() - vpSize.width) / 2;
int vpY = (bufImg.getHeight() - vpSize.height) / 2;
Point viewPos = new Point(vpX, vpY);
viewport.setViewPosition(viewPos);
viewLocOnScrn = viewportView.getLocationOnScreen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void createAndShowGui() {
ImageViewer2 mainPanel = new ImageViewer2();
JFrame frame = new JFrame("Image Viewer 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
欢迎评论和批评 不是答案,而是一次失败的尝试,我想与大家分享。如果必须的话,请投反对票 我想我会很聪明,试着用一个带有JLabel/ImageIcon的JScrollPane来为我做这个动作,但它仍然不起作用。例如
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class ImageViewer2 extends JPanel {
private static final int SP_WIDTH = 500;
private static final int SP_HEIGHT = SP_WIDTH;
private JLabel viewportView = new JLabel();
private JViewport viewport = new JViewport();
private JScrollPane scrollpane = new JScrollPane();
private Point viewLocOnScrn = null;
public ImageViewer2() {
viewport.setView(viewportView);
scrollpane.setViewport(viewport);
viewport.setBackground(Color.gray);
viewport.addComponentListener(new MyComponentListener());
scrollpane.setPreferredSize(new Dimension(SP_WIDTH, SP_HEIGHT));
scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
viewport.addMouseListener(mouseAdapter);
viewport.addMouseMotionListener(mouseAdapter);
JButton loadImageBtn = new JButton(new LoadImageAction("Load Image"));
JPanel topPanel = new JPanel();
topPanel.add(loadImageBtn);
setLayout(new BorderLayout());
add(scrollpane, BorderLayout.CENTER);
add(topPanel, BorderLayout.PAGE_START);
}
private class MyComponentListener extends ComponentAdapter {
@Override
public void componentMoved(ComponentEvent compEvt) {
compEvtOccurred(compEvt);
}
@Override
public void componentResized(ComponentEvent compEvt) {
compEvtOccurred(compEvt);
}
private void compEvtOccurred(ComponentEvent compEvt) {
Point newViewLocOnScn = viewportView.getLocationOnScreen();
if (viewLocOnScrn != null && !newViewLocOnScn.equals(viewLocOnScrn)) {
Point scrollPaneLocOnScrn = scrollpane.getLocationOnScreen();
int x = scrollPaneLocOnScrn.x - viewLocOnScrn.x;
int y = scrollPaneLocOnScrn.y - viewLocOnScrn.y;
viewport.setViewPosition(new Point(x, y));
}
}
}
private class MyMouseAdapter extends MouseAdapter {
private Point delta;
@Override
public void mousePressed(MouseEvent mEvt) {
Point mousePt = mEvt.getPoint();
Point viewPos = viewport.getViewPosition();
delta = new Point(viewPos.x + mousePt.x, viewPos.y + mousePt.y);
}
@Override
public void mouseDragged(MouseEvent e) {
if (delta == null ) {
return;
}
Point p = e.getPoint();
viewport.setViewPosition(new Point(delta.x - p.x, delta.y - p.y));
viewLocOnScrn = viewportView.getLocationOnScreen();
}
@Override
public void mouseReleased(MouseEvent e) {
delta = null;
}
}
private class LoadImageAction extends AbstractAction {
public LoadImageAction(String text) {
super(text);
}
@Override
public void actionPerformed(ActionEvent actEvt) {
JFileChooser jfc = new JFileChooser("img003.jpg");
int jfcResult = jfc.showOpenDialog(ImageViewer2.this);
if (jfcResult == JFileChooser.APPROVE_OPTION) {
File file = jfc.getSelectedFile();
try {
BufferedImage bufImg = ImageIO.read(file);
ImageIcon icon = new ImageIcon(bufImg);
viewportView.setIcon(icon);
Dimension vpSize = viewport.getSize();
int vpX = (bufImg.getWidth() - vpSize.width) / 2;
int vpY = (bufImg.getHeight() - vpSize.height) / 2;
Point viewPos = new Point(vpX, vpY);
viewport.setViewPosition(viewPos);
viewLocOnScrn = viewportView.getLocationOnScreen();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void createAndShowGui() {
ImageViewer2 mainPanel = new ImageViewer2();
JFrame frame = new JFrame("Image Viewer 2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
欢迎评论和批评 请编辑您的问题,以包含一个显示您描述的问题的列表。可能是实际图像的方便替代品。如果没有代码,很难猜测是什么导致了您的问题。出于这个原因,我支持上面垃圾神的建议。谢谢你发布代码。对你的毅力投1+以上的赞成票。请编辑你的问题,使之包含一个能展示你所描述问题的答案。可能是实际图像的方便替代品。如果没有代码,很难猜测是什么导致了您的问题。出于这个原因,我支持上面垃圾神的建议。谢谢你发布代码。1+投票支持你的毅力。