我试图编写一个从JPanel扩展的简单类,它可以放大和缩小图像,然后在顶层使用JScrollPane,允许某人在缩放图像上来回滚动。我在使用JScrollPane部分时遇到了麻烦。
单击其中一个缩放按钮(无论是进入,退出还是重置)时,必须单击该按钮两次才能显示JScrollBars(或者在重置按钮的情况下,消失)。即使在他们继续放大或缩小后出现它们,也不会根据新的缩放级别进行更新。调整窗口大小可以解决这个问题,但我正在寻找更具体的解决方案。
ImagePanel代码:
package com.zephyr.graphics;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel implements PropertyChangeListener{
private File imageFile;
private BufferedImage image;
private double zoomMultiplier;
public ImagePanel()
{
imageFile = null;
image = null;
zoomMultiplier = 1;
}
public ImagePanel(File imageFile)
{
this.imageFile = imageFile;
try {
image = ImageIO.read(imageFile);
} catch (IOException e) {
image = null;
}
zoomMultiplier = 1;
}
public void setImageFile(File imageFile)
{
this.imageFile = imageFile;
if(imageFile == null)
{
image = null;
}
else
{
try {
image = ImageIO.read(imageFile);
} catch (IOException e) {
image = null;
}
}
zoomMultiplier = 1;
this.revalidate();
this.repaint();
}
public File getImageFile()
{
return imageFile;
}
public void paintComponent(Graphics g)
{
g.clearRect(0, 0, this.getWidth(), this.getHeight());
if(image == null)
{
this.setPreferredSize(new Dimension(this.getParent().getWidth(), this.getParent().getHeight()));
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
else
{
double preferredWidth = this.getParent().getWidth() * zoomMultiplier;
double preferredHeight = this.getParent().getHeight() * zoomMultiplier;
this.setPreferredSize(new Dimension((int)preferredWidth, (int)preferredHeight));
Image scaled = image.getScaledInstance((int)preferredWidth, (int)preferredHeight, Image.SCALE_DEFAULT);
g.drawImage(scaled, 0, 0, null);
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("Image File"))
{
setImageFile((File)evt.getNewValue());
}
else if(evt.getPropertyName().equals("Zoom In"))
{
double additive = ((Number)evt.getNewValue()).doubleValue();
zoomMultiplier += additive;
this.revalidate();
this.repaint();
}
else if(evt.getPropertyName().equals("Zoom Out"))
{
double subtractive = ((Number)evt.getNewValue()).doubleValue();
zoomMultiplier -= subtractive;
this.revalidate();
this.repaint();
}
else if(evt.getPropertyName().equals("Zoom Reset"))
{
zoomMultiplier = 1;
this.revalidate();
this.repaint();
}
}
}
主类
package com.zephyr.graphics;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Main {
public static void main(String[] args)
{
PropertyChangeSupport pcs = new PropertyChangeSupport(Main.class);
JFileChooser chooser = new JFileChooser(System.getProperty("user.home"));
chooser.setDialogTitle("Select an image");
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
File file = null;
if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
{
file = chooser.getSelectedFile();
}
else
{
System.err.println("NO FILE WAS SELECTED OR THE WINDOW WAS CLOSED");
return;
}
JFrame frame = new JFrame("ImagePanel Tester");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImagePanel iPanel = new ImagePanel(file);
pcs.addPropertyChangeListener(iPanel);
JScrollPane iScroll = new JScrollPane(iPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
iScroll.setPreferredSize(new Dimension(1024, 768));
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton zoomIn = new JButton("Zoom In");
zoomIn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
pcs.firePropertyChange("Zoom In", null, new Double(.25));
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomIn);
JButton zoomOut = new JButton("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pcs.firePropertyChange("Zoom Out", null, new Double(.25));
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomOut);
JButton zoomReset = new JButton("Zoom Reset");
zoomReset.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
pcs.firePropertyChange("Zoom Reset", null, null);
frame.revalidate();
frame.repaint();
}
});
controlPanel.add(zoomReset);
JButton changeImage = new JButton("Change Image");
changeImage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)
{
File tempFile = chooser.getSelectedFile();
pcs.firePropertyChange("Image File", null, tempFile);
frame.revalidate();
frame.repaint();
}
}
});
controlPanel.add(changeImage);
frame.add(iScroll, BorderLayout.CENTER);
frame.add(controlPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.revalidate(); //Shouldn't really be necessary, but seems to be helping
}
}
答案 0 :(得分:0)
经过一番繁重的挖掘,Scrollable界面救了我。在此example之后实现此方法及其各自的方法以及从paintComponent中删除preferredSize引用可修复我遇到的问题。