我有一个包含JScrollPane的JFrame,其中包含一个JPanel。 我在JPanel上传和绘制图像。图像的大小可能会发生变化。每次我画一个新图像,在一个事件之后,我在JFrame上调用pack。 这一切都可以正常使用JFrame并且所有内容都已正确调整大小,但是滚动条出现问题并且不规则地出现和消失。如果我删除对pack()的调用,那么滚动条就在那里,但是包含JPanel的内容不会调整大小。为什么?我能做什么 ? 这是用于测试的修剪SSCCE代码。使用的图像是 enter link description here
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.border.Border;
@SuppressWarnings("serial")
public class JComicFrame extends JFrame {
private JComicPanel panel;
private JToolBar toolbar;
private JButton buttonZoom;
private JButton buttonPrev;
private JButton buttonNext;
private JMenuBar menuBar;
private JScrollPane scroller;
private BufferedImage img;
private ArrayList<BufferedImage> images;
private int currentFile;
public JComicFrame(){
super("JComic");
images = new ArrayList<BufferedImage>();
try {
images.add(ImageIO.read(new File("1.jpg")));
images.add(ImageIO.read(new File("2.jpg")));
images.add(ImageIO.read(new File("3.jpg")));
images.add(ImageIO.read(new File("4.jpg")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BorderLayout layout = new BorderLayout();
setLayout(layout);
createToolbar();
createPanel();
createMenu();
setJMenuBar(menuBar);
add(toolbar,BorderLayout.NORTH);
scroller = new JScrollPane(panel);
add(scroller,BorderLayout.CENTER);
setVisible(true);
currentFile = -1;
BufferedImage img = getNextFile();
panel.setImage(img);
pack();
}
private BufferedImage getNextFile(){
currentFile = currentFile + 1;
currentFile = (currentFile > images.size() - 1) ? images.size() - 1 : currentFile;
return images.get(currentFile);
}
private BufferedImage getPrevFile(){
currentFile = currentFile - 1;
currentFile = (currentFile < 0) ? 0 : currentFile;
return images.get(currentFile);
}
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.setFloatable(false);
buttonZoom = new JButton("+");
toolbar.add(buttonZoom);
buttonPrev = new JButton("<-");
buttonPrev.addActionListener
(
new ActionListener(){
public void actionPerformed(ActionEvent e){
BufferedImage img = getPrevFile();
panel.setImage(img);
pack();
repaint();
}
}
);
toolbar.add(buttonPrev);
buttonNext = new JButton("->");
buttonNext.addActionListener
(
new ActionListener(){
public void actionPerformed(ActionEvent e){
BufferedImage img = getNextFile();
panel.setImage(img);
pack();
}
}
);
toolbar.add(buttonNext);
toolbar.setBackground(Color.WHITE);
}
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...");
menuFile.add(fileOpen);
menuBar.add(menuFile);
}
public static void main(String args[]){
JComicFrame theFrame = new JComicFrame();
theFrame.show();
}
}
///////////////// next class ///////////////////
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class JComicPanel extends JPanel{
private static final long serialVersionUID = 1L;
private BufferedImage img = null;
private float scaling = 0.5f;
private int newW, newH;
public JComicPanel(BufferedImage img){
super();
this.img = img;
}
public JComicPanel(){
super();
this.img = null;
}
private Runnable scaleImage(BufferedImage img){
int w = img.getWidth();
int h = img.getHeight();
newW = (int)(w * scaling);
newH = (int)(h * scaling);
BufferedImage dimg = new BufferedImage(newW, newH, img.getType());
Graphics2D g = dimg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
this.img = dimg;
revalidate();
repaint();
return null;
}
public void setImage(BufferedImage img){
Thread t = new Thread(scaleImage(img));
t.start();
}
public Dimension getPreferredSize(){
System.out.println("PS");
if(img==null || this.isVisible() == false)
return new Dimension(1,1);
else
return new Dimension(img.getWidth(),img.getHeight());
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D)g.create();
super.paintComponent(g);
g2d.drawImage(img,0,0,getSize().width,getSize().height, this);
g2d.dispose();
}
}
答案 0 :(得分:1)
必须在屏幕上为max_size
决定JFrame
添加新Image
后,您必须致电revalidate
&amp; repaint
JPanel
然后JPanel
返回正确的PreferredSize
,
将此Dimension
与所需的JFrames max size
进行比较,如果大于pack()
,则不要调用{{1}},反之亦然
在SSCCE发布后更快获得更好的帮助,因为上午点只是关于理论的
答案 1 :(得分:0)
我的建议是:如果您想要显示图片,请不要使用JPanel
,请使用JLabel
:
import javax.swing.*;
public class ScrollPane extends JFrame{
JLabel label = new JLabel();
JScrollPane scrollPane = new JScrollPane();
public ScrollPane(){
label.setIcon(new ImageIcon("C:/Documents and Settings/All Users/Documents/My Pictures/Sample Pictures/Image.jpg"));
scrollPane.setViewportView(label);
add(scrollPane);
}
public static void main(String[] args) {
ScrollPane sp = new ScrollPane();
sp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//sp.setSize(1024,800);
sp.pack();
sp.setVisible(true);
}
}
此外,如果您想使用pack();
来显示图片,请不要每次在JPanel
上添加图片后调用repaint();
,请调用JPanel
方法。
答案 2 :(得分:0)
无需每次都声明pack()。如果你在main方法中声明它就足够了。这意味着不在以下部分声明:
public void actionPerformed(ActionEvent e){
BufferedImage img = (BufferedImage)archiveHandler.getNextFile();
panel.setImage(img);
pack();