所以,我有一个带有菜单,工具栏和面板的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找到。正如您所看到的,图像位于工具栏下方,但在我的完整代码中,它也在上面。
答案 0 :(得分:5)
让我们从这里开始......
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()
,则实际上会重新调整组件的大小以满足布局管理器的要求。
更大的问题是您正在设置父框架的大小,但您不知道框架的布局要求与其他组件有关,例如工具栏,菜单栏和框架(例如)< / p>
这是在不考虑原始图像的比率的情况下绘制图像
g.drawImage(img,0,0,getSize().width,getSize().height, this);
正如所建议的那样,在缩放图像之后,可能更容易将图像简单地设置为JLabel的图标,该图标已使用BorderLayout
您假设面板的大小是正确的,但不会像面板的布局管理器接管那样。
这是多余的,因为Swing会在调整组件大小时自动重新绘制组件。
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e)
{
repaint();
}
});
最好的办法是将图像窗格拖放到滚动窗格中,或者重新缩放图像以适应动态窗格的大小。
例如......
可扩展页面
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();
}
}
}
}
可滚动页面
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,了解有关缩放技术的更多信息。
答案 1 :(得分:2)
技术原因是您暂时将menuBar添加到contentPane的中心,即与之前添加的面板相同的逻辑位置:
add(panel, BorderLayout.CENTER);
// following line is wrong - must be removed!!!
add(menuBar); // no constraint == BorderLayout.CENTER
setJMenuBar(menuBar);
这样做会将面板推出LayoutManager的控制范围,但不会超出面板 - 净效果是它没有约束。
这并不是特别的是菜单栏(这需要被添加到为rootPane的layeredPane,不contentPane中 - 这就是为什么它有自己专门的方法setJMenuBar),同样的混乱将与在其他任意成分发生中心。
除此之外,我建议你清理你的代码: