Java JPanel getGraphics()

时间:2014-01-24 00:49:25

标签: java swing graphics jpanel paintcomponent

由于Java仅支持single inheritance,因此我希望paint直接在作为类JPanel成员的Panel的实例上。我从会员那里抓了一个Graphics的实例,然后把我想要的任何东西画在上面。

我怎样才能继承JComponentJPanel并仍然使用getGraphics()this上进行绘画而不覆盖public void paintComponent(Graphics g)

private class Panel
{
      private JPanel panel;
      private Grahics g;

      public Panel()
      {
           panel = new JPanel();
      }

      public void draw()
      {
           g = panel.getGraphics();
           g.setColor(Color.CYAN);
           g.draw(Some Component);
           panel.repaint();
      }
}

该面板已添加到JFrame,该panel.draw()在调用JPanel之前可见。这种方法对我不起作用,虽然我已经知道如何通过继承public void paintComponent(Graphics g)并覆盖JPanel来绘制自定义组件,但我不想继承{{1}}。

2 个答案:

答案 0 :(得分:5)

以下是一些非常简单的示例,展示如何在paintComponent之外进行绘制。

绘图实际上发生在java.awt.image.BufferedImage上,只要我们在事件派遣线程上,我们就可以在任何地方执行此操作。 (有关使用Swing进行多线程处理的讨论,请参阅herehere。)

然后,我正在覆盖paintComponent,但只是将图像绘制到面板上。 (我还在角落里画了一点色板。)

这样绘图实际上是永久性的,如果需要,Swing能够重新绘制面板,而不会给我们造成问题。如果我们愿意的话,我们也可以做一些像将文件轻松保存到文件中的东西。

PaintAnyTime screenshot

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

/**
 * Holding left-click draws, and
 * right-clicking cycles the color.
 */
class PaintAnyTime {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new PaintAnyTime();
            }
        });
    }

    Color[]    colors = {Color.red, Color.blue, Color.black};
    int  currentColor = 0;
    BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
    Graphics2D  imgG2 = img.createGraphics();

    JFrame frame = new JFrame("Paint Any Time");
    JPanel panel = new JPanel() {
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Creating a copy of the Graphics
            // so any reconfiguration we do on
            // it doesn't interfere with what
            // Swing is doing.
            Graphics2D g2 = (Graphics2D) g.create();
            // Drawing the image.
            int w = img.getWidth();
            int h = img.getHeight();
            g2.drawImage(img, 0, 0, w, h, null);
            // Drawing a swatch.
            Color color = colors[currentColor];
            g2.setColor(color);
            g2.fillRect(0, 0, 16, 16);
            g2.setColor(Color.black);
            g2.drawRect(-1, -1, 17, 17);
            // At the end, we dispose the
            // Graphics copy we've created
            g2.dispose();
        }
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(img.getWidth(), img.getHeight());
        }
    };

    MouseAdapter drawer = new MouseAdapter() {
        boolean rButtonDown;
        Point prev;

        @Override
        public void mousePressed(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                prev = e.getPoint();
            }
            if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
                // (This just behaves a little better
                // than using the mouseClicked event.)
                rButtonDown  = true;
                currentColor = (currentColor + 1) % colors.length;
                panel.repaint();
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (prev != null) {
                Point  next = e.getPoint();
                Color color = colors[currentColor];
                // We can safely paint to the
                // image any time we want to.
                imgG2.setColor(color);
                imgG2.drawLine(prev.x, prev.y, next.x, next.y);
                // We just need to repaint the
                // panel to make sure the
                // changes are visible
                // immediately.
                panel.repaint();
                prev = next;
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                prev = null;
            }
            if (SwingUtilities.isRightMouseButton(e)) {
                rButtonDown = false;
            }
        }
    };

    PaintAnyTime() {
        // RenderingHints let you specify
        // options such as antialiasing.
        imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        imgG2.setStroke(new BasicStroke(3));
        //
        panel.setBackground(Color.white);
        panel.addMouseListener(drawer);
        panel.addMouseMotionListener(drawer);
        Cursor cursor =
            Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
        panel.setCursor(cursor);
        frame.setContentPane(panel);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

也可以使用JLabel设置ImageIcon,但我个人不喜欢这种方法。我认为他们的规范不需要JLabelImageIcon来查看我们在将图像传递给构造函数后对图像所做的更改。

这种方式也不会让我们像绘制色板一样。 (对于稍微复杂的绘图程序,在MSPaint的层面上,我们想要有一种方法来选择一个区域并在它周围绘制一个边界框。这是我们希望能够直接绘制的另一个地方面板,除了绘制图像外。)

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

/**
 * Holding left-click draws, and
 * right-clicking cycles the color.
 */
class PaintAnyTime {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new PaintAnyTime();
            }
        });
    }

    Color[]    colors = {Color.red, Color.blue, Color.black};
    int  currentColor = 0;
    BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
    Graphics2D  imgG2 = img.createGraphics();

    JFrame frame = new JFrame("Paint Any Time");
    JLabel label = new JLabel(new ImageIcon(img));

    MouseAdapter drawer = new MouseAdapter() {
        boolean rButtonDown;
        Point prev;

        @Override
        public void mousePressed(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                prev = e.getPoint();
            }
            if (SwingUtilities.isRightMouseButton(e) && !rButtonDown) {
                // (This just behaves a little better
                // than using the mouseClicked event.)
                rButtonDown  = true;
                currentColor = (currentColor + 1) % colors.length;
                label.repaint();
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (prev != null) {
                Point  next = e.getPoint();
                Color color = colors[currentColor];
                // We can safely paint to the
                // image any time we want to.
                imgG2.setColor(color);
                imgG2.drawLine(prev.x, prev.y, next.x, next.y);
                // We just need to repaint the
                // label to make sure the
                // changes are visible
                // immediately.
                label.repaint();
                prev = next;
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (SwingUtilities.isLeftMouseButton(e)) {
                prev = null;
            }
            if (SwingUtilities.isRightMouseButton(e)) {
                rButtonDown = false;
            }
        }
    };

    PaintAnyTime() {
        // RenderingHints let you specify
        // options such as antialiasing.
        imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        imgG2.setStroke(new BasicStroke(3));
        //
        label.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
        label.setBackground(Color.white);
        label.setOpaque(true);
        label.addMouseListener(drawer);
        label.addMouseMotionListener(drawer);
        Cursor cursor =
            Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR);
        label.setCursor(cursor);
        frame.add(label, BorderLayout.CENTER);
        frame.pack();
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}

答案 1 :(得分:-1)

class SomeComponent extends JComponent {

    private Graphics2D g2d;

    public void paintComponent(Graphics g) {
        g2d = (Graphics2D) g.create();
        g2d.setColor(Color.BLACK);
        g2d.scale(scale, scale);
        g2d.drawOval(0, 0, importance, importance);

    }

    public Graphics2D getG2d() {
        return g2d;
    }
    public void setG2d(Graphics2D g2d) {
        this.g2d = g2d;
    }
}

然后您可以执行以下操作 获取面板中的SomeComponent实例并进行修改

Graphics2D x= v.getPanel().get(i).getG2d;
x.setColor(Color.BLUE);
v.getPanel().get(i).setG2d(x);
v.getPanel().repaint();
v.getPanel().revalidate();

V是一个扩展JFrame并在其中包含面板的类 我是SomeComponent的实例