【问题标题】:Difference between Graphics object of getGraphics and paintComponentgetGraphics的Graphics对象和paintComponent的区别
【发布时间】:2014-01-15 04:28:53
【问题描述】:

如果我使用的是 JPanel,getGraphics 返回的 Graphics 对象与 paintComponent 方法中传递的 Graphics 对象有什么区别?

【问题讨论】:

    标签: java graphics paint paintcomponent repaint


    【解决方案1】:

    getGraphics

    • 可以是null
    • 是最后一次绘制过程的“快照”
    • 在其上绘制的任何内容都将在下一个绘制周期中丢失

    您应该避免使用 getGraphics 并简单地使用 paintComponent 方法的过去内容。

    理论上,它们之间没有区别,但如果你想让你画的东西在重画之间继续存在,那么你应该使用paintComponent

    更新示例

    没有示例代码,我猜...但是...

    基本上,这有一个JPanel,它充当绘制图像的主要“画布”,并且当设置时,它是一个作为选择的@ 987654328。

    它使用第二个类作为MouseListener 来实际决定要绘制什么

    import java.awt.AlphaComposite;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Composite;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class MouseSelection {
    
        public static void main(String[] args) {
            new MouseSelection();
        }
    
        public MouseSelection() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    ImagePane imgPane = new ImagePane();
                    new MouseHandler(imgPane);
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(imgPane);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class MouseHandler    extends MouseAdapter {
    
            private ImagePane imgPane;
    
            private Point clickPoint;
    
            public MouseHandler(ImagePane imgPane) {
                this.imgPane = imgPane;
                imgPane.addMouseMotionListener(this);
                imgPane.addMouseListener(this);
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                imgPane.clearSelection();
                clickPoint = e.getPoint();
            }
    
            @Override
            public void mouseReleased(MouseEvent e) {
                clickPoint = null;
            }
    
            @Override
            public void mouseDragged(MouseEvent e) {
                if (clickPoint != null) {
                    Point dragPoint = e.getPoint();
    
                    int x = Math.min(clickPoint.x, dragPoint.x);
                    int y = Math.min(clickPoint.y, dragPoint.y);
                    int width = Math.max(clickPoint.x, dragPoint.x) - x;
                    int height = Math.max(clickPoint.y, dragPoint.y) - y;
    
                    imgPane.setSelection(new Rectangle(x, y, width, height));
    
                }
            }
    
        }
    
        public class ImagePane extends JPanel {
    
            private BufferedImage img;
            private Rectangle selection;
    
            public ImagePane() {
                try {
                    img = ImageIO.read(new File("C:\\hold\\thumbnails\\issue459.jpg"));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
                return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                if (img != null) {
                    int x = (getWidth() - img.getWidth()) / 2;
                    int y = (getHeight() - img.getHeight()) / 2;
                    g2d.drawImage(img, x, y, this);
                }
                if (selection != null) {
    
                    Color color = UIManager.getColor("Table.selectionBackground");
                    g2d.setColor(color);
                    Composite comp = g2d.getComposite();
                    g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                    g2d.fill(selection);
                    g2d.setComposite(comp);
                    g2d.draw(selection);
    
                }
                g2d.dispose();
            }
    
            protected void clearSelection() {
                selection = null;
                repaint();
            }
    
            protected void setSelection(Rectangle rectangle) {
                selection = rectangle;
                repaint();
            }
        }
    
    }
    

    【讨论】:

    • 我问是因为我在拖动鼠标时正在绘制一个矩形,当我使用 getGraphics 然后重新绘制时会出现闪烁,但是当我使用 paintComponent 绘制矩形然后重新绘制时效果很好。为什么会发生这种情况?
    • 鼠标(可能)导致重绘被触发,paintComponent 方法(间接)被调用并填充背景,丢弃您之前使用 getGraphics 绘制的内容。改为在 paintComponent 方法中更新您的矩形
    • 问题是我正在其他类中进行矩形绘画,以便在必要时覆盖行为,这就是我尝试使用 getGraphics 的原因,但结果不太好。有没有办法使用paintComponent在外面进行绘画?
    • 简答,不。长答案,不。您可能需要做的是设置两个类可以共享的某种模型
    • 我们的目标是实现某种状态(设计模式)方法,将绘图行为委托给特定的类......虽然模型似乎可维护且更好,但性能绘图并不是我所期望的。
    猜你喜欢
    • 2013-10-21
    • 2014-10-07
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2011-10-07
    相关资源
    最近更新 更多