Java绘图图像JPanel:工作正常但很奇怪

Java绘图图像JPanel:工作正常但很奇怪,java,swing,drawing,jframe,bufferedimage,Java,Swing,Drawing,Jframe,Bufferedimage,我知道,在任何地方都有一个关于如何绘制图像的教程。通常,人们建议通过添加加载该图像的对象来显示它。但在我的例子中,我不想每次更改图像中的某些内容时都实例化一个新对象 所以,我用图形类来做这件事。 另外,我正在使用MVC方法来实现它 问题: 正如我们所看到的,只有一个小区域的图像是绘制的,如果我加载另一个图像,这个小区域会根据图片的变化而变化。然后,我假设缓冲的图像已正确加载 因此,我在寻找问题出在哪里: 这是我的代码: import java.awt.FlowLayout; import ja

我知道,在任何地方都有一个关于如何绘制图像的教程。通常,人们建议通过添加加载该图像的对象来显示它。但在我的例子中,我不想每次更改图像中的某些内容时都实例化一个新对象

所以,我用图形类来做这件事。 另外,我正在使用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);
    }
}

问题是
面板
类没有覆盖
getPreferredSize()
,因此它的首选大小实际上是(0,0),因此
流程布局
将为
面板
分配(0,0)大小

<>无论如何,我会考虑用简单的<代码> jLabel <代码> >替换你的<代码>面板>代码>类,它将做完全相同的事情并处理你喜欢的大小。

  • 调用
    setSize()
    在您同时使用LayoutManager(您应该这样做)时是无用的。通常,只需忘记
    setSize/setLocation/setBounds/setPreferredSize
    。答案总是一样的:“使用适当的
    LayoutManager
  • 对于自定义绘制,替代
    paintComponent
    而不是
    paint

问题在于
面板
类没有覆盖
getPreferredSize()
,因此其首选大小实际上是(0,0),因此
流程布局
将为
面板分配(0,0)大小

<>无论如何,我会考虑用简单的<代码> jLabel <代码> >替换你的<代码>面板>代码>类,它将做完全相同的事情并处理你喜欢的大小。

  • 调用
    setSize()
    在您同时使用LayoutManager(您应该这样做)时是无用的。通常,只需忘记
    setSize/setLocation/setBounds/setPreferredSize
    。答案总是一样的:“使用适当的
    LayoutManager
  • 对于自定义绘制,替代
    paintComponent
    而不是
    paint

您的形象有哪些变化?你不能修改它然后重新绘制吗?这只是一个简单应用程序的视图。因此,每当模型中的图像发生更改时,视图都会收到通知并再次设置图像,然后重新绘制图像本身。对吧?你可以这样做,或者你可以把它保留下来再利用。两种方法都可以。你的形象有什么变化?你不能修改它然后重新绘制吗?这只是一个简单应用程序的视图。因此,每当模型中的图像发生更改时,视图都会收到通知并再次设置图像,然后重新绘制图像本身。对吧?你可以这样做,或者你可以把它保留下来再利用。无论哪种方法都行。+1,我一开始很想念你关于使用JLabel:)OP也需要
revalidate()
组件,然后再调用
repaint()
,如果他们继续沿着自定义绘制路径。@camickr我也将+1你的答案,但因为它被删除而被拒绝;-)。是的,自定义绘制路径需要很多改进才能正常工作。谢谢回答。我想象它可能是JPanel大小的东西,所以我插入了设置行大小的代码。我做了一些测试:1-我刚刚用JPanel替换了JLabel-但是他们什么也没画出来。也不是那个小正方形的图像。2-我在面板类的setImage中插入了这一行:this.setPreferredSize(新维度(image.getWidth(),image.getHeight());-我没有改变我的第一个结果。3-我对定义布局管理的行进行注释,因此,使用默认行效果很好。但是,我想知道如何使用这个布局管理,并使其工作。Thks@EduardoReis框架内容窗格的默认布局管理器是BorderLayout,它会自动拉伸中心构件(只能有一个中心构件)。如果您正在寻找更多的帮助,请考虑发布。你的代码中有几十个可能的问题(你的图像大小正确吗?里面有什么东西吗?等等…@GuillaumePolet,图像加载正确。我设置了一个断点,我看到即使我将面板大小设置为500x500,但不知怎的,它还是设置为10x10。我可以在该绘制函数中插入一个setSize,但是当窗口被驻留时,仍然可以看到窗格是先绘制10x10,然后再绘制我在该方法上设置的大小。+1,我一开始就错过了您使用JLabel的建议:)OP还需要在调用
重新绘制()之前对组件进行
重新验证()
如果他们继续沿着自定义绘制路径进行绘制。@camickr我也将+1您的答案,但被拒绝,因为它已被删除;-)。是的,自定义绘制路径需要很多改进才能正常工作。谢谢回答。我想象它可能是JPanel大小的东西,所以我插入了设置行大小的代码。我做了一些测试:1-我刚刚用JPanel替换了JLabel-但是他们什么也没画出来。也不是那个小正方形的图像。2-我在面板类的setImage中插入了这一行:this.setPreferredSize(新维度(image.getWidth(),image.getHeight());-我没有改变我的第一个结果。3-我对定义布局管理的行进行注释,因此,使用默认行效果很好。但是,我想知道如何使用这个布局管理,并使其工作。Thks@EduardoReis框架内容窗格的默认布局管理器是BorderLayout,它会自动拉伸中心构件(只能有一个中心构件)。如果您正在寻找更多的帮助,请考虑发布。您的代码中有几十个可能的问题(是