簡體   English   中英

將JPanel保存為圖像(對象)並將其繪制回JPanel

[英]Saving a JPanel as an Image (object) and drawing it back onto a JPanel

我環顧四周並嘗試使用其他查詢,但似乎無法正常工作。

我試圖保留通過g.draw / fill方法繪制的JPanel的圖像。

我試圖將圖形保存在緩沖的圖像中,但是當我在messageDialog中顯示它時,我得到的只是背景,沒有一個圖形

這兩個方法是重要的代碼(來自DrawingPanel類):

        public void loadDrawing(BufferedImage bi) {
            //opens a message dialog and displays the image parameter
            JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
            System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
        }

        public BufferedImage getScreenShot() {

            BufferedImage image = new BufferedImage(this.getWidth(),
                    this.getHeight(), BufferedImage.TYPE_INT_RGB);
            // call the Panels's paint method, using
            // the Graphics object of the image.
            this.paint(image.getGraphics());
            return image;
        }

他們在這里打來電話:

        @Override
    public void actionPerformed(ActionEvent ae) {
        BufferedImage bi = dp.getScreenShot();
        dp.loadDrawing(bi);
    }

這是整個程序,它應該運行。

      import java.awt.BorderLayout;
      import java.awt.Color;
      import java.awt.Graphics;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.awt.event.MouseEvent;
      import java.awt.event.MouseListener;
      import java.awt.event.MouseMotionListener;
      import java.awt.image.BufferedImage;
      import javax.swing.ImageIcon;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JLabel;
      import javax.swing.JOptionPane;
      import javax.swing.JPanel;

public class TestClass extends JFrame implements ActionListener {

    DrawingPanel dp;

    public TestClass() {
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel top = new JPanel();
        JButton load = new JButton("Load Image");
        load.addActionListener(this);
        top.add(load);

        dp = new DrawingPanel();
        dp.setBackground(Color.CYAN);

        add(top, BorderLayout.NORTH);
        add(dp, BorderLayout.CENTER);
        setVisible(true);
    }

    public static void main(String[] args) {
        new TestClass();
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        BufferedImage bi = dp.getScreenShot();
        dp.loadDrawing(bi);
    }

    private class DrawingPanel extends JPanel implements 
      MouseListener, MouseMotionListener {

        private int xPos, yPos;//mouse positions

        private DrawingPanel() {
            addMouseListener(this);
            addMouseMotionListener(this);
        }

        @Override
        public void mousePressed(MouseEvent me) {
            xPos = me.getX();
            yPos = me.getY();
        }

        @Override
        public void mouseDragged(MouseEvent me) {
            int x = me.getX(), y = me.getY();
            Graphics g = getGraphics();
            g.setColor(Color.BLACK);
            g.drawOval(xPos, yPos, 30, 30);
            xPos = x;
            yPos = y;
        }

        public void loadDrawing(BufferedImage bi) {
            //opens a message dialog and displays the image parameter
            JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
            System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
        }

        public BufferedImage getScreenShot() {

            BufferedImage image = new BufferedImage(this.getWidth(),
                    this.getHeight(), BufferedImage.TYPE_INT_RGB);
            // call the Panels's paint method, using
            // the Graphics object of the image.
            this.paint(image.getGraphics());
            return image;
        }

        //unused abstract method
        @Override
        public void mouseClicked(MouseEvent me) {
        }

        @Override
        public void mouseReleased(MouseEvent me) {
        }

        @Override
        public void mouseEntered(MouseEvent me) {
        }

        @Override
        public void mouseExited(MouseEvent me) {
        }

        @Override
        public void mouseMoved(MouseEvent me) {
        }
    }
}

我需要能夠從面板中存儲圖形並檢索它。

幫助將不勝感激。

通過在組件上調用getGraphics()來獲取Graphics對象,使用該對象繪制的圖像將不會保留。 為什么不使用它的 Graphics對象繪制一個BufferedImage,然后簡單地保存該BufferedImage呢? 這樣可以大大簡化事情,並且您的程序可以運行。

例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.*;

public class TestClass2 extends JPanel {
   private DrawingPanel drawingPanel = new DrawingPanel();

   public TestClass2() {     
      JPanel northPanel = new JPanel();
      northPanel.add(new JButton(new GetImageAction("Get Image")));
      northPanel.add(new JButton(new ClearImageAction("Clear Image")));

      setLayout(new BorderLayout(5, 5));
      add(drawingPanel, BorderLayout.CENTER);
      add(northPanel, BorderLayout.NORTH);

   }

   private class GetImageAction extends AbstractAction {
      public GetImageAction(String name) {
         super(name);
         putValue(MNEMONIC_KEY, KeyEvent.VK_G);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         BufferedImage img = drawingPanel.getMainImage();
         ImageIcon icon = new ImageIcon(img);
         JOptionPane.showMessageDialog(TestClass2.this, icon);
      }
   }

   private class ClearImageAction extends AbstractAction {
      public ClearImageAction(String name) {
         super(name);
         putValue(MNEMONIC_KEY, KeyEvent.VK_C);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         drawingPanel.clearImage();
         drawingPanel.repaint();
      }
   }


   private static void createAndShowGui() {
      TestClass2 mainPanel = new TestClass2();

      JFrame frame = new JFrame("TestClass2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class DrawingPanel extends JPanel {
   public static final int BI_WIDTH = 400;
   public static final int BI_HEIGHT = BI_WIDTH;
   private static final Color BACKGROUND = Color.CYAN;
   public static final Color DRAW_COLOR = Color.black;
   public static final int OVAL_WIDTH = 30;
   private BufferedImage mainImage;

   public DrawingPanel() {
      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseListener(myMouseAdapter);
      addMouseMotionListener(myMouseAdapter);
      clearImage();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (mainImage != null) {
         g.drawImage(mainImage, 0, 0, this);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(BI_WIDTH, BI_HEIGHT);
   }

   public BufferedImage getMainImage() {
      return mainImage;
   }

   public void clearImage() {
      mainImage = new BufferedImage(BI_WIDTH, BI_HEIGHT, BufferedImage.TYPE_INT_ARGB);
      Graphics g = mainImage.getGraphics();
      g.setColor(BACKGROUND);
      g.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
      g.dispose();
   }

   private class MyMouseAdapter extends MouseAdapter {

      @Override
      public void mousePressed(MouseEvent mEvt) {
         draw(mEvt);
      }

      @Override
      public void mouseDragged(MouseEvent mEvt) {
         draw(mEvt);
      }

      private void draw(MouseEvent mEvt) {
         Graphics2D g2 = mainImage.createGraphics();
         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
         g2.setColor(DRAW_COLOR);
         g2.drawOval(mEvt.getX() - OVAL_WIDTH / 2, mEvt.getY() - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
         g2.dispose();
         repaint();
      }
   }

}

通過調用getGraphicsComponent獲得的將某些東西繪制到Graphics對象中的任何嘗試都會遲早失敗。 Graphics對象僅充當實際屏幕的“路徑”(僅在組件實際繪制在屏幕上時才有效)。 它不是“緩沖區”,也不“存儲”繪制的任何內容。

如果要創建一個簡單的繪畫程序,則應繪制到BufferedImage 當繪制DrawingPanel時,只需繪制此BufferedImage 這里的另一個優點是,當您要制作屏幕截圖時,基本上只需要返回此BufferedImage的副本即可。

我在您的DrawingPanel類中添加了一些內聯注釋,從而簡化了基本方法。 可以對其進行清理和美化,並且需要考慮一些方面(例如,調整DrawingPanel的大小時會發生什么?),但它總體上顯示了其工作方式:

private class DrawingPanel extends JPanel implements 
    MouseListener, MouseMotionListener {

    // The image that will store what was drawn. In the
    // mouseDragged method, the painting operations will
    // go directly to this image. When this panel is
    // painted, then ONLY this image will be painted.
    private BufferedImage bufferedImage;

    private int xPos, yPos;//mouse positions

    private DrawingPanel() {
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    // Make sure that the "bufferedImage" is non-null
    // and has the same size as this panel
    private void validateImage()
    {
        if (bufferedImage == null)
        {
            bufferedImage = new BufferedImage(
                getWidth(), getHeight(), 
                BufferedImage.TYPE_INT_ARGB);
            Graphics g = bufferedImage.getGraphics();
            g.setColor(getBackground());
            g.fillRect(0,0,getWidth(),getHeight());
            g.dispose();

        }
        if (bufferedImage.getWidth() != getWidth() ||
            bufferedImage.getHeight() != getHeight())
        {
            BufferedImage newBufferedImage = new BufferedImage(
                getWidth(), getHeight(), 
                BufferedImage.TYPE_INT_ARGB);
            Graphics g = newBufferedImage.getGraphics();
            g.setColor(getBackground());
            g.fillRect(0,0,getWidth(),getHeight());
            g.drawImage(bufferedImage, 0,0,null);
            g.dispose();
            bufferedImage = newBufferedImage;
        }
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        validateImage();

        // Paint the bufferedImage which stores
        // what was drawn until now
        g.drawImage(bufferedImage, 0, 0, null);
    }


    @Override
    public void mousePressed(MouseEvent me) {
        xPos = me.getX();
        yPos = me.getY();
    }


    @Override
    public void mouseDragged(MouseEvent me) {
        int x = me.getX(), y = me.getY();
        validateImage();

        // Paint directly into the bufferedImage here
        Graphics g = bufferedImage.getGraphics();
        g.setColor(Color.BLACK);
        g.drawOval(xPos, yPos, 30, 30);
        repaint();
        xPos = x;
        yPos = y;
    }

    public void loadDrawing(BufferedImage bi) {
        //opens a message dialog and displays the image parameter
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
        System.out.println("w:" + bi.getWidth() + " h:" + bi.getHeight());
    }

    public BufferedImage getScreenShot() {

        // This basically returns a "copy" of the
        // bufferedImage that stores what was drawn
        BufferedImage image = new BufferedImage(
            getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        g.drawImage(bufferedImage, 0, 0, null);
        g.dispose();
        return image;
    }

    //unused abstract method
    @Override
    public void mouseClicked(MouseEvent me) {
    }

    @Override
    public void mouseReleased(MouseEvent me) {
    }

    @Override
    public void mouseEntered(MouseEvent me) {
    }

    @Override
    public void mouseExited(MouseEvent me) {
    }

    @Override
    public void mouseMoved(MouseEvent me) {
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM