【问题标题】:Java Draw Image JPanel: Working but weirdJava Draw Image JPanel:工作但很奇怪
【发布时间】:2013-04-24 14:25:20
【问题描述】:

我知道到处都有关于如何绘制图像的辅导。通常人们建议显示它添加一个加载该图像的对象。但就我而言,我不想每次更改图像中的某些内容时都实例化一个新对象。

所以,我正在使用 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);
    }
}

【问题讨论】:

  • 你的形象有什么变化?你不能修改然后重绘它吗?
  • 这只是一个简单应用程序的视图。因此,每当模型中的图像发生变化时,视图都会收到通知并再次设置图像,然后重新绘制自己。对吗?
  • 您可以这样做,或者您可以保留它并重复使用它。无论哪种方式都可以。

标签: java swing drawing jframe bufferedimage


【解决方案1】:

问题是您的Panel 类不会覆盖getPreferredSize(),因此它的首选大小实际上是(0,0),因此FlowLayout 将为您的@987654325 分配一个(0,0) 的大小@。

无论如何,我会考虑用简单的JLabel 替换您的Panel 类,这将做完全相同的事情并为您处理首选大小。

  • 当您还使用 LayoutManager(您应该这样做)时,调用 setSize() 是没有用的。一般来说,只需忘记setSize/setLocation/setBounds/setPreferredSize。答案总是一样的:“使用适当的LayoutManager
  • 对于自定义绘画,覆盖 paintComponent 而不是 paint

【讨论】:

  • +1,我最初错过了您使用 JLabel 的建议 :) 如果继续沿自定义绘制路径,OP 还需要在调用 repaint() 之前revalidate() 组件。跨度>
  • @camickr 我也打算为你的答案+1,但因为它被删除了所以拒绝了 ;-)。是的,自定义绘画路径需要许多改进才能正常工作。
  • 感谢您的回答。我想象它可能是 JPanel 大小的东西,所以我插入了 setSize 行的代码。我做了一些测试: 1 - 我刚刚将 JPanel 替换为 JLabel - 但是它们没有绘制任何内容。也不是那个小正方形的图像。 2 - 我在 Panel 类的 setImage 中插入了这一行: this.setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); - 我没有改变我的第一个结果。 3 - 我评论了我正在定义我的布局管理的行,因此,使用默认的行很好。但是,我想知道如何使用这个布局管理,并使它工作。谢谢
  • @EduardoReis 框架内容窗格的默认布局管理器是BorderLayout,它会自动拉伸中心组件(中心组件只能有一个)。如果您正在寻求更多帮助,请考虑发布SSCCE。您的代码中有许多可能的问题(您的图像大小是否正确?里面有什么东西吗?等等...)
  • @GuillaumePolet,图片已正确加载。我放了一个断点,我看到即使我将面板大小设置为 500x500,它也以某种方式设置为 10x10。我可以在该绘制函数中插入一个 setSize,但是当驻留窗口时,仍然可以看到窗格首先绘制 10x10 并且在我放在该方法上的大小之后。
猜你喜欢
  • 2014-08-15
  • 2011-05-07
  • 1970-01-01
  • 2015-12-07
  • 2016-07-10
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
相关资源
最近更新 更多