Java JPanel getGraphics() [英] Java JPanel getGraphics()

查看:97
本文介绍了Java JPanel getGraphics()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为Java只支持单一继承,我希望直接在<$ c $的一个实例上绘制 c> JPanel ,它是类 Panel 的成员。我从成员中获取 Graphics 的一个实例,然后绘制我想要的任何内容。



我怎么能继承自 JComponent JPanel 并仍然使用 getGraphics()用于在这个上绘制而不用重写 public void paintComponent(Graphics g)

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

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

public void draw()
{
g = panel.getGraphics();
g.setColor(Color.CYAN);
g.draw(某个组件);
panel.repaint();






$ 面板被添加到 JFrame ,它在调用 panel.draw()之前变得可见。虽然我已经知道如何通过从 JPanel 继承并覆盖 public void paintComponent(Graphics g)来绘制自定义组件, ,我不想继承 JPanel

解决方案下面是一些非常简单的例子,它们显示了如何在 paintComponent 之外进行绘制。



发生在 java.awt.image.BufferedImage 上,我们可以在任何地方做到这一点,只要我们在Event Dispatch Thread上。 (有关Swing多线程的讨论,请参见

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

/ **
*持有左键单击,并且
*右键单击该颜色。
* /
class PaintAnyTime {
public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new PaintAnyTime();
}
});
}

颜色[]颜色= {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);
//创建Graphics
的副本//所以我们在
上做的任何重新配置​​//它不会影响
// Swing正在做什么。
Graphics2D g2 =(Graphics2D)g.create();
//绘制图像。
int w = img.getWidth();
int h = img.getHeight();
g2.drawImage(img,0,0,w,h,null);
//绘制色板。
颜色颜色=颜色[currentColor];
g2.setColor(color);
g2.fillRect(0,0,16,16);
g2.setColor(Color.black);
g2.drawRect(-1,-1,17,17);
//最后,我们处理
//我们创建的图形副本
g2.dispose();

@Override
public Dimension getPreferredSize(){
return new Dimension(img.getWidth(),img.getHeight());
}
};

MouseAdapter drawer = new MouseAdapter(){
boolean rButtonDown;
点前置;

@Override
public void mousePressed(MouseEvent e){
if(SwingUtilities.isLeftMouseButton(e)){
prev = e.getPoint();
}
if(SwingUtilities.isRightMouseButton(e)&&!rButtonDown){
//(这只比使用mouseClicked事件表现得更好一点
//。 )
rButtonDown = true;
currentColor =(currentColor + 1)%colors.length;
panel.repaint();
}
}

@Override
public void mouseDragged(MouseEvent e){
if(prev!= null){
next next = e.getPoint();
颜色颜色=颜色[currentColor];
//我们可以在任何时候安全地绘制到
//图像。
imgG2.setColor(color);
imgG2.drawLine(prev.x,prev.y,next.x,next.y);
//我们只需要重新绘制
//面板以确保
//变化立即可见
//。
panel.repaint();
prev = next;



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

PaintAnyTime(){
// RenderingHints让您指定
//选项,例如抗锯齿。
imgG2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
imgG2.setStroke(new BasicStroke(3));
//
panel.setBackground(Color.white);
panel.addMouseListener(抽屉);
panel.addMouseMotionListener(drawer);
游标游标=
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);


$ / code $ / pre

也可以设置 JLabel 与一个 ImageIcon ,尽管我个人不喜欢这种方法。我不认为 JLabel ImageIcon 是他们的规范所要求的,我把它传递给了构造函数。



这种方法也不会让我们做像绘制色板这样的东西。 (对于稍微复杂一点的绘画程序,例如MSPaint,我们希望能够选择一个区域并在其周围画一个边框,这是我们希望能够直接绘制的另一个地方);

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

/ **
*持有左键单击,并且
*右键单击该颜色。
* /
class PaintAnyTime {
public static void main(String [] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
new PaintAnyTime();
}
});
}

颜色[]颜色= {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标签=新的JLabel(新的ImageIcon(img));

MouseAdapter drawer = new MouseAdapter(){
boolean rButtonDown;
点前置;

@Override
public void mousePressed(MouseEvent e){
if(SwingUtilities.isLeftMouseButton(e)){
prev = e.getPoint();
}
if(SwingUtilities.isRightMouseButton(e)&&!rButtonDown){
//(这只比使用mouseClicked事件表现得更好一点
//。 )
rButtonDown = true;
currentColor =(currentColor + 1)%colors.length;
label.repaint();
}
}

@Override
public void mouseDragged(MouseEvent e){
if(prev!= null){
next next = e.getPoint();
颜色颜色=颜色[currentColor];
//我们可以在任何时候安全地绘制到
//图像。
imgG2.setColor(color);
imgG2.drawLine(prev.x,prev.y,next.x,next.y);
//我们只需要重新绘制
//标签以确保
//更改立即可见
// //。
label.repaint();
prev = next;



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

PaintAnyTime(){
// RenderingHints让您指定
//选项,例如抗锯齿。
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.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);
}
}


Since Java only supports single inheritance, I desire to paint directly on an instance of a JPanel that is a member of the class Panel. I grab an instance of Graphics from the member and then paint whatever I desire onto it.

How can I not inherit from JComponent or JPanel and still utilize getGraphics() for painting on this without overriding 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();
      }
}

The panel is added to a JFrame that is made visible prior to calling panel.draw(). This approach is not working for me and, although I already know how to paint custom components by inheriting from JPanel and overriding public void paintComponent(Graphics g), I did not want to inherit from JPanel.

解决方案

Here are some very simple examples which show how to paint outside paintComponent.

The drawing actually happens on a java.awt.image.BufferedImage, and we can do that anywhere, as long as we're on the Event Dispatch Thread. (For discussion of multithreading with Swing, see here and here.)

Then, I'm overriding paintComponent, but only to paint the image on to the panel. (I also paint a little swatch in the corner.)

This way the drawing is actually permanent, and Swing is able to repaint the panel if it needs to without causing a problem for us. We could also do something like save the image to a file easily, if we wanted to.

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);
    }
}

It's also possible to set up a JLabel with an ImageIcon, although personally I don't like this method. I don't think JLabel and ImageIcon are required by their specifications to see changes we make to the image after we've passed it to the constructors.

This way also doesn't let us do stuff like painting the swatch. (For a slightly more complicated paint program, on the level of e.g. MSPaint, we'd want to have a way to select an area and draw a bounding box around it. That's another place we'd want to be able to paint directly on the panel, in addition to drawing to the image.)

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);
    }
}

这篇关于Java JPanel getGraphics()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆