我知道到处都有关于如何绘制图像的教程。通常人们建议显示它添加一个加载该图像的对象。但就我而言,我不想每次更改图像中的某些内容时都实例化一个新对象。
所以,我使用 Graphics 类来做到这一点。 另外,我正在使用 MVC 方法来完成此操作。
问题: 正如我们所看到的,只绘制了图像的一小部分区域,如果我加载另一张图像,这个小区域会根据图片而变化。然后,我认为缓冲图像已正确加载。
所以,我寻找问题出在哪里: 这是我的代码:
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class DisplayView extends JFrame implements Observer {
private static final long serialVersionUID = 1L;
/**
* @param args
*/
private static DisplayView instance;
private DisplayControl control;
private JFileChooser fileChooser;
Panel imageLeft, imageRight;
private DisplayView() {
JMenuItem exit = new JMenuItem("Exit");
exit.setMnemonic('E');
exit.setToolTipText("Exit Application");
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
fileChooser = new JFileChooser();
fileChooser.setFileFilter(new ImageFileFilter());
JMenuItem loadImage = new JMenuItem("Load Image");
loadImage.setMnemonic('O');
loadImage.setToolTipText("Loads an Image to Process");
loadImage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
int ret = fileChooser.showDialog(DisplayView.getInstance(),
"Open file");
if (ret == JFileChooser.APPROVE_OPTION) {
System.out.println(fileChooser.getSelectedFile());
control.onFileChoose(fileChooser.getSelectedFile()
.getAbsolutePath());
}
}
});
JMenu file = new JMenu("File");
file.setMnemonic('F');
file.add(loadImage);
file.add(exit);
JMenuBar menuBar = new JMenuBar();
menuBar.add(file);
imageLeft = new Panel();
imageLeft.setSize(500, 500);
imageLeft.setVisible(true);
imageRight = new Panel();
this.setLayout(new FlowLayout());
this.add(imageLeft);
// this.add(imageRight);
this.setTitle("Test");
this.setSize(300, 200);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setJMenuBar(menuBar);
}
static public DisplayView getInstance() {
if (instance == null)
instance = new DisplayView();
return DisplayView.instance;
}
public void setControl(DisplayControl control) {
this.control = control;
}
@Override
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
if (o instanceof DisplayModel) {
this.imageLeft.setImage(((DisplayModel) o).getOriginalImage());
// this.imageRight.setImage(((DisplayModel) o).getProcessedImage());
}
}
}
class Panel extends JPanel {
BufferedImage image;
public void setImage(BufferedImage image) {
if (image != null)
this.image = image;
this.repaint();
}
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
super.paint(g);
if (image != null)
g.drawImage(image, 0, 0, this);
}
}
最佳答案
问题是您的 Panel
类不会重写 getPreferredSize()
,因此它的首选大小实际上是 (0,0),因此 FlowLayout
将为您的 Panel
分配 (0,0) 的大小。
无论如何,我会考虑用简单的 JLabel
类替换您的 Panel
类,它将执行完全相同的操作并为您处理首选尺寸。
- 当您还使用 LayoutManager 时(您应该这样做),调用
setSize()
是没有用的。一般来说,只需忘记 setSize/setLocation/setBounds/setPreferredSize 即可。答案总是相同的:“使用适当的LayoutManager
” - 对于自定义绘画,请覆盖
paintComponent
而不是paint
关于Java 绘制图像 JPanel : Working but weird,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16194590/