Java:不确定如何在单独的类中修改Graphics对象

时间:2017-03-26 02:10:37

标签: java user-interface

所以我的这个程序的目标是使用GUI制作一个基本的Etch-A-Sketch。除了能够使用鼠标绘图之外,我还需要添加一个按钮来更改任何四种颜色之间的线条颜色。因为我刚刚第一次学习这个,所以在遇到问题之前,我已经改变了线条颜色:

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

public class Etch_A_Sketch implements MouseListener, MouseMotionListener
{
    JFrame window;
    Container content;
    int mouseX,mouseY,oldX,oldY;
    JButton colorButton;
    ActionListener bPress = new MyListener();

    public Etch_A_Sketch()
    {
        JFrame window = new JFrame("Classic Etch a Sketch");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        content = window.getContentPane();
        window.setSize(640,480);
        content.setLayout( new FlowLayout() );

        content.addMouseListener(this);
        content.addMouseMotionListener(this);           
        colorButton = new JButton("Click to switch color!");
        colorButton.setSize(175,50);
        colorButton.setVisible(true);
        colorButton.addActionListener(bPress);
        content.add(colorButton);

        window.setVisible(true);
    }


    public void mouseClicked( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();

    }

    public void mousePressed( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();
        //repaint();
    }

    public void mouseReleased( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();
        //repaint();
    }

    public void mouseExited( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();
        //repaint();
    }

    public void mouseEntered( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();
        //repaint();
    }

    public void mouseDragged( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();

        if (oldX ==0 )
        {
            oldX=mouseX;
            oldY=mouseY;
            return;
        }


        Graphics g = content.getGraphics(); // use g to draw onto the pane
        g.drawLine( oldX,oldY, mouseX, mouseY );
        oldX = mouseX;
        oldY = mouseY;
        // repaint();
    }

    public void mouseMoved( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();
        //repaint();
    }

    class MyListener implements ActionListener
    {
        final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE};
        int index = 0;

        public void actionPerformed(ActionEvent e)
        {   
            g.setColor(colors[index]);
            index = (index + 1) % colors.length;
        }
    }


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

我的问题是这个 - 我意识到MyListener类中对“g”的引用超出了范围,因为它是mouseDragged方法的一部分。当我的JButton被按下时,我怎么能够改变呢?我已经尝试在方法之外移动g的声明,但它没有用。任何帮助将不胜感激!

另外,值得注意的是我有一个基本文件来启动这个项目,并且“// repaint();”线已经分开了。我不确切地知道他们的意思,但是......这与我的问题有关吗?

4 个答案:

答案 0 :(得分:0)

尝试将静态全局变量放在文件的顶部;

static Graphics g = null;

然后在public void mouseDragged( MouseEvent me)

Etch_A_Sketch.g = content.getGraphics(); // use g to draw onto the pane

然后在class MyListener

中引用它

有趣的是,为了安全起见,我建议使用界面。在主类中声明一个,让类实现它,然后在需要content.getGraphics();

的值时触发事件

答案 1 :(得分:0)

您可以做的是通过构造函数传递对图形对象的引用:

class MyListener implements ActionListener
{
    private final Graphics graphics;
    private final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE};
    private int index = 0;

    public MyListener(Graphics graphics)
    {
        this.graphics = graphics;
    }

    public void actionPerformed(ActionEvent e)
    {   
        this.graphics.setColor(colors[index]);
        index = (index + 1) % colors.length;
    }
}

现在在创建ActionListener时,而不是这样做......

ActionListener bPress = new MyListener();

public Etch_A_Sketch()
{
    JFrame window = new JFrame("Classic Etch a Sketch");
    // ...
    // ...
    colorButton.addActionListener(bPress);
    content.add(colorButton);

    window.setVisible(true);
}

你可以这样做:

public Etch_A_Sketch()
{
    JFrame window = new JFrame("Classic Etch a Sketch");
    // ...
    // ...
    Graphics graphics = content.getGraphics();
    colorButton.addActionListener(new MyListener(graphics));
    content.add(colorButton);

    window.setVisible(true);
}

答案 2 :(得分:0)

良好的OOP设计是将保持不变的内容与您预期扩展的内容分开。你是etcha sketch的铅笔会扩大很多(将添加不同的颜色,不同的厚度,生产盒子而不是涂鸦,也许是橡皮擦)。你应该创建一个Pencil类。

public class Pencil {
    private Graphics backGroundGraphics;
    final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE};
    private int colorIndex;


public Pencil(BufferedImage backGround) {
    backGroundGraphics = backGround.getGraphics();
    backGroundGraphics.setColor(Color.BLACK);
}

    public void changeColor() {
        colorIndex++;
        backGroundGraphics.setColor(colors[colorIndex % 4]);
    } 

    public void drawLine(int oldX, int oldY, int mouseX, int mouseY) {
         backGroundGraphics.drawLine(oldX,oldY, mouseX, mouseY);
    }
}

然后在你的GUI类中添加所有这些:

class  Etch_A_Sketch implements MouseListener, MouseMotionListener {

    ...
   private Pencil pencil;
   BufferedImage bf;

   ...
   ...

        public Etch_A_Sketch()
        {
        bf = new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
        pencil = new Pencil(bf);
            ....
            ....
}
                           ....

public void mouseDragged( MouseEvent me)
    {
        mouseX = me.getX();
        mouseY = me.getY();

        if (oldX ==0 )
        {
            oldX=mouseX;
            oldY=mouseY;
            return;
        }

        pencil.drawLine(oldX, oldY, mouseX, mouseY);
        Graphics g2 = content.getGraphics();

        g2.drawImage(bf, 0, 0, content);

        oldX = mouseX;
        oldY = mouseY;

    }


                 ....

class MyListener implements ActionListener
{
    final Color[] colors = {Color.RED, Color.BLUE, Color.GREEN, Color.ORANGE};
    int index = 0;

    public void actionPerformed(ActionEvent e)
    {   
        pencil.changeColor();
    }
}

现在,您正在绘制缓冲图像。然后,您将该缓冲的图像绘制到contentPane上。这消除了我添加新铅笔类时出现的闪烁行为。这种方法称为“缓冲”。

一旦掌握了所有这些,您甚至可以练习一种名为策略模式的设计模式。这将允许您更改铅笔行为(而不是画线,可能画圆圈或其他东西)。这个想法是g.drawLine代码不会在你的铅笔类中进行硬编码。

答案 3 :(得分:-1)

请勿使用getGraphics()进行绘画。

通过使用自定义绘画代码覆盖面板的paintComponent(...)方法来完成绘画。

查看Custom Painting Approaches了解自定义绘画的几种不同方法的工作示例。这些示例向您展示了如何绘制不同颜色的矩形。