gpt4 book ai didi

java - 面板内绘制的图像似乎有错误的 x,y 偏移

转载 作者:行者123 更新时间:2023-12-01 07:35:03 24 4
gpt4 key购买 nike

所以,我有一个带有菜单、工具栏和面板的 JFrame。我在面板内加载图像,但由于某些奇怪的原因(至少对我来说),它们没有正确显示在面板中。有时它们从工具栏下方开始,有时在上方。此外,图像在底部被剪切。该代码是完整示例中经过清理的示例,可以编译和测试。提前致谢。

包含框架的类:

    import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FileDialog;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipInputStream;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
public class SSCE extends JFrame {
private JComicPanel panel;
private JToolBar toolbar;
private JButton buttonZoom;
private JButton buttonPrev;
private JButton buttonNext;
private JMenuBar menuBar;

private Dimension dim;
private BufferedImage img;
private int currentPage;
private JFrame parentFrame;




public SSCE(){

super("JComic");
BorderLayout layout = new BorderLayout();
setLayout(layout);

dim = Toolkit.getDefaultToolkit().getScreenSize();

setSize((int)(dim.width /2.5),dim.height);

this.setPreferredSize(new Dimension((int) (dim.width /2.5),dim.height));

createToolbar();
createPanel();

add(toolbar,BorderLayout.NORTH);

add(panel,BorderLayout.CENTER);


createMenu();
add(menuBar);
setJMenuBar(menuBar);
panel.setVisible(true);
img = null;
pack();
parentFrame = this;

}


private void createPanel(){
Border raisedbevel, loweredbevel;
raisedbevel = BorderFactory.createRaisedBevelBorder();
loweredbevel = BorderFactory.createLoweredBevelBorder();
panel = new JComicPanel(img);
panel.setBorder(BorderFactory.createCompoundBorder(raisedbevel,loweredbevel));


}
private void createToolbar(){
toolbar = new JToolBar();
toolbar.setPreferredSize(new Dimension(dim.width,45));
toolbar.setFloatable(false);
buttonZoom = new JButton("+");

toolbar.add(buttonZoom);
buttonPrev = new JButton("<-");
toolbar.add(buttonPrev);
buttonNext = new JButton("->");
toolbar.add(buttonNext);
toolbar.setBackground(Color.RED);


}
private void createMenu(){
JMenu menuFile,menuJComic;
JMenuItem fileOpen;
JMenuItem quitJComic,aboutJComic;


menuBar = new JMenuBar();
menuJComic = new JMenu("JComic");
aboutJComic = new JMenuItem("About JComic...");
menuJComic.add(aboutJComic);
quitJComic = new JMenuItem("Quit");
quitJComic.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
);
menuJComic.add(quitJComic);

menuBar.add(menuJComic);

menuFile = new JMenu("File");

fileOpen = new JMenuItem("Open...");
fileOpen.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
try {


img = ImageIO.read(new File("superman.jpg"));
currentPage = 1;

int offset = menuBar.getHeight() + toolbar.getHeight();
panel.setImage(img,parentFrame,offset);


}
catch (IOException e1) {
System.out.println(e1.getMessage());
}

}
}
);

menuFile.add(fileOpen);
menuBar.add(menuFile);


}

/**
* @param args
*/
@SuppressWarnings("deprecation")
public static void main(String[] args) {
// TODO Auto-generated method stub
SSCE f = new SSCE();
f.show();

}

}

面板类别

    import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class JComicPanel extends JPanel{
private BufferedImage img;
private int offset;
private final float scaling = 0.5f;
public JComicPanel(BufferedImage img){
super();
this.img = img;
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e)
{
repaint();
}
});

}




public void setImage(BufferedImage img,JFrame parentFrame,int offset){



try{

int w = img.getWidth();
int h = img.getHeight();
int newW = (int)(w * scaling);
int newH = (int)(h * scaling);
BufferedImage dimg = new BufferedImage(newW, newH, img.getType());
Graphics2D g = dimg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
this.img = img;
System.out.printf("dim %d x %d",newW,newH);


this.setSize(new Dimension(newW,newH+offset));

parentFrame.pack();
}
catch(Exception e){
}


}

public Dimension getPreferredSize(){

return new Dimension(img.getWidth(),img.getHeight());
}

public void paintComponent(Graphics g){

// Draw our Image object.
super.paintComponent(g);
g.drawImage(img,0,0,getSize().width,getSize().height, this); // at location 50,10
System.out.println("painting 2");
}

}

图片 superman.jpg 可以在这里找到 http://i50.tinypic.com/2yxnc3n.jpg 。正如您所看到的,图像位于工具栏下方,但在我的完整代码中,它也位于工具栏上方。

最佳答案

让我们从这里开始...

public void setImage(BufferedImage img,JFrame parentFrame,int offset){
try{
// You're scaling the incoming image, which means you no longer
// have a reference to the original image should you want to
// change that scale...
// You're previous code...

// Don't do this. The parent container's layout manager will simple
// override it, so it's useless...
this.setSize(newW,newH);
repaint();

// This is a bad idea (personally)...
parentFrame.setSize(newW,newH+offset);
} catch(Exception e){
}
}

以这种方式调用setSize将暂时允许组件采用您设置的大小。如果您在其后调用 invalidate(),组件实际上会重新调整大小以满足布局管理器的要求。

更大的问题是,您正在设置父框架的大小,但您不知道框架相对于其其他组件的布局要求,例如工具栏、菜单栏和框架(例如)

这是在不考虑原始图像比例的情况下绘制图像

g.drawImage(img,0,0,getSize().width,getSize().height, this);

正如建议的那样,缩放图像后,将图像简单地设置为 JLabel 的图标可能会更容易,该图标已使用 BorderLayout 添加到图像 Pane

您假设面板的大小是正确的,但事实并非如此,因为面板的布局管理器将接管。

这是多余的,因为 Swing 会在调整组件大小时自动重新绘制组件。

addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e)
{
repaint();
}
});

最好的办法是将图像 Pane 拖放到滚动 Pane 中,或者重新缩放图像以动态适应 Pane 的大小。

例如...

可缩放页面

enter image description here enter image description here

public class ComicPage {

public static void main(String[] args) {
new ComicPage();
}

public ComicPage() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}

try {
BufferedImage page = ImageIO.read(getClass().getResource("/1346.gif"));
ComicPagePane comicPagePane = new ComicPagePane();
comicPagePane.setComicPage(page);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(comicPagePane);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}

public class ComicPagePane extends JPanel {

private BufferedImage comicPage;
private Image scaledInstance;

public void setComicPage(BufferedImage page) {
if (page != comicPage) {
comicPage = page;
scaledInstance = null;
repaint();
}
}

@Override
public void invalidate() {
scaledInstance = null;
super.invalidate();
}

public BufferedImage getComicPage() {
return comicPage;
}

public double getScaleFactor(int iMasterSize, int iTargetSize) {
return (double) iTargetSize / (double) iMasterSize;
}

public double getScaleFactorToFit(BufferedImage img) {
double dScale = 1d;

double dScaleWidth = getScaleFactor(img.getWidth(), getWidth());
double dScaleHeight = getScaleFactor(img.getHeight(), getHeight());

dScale = Math.min(dScaleHeight, dScaleWidth);

return dScale;
}

protected Image getScaledInstance(BufferedImage master) {
if (scaledInstance == null) {
double scaleFactor = getScaleFactorToFit(master);
System.out.println("scaleFactor = " + NumberFormat.getNumberInstance().format(scaleFactor));

// This is not the best scaling alorithm
scaledInstance = master.getScaledInstance(
(int) Math.round(master.getWidth() * scaleFactor),
(int) Math.round(master.getHeight() * scaleFactor), Image.SCALE_SMOOTH);
}
return scaledInstance;
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

BufferedImage comicPage = getComicPage();
if (comicPage != null) {
Graphics2D g2d = (Graphics2D) g.create();

int width = getWidth();
int height = getHeight();

// Normally, I would put this into a background worker as this
// operation can be expensive....
Image scaledInstance = getScaledInstance(comicPage);

int x = (width - scaledInstance.getWidth(this)) / 2;
int y = (height - scaledInstance.getHeight(this)) / 2;
g2d.drawImage(scaledInstance, x, y, this);
g2d.dispose();
}
}
}
}

可滚动页面

enter image description here

public class ScrollableComicPage {

public static void main(String[] args) {
new ScrollableComicPage();
}

public ScrollableComicPage() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}

try {
BufferedImage page = ImageIO.read(getClass().getResource("/1346.gif"));
ComicPagePage comicPagePane = new ComicPagePage();
comicPagePane.setComicPage(page);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(comicPagePane));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}

public class ComicPagePage extends JPanel {

private BufferedImage comicPage;

@Override
public Dimension getPreferredSize() {
return comicPage != null ? new Dimension(comicPage.getWidth(), comicPage.getHeight()) : new Dimension(0, 0);
}

public void setComicPage(BufferedImage page) {
if (page != comicPage) {

comicPage = page;
invalidate();
repaint();
}
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (comicPage != null) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(comicPage, 0, 0, this);
g2d.dispose();
}
}
}
}

您可以阅读Java: maintaining aspect ratio of JPanel background image有关缩放技术的更多信息。

关于java - 面板内绘制的图像似乎有错误的 x,y 偏移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13166402/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com