所以我这个程序的目标是使用GUI制作一个基本的蚀刻草图。除了能够用鼠标绘制之外,我还需要添加一个按钮来更改任意四种颜色之间的线条颜色。由于我只是第一次学习这一点,因此在遇到问题之前,我已经更改了线条颜色:
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((;"行已经分开了。不过,我不知道它们到底是什么意思...它与我的问题有关吗?
尝试将静态全局变量放在文件的顶部;
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();
的值时触发事件<</p>
做的是通过构造函数传递对图形对象的引用:
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 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);
}
好的OOP设计是关于区分保持不变的内容和您预期将要扩展的内容。 你是蚀刻素描的铅笔将扩大很多(将添加不同的颜色,不同的厚度,生产盒子而不是涂鸦,也许是橡皮擦(。 您应该创建一个铅笔类。
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();
}
}
现在,您现在正在绘制缓冲图像。 然后,您将缓冲的图像绘制到内容窗格上。 这消除了我添加新铅笔类时出现的闪烁行为。 此方法称为"缓冲"。
一旦你得到了所有这些,你甚至可以练习一种叫做策略模式的设计模式。 这将允许您更改铅笔行为(而不是画线,也许画圆圈或其他东西(。 这个想法是g.drawLine代码不会在你的铅笔课中硬编码。
不要用getGraphics()
来画画。
是通过使用自定义绘制代码重写面板的paintComponent(...)
方法来完成的。
了解进行自定义绘画的几种不同方法的工作示例。这些示例演示如何绘制不同颜色的矩形。