4

I try to implement two classes, one dedicated to the interface and the other one dedicated to the canvas allowing user to draw shapes on it.

So basically, let's take one of my button, here is my Jbutton bCircle where I want to initialize the action in an anonymous class. I have put just the specific piece :

public class Application extends JFrame implements ActionListener {

    toolBar.add(Box.createHorizontalGlue());
    toolBar.add(Box.createVerticalGlue());
    toolBar.add(bSquare, toolBar.getComponentCount() - 1);
    toolBar.add(bCircle, toolBar.getComponentCount() - 1);
    bCircle.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent event){
        //Action ?????
    }
});
    toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
    toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
    toolBar.add(bErase, toolBar.getComponentCount() - 1);
    toolBar.setOrientation(SwingConstants.VERTICAL);
    container.add(toolBar, BorderLayout.WEST);
}

And in the other class, here is the action I want the selected state of the Jbutton bCircle to execute when I click on the canvas :

public class DrawingCanvas extends JPanel implements MouseListener, MouseMotionListener {

    public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub
        if(e.getSource() == bCircle) {
            shapes.add(new Circle(e.getX(),e.getY()));
        }
        repaint();
    }
}

shapes is a ArrayList stocking the shapes to make the canvas easier to clean, Circle is a class which only contains drawing of the circle.

At the end, the purpose is to allow user to click first on four buttons representing four shapes, then draw them by a mouse pressed on the canvas. But I don't know how to link theses two classes, please help me,

Thanks in advance,

P.S : the full Application class (interface) that I have updated a second time:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;

public class Application extends JFrame implements ActionListener {

{
    //Set appearance Look & Feel for the window
try { javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch(Exception e) {
        e.printStackTrace();
    }
}

    private DrawingCanvas canvas = new DrawingCanvas();
    private JPanel container = new JPanel();
    private JPanel commandes = new JPanel();
    private JMenuBar menu = new JMenuBar();
    private JMenu newFile = new JMenu();
    private JMenu open = new JMenu(); 
    private JMenu save = new JMenu();
    private JFileChooser fileChooser;
    private JToolBar toolBar = new JToolBar();

    private JButton bSquare = new JButton("Square");
    private JButton bRectangle = new JButton("Rectangle");
    private JButton bCircle = new JButton("Circle");
    private JButton bTriangle = new JButton("Triangle");
    private JButton bErase = new JButton("CLEAR");

    //public static boolean bIsSelected = false;

    public Application(){

    this.setTitle("Animation");         
    this.setSize(579, 432); 
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setLocationRelativeTo(null);
    this.setVisible(true);

        container.setBackground(Color.white);
    container.setLayout(new BorderLayout());
    container.add(canvas, BorderLayout.CENTER);
    this.setContentPane(container);

    toolBar.add(Box.createHorizontalGlue());
        toolBar.add(Box.createVerticalGlue());
        toolBar.add(bSquare, toolBar.getComponentCount() - 1);
        toolBar.add(bCircle, toolBar.getComponentCount() - 1);

        bCircle.addActionListener(new SampleActionListener(canvas, new Circle()));

            toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
        toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
        toolBar.add(bErase, toolBar.getComponentCount() - 1);
        bErase.addActionListener(new ActionListener(){
              public void actionPerformed(ActionEvent erase){
                 canvas.getShapes().clear();
                 repaint();
              }
            });
        toolBar.setOrientation(SwingConstants.VERTICAL);
        container.add(toolBar, BorderLayout.WEST);

        menu.add(newFile);
        newFile.setIcon(new ImageIcon("src/images/new.png"));
        menu.add(open);
        open.setIcon(new ImageIcon("src/images/open.png"));
        menu.add(save);
        save.setIcon(new ImageIcon("src/images/save.png"));
        this.setJMenuBar(menu);  

      }  

    public class SampleActionListener implements ActionListener {

        private final DrawingCanvas canvas2;
        private final ShapeGenerator shapeGenerator;

        public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
            this.canvas2 = canvas;
            this.shapeGenerator = shapeGenerator;
        }

        public void actionPerformed(ActionEvent event) {
           this.canvas2.setShapeGenerator(shapeGenerator);
        }
    }
    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }   

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Application App = new Application();

    }
}

Here is the class for the canvas, uploaded a second time as well :

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.util.ArrayList;

import javax.swing.JPanel;



public class DrawingCanvas extends JPanel implements MouseListener {

private ArrayList<Shape> shapes = new ArrayList<>();
private Shape shapeUnderMouse = null;

public ArrayList<Shape> getShapes() {
    return shapes;
}

public void setShapes(ArrayList<Shape> shapes) {
    this.shapes = shapes;
}

public DrawingCanvas() {
    super();
    addMouseListener(this);
}

public void paint(Graphics g){
    for(int i = 0;i < shapes.size();i++){
        shapes.get(i).paint(g);
    }    
}


@Override
public void mouseClicked(MouseEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void mouseEntered(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

@Override
public void mouseExited(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

public void addShape(Shape anyShape)
{
        shapes.add(anyShape);
}

@Override
public void mousePressed(MouseEvent e) {

    shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
    repaint();
}
@Override
public void mouseReleased(MouseEvent arg0) {
    // TODO Auto-generated method stub

}

public void setShapeGenerator(ShapeGenerator shapeGenerator) {
    // TODO Auto-generated method stub

}

Now, the class shape :

import javax.swing.JPanel;

public class Shape extends JPanel{

protected int posX;
protected int posY;

/*public Shape(int posX, int posY) {
    super();
    this.posX = posX;
    this.posY = posY;
}*/

public int getPosX() {
    return posX;
}

public void setPosX(int posX) {
    this.posX = posX;
}

public int getPosY() {
    return posY;
}

public void setPosY(int posY) {
    this.posY = posY;
}

}

My little circle class :

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Ellipse2D.Float;

import javax.swing.JPanel;

public class Circle extends Shape implements ShapeGenerator{

/*public Circle(int posX, int posY) {
    super(posX, posY);
    // TODO Auto-generated constructor stub
}*/

public void paint(Graphics g){
    g.fillOval(posX,posY,40,40);
    g.setColor(Color.blue);
  } 

public Shape getGeneratedShape(int x, int y) {
    return new Ellipse2D.Float(x, y, 10, 10); //--> does not work, ask me to change       method type to a float
    return new Circle();
    }

} And finally the interface, all the class are in separate classes :
public interface ShapeGenerator {

Shape getGeneratedShape(int posX, int posY);

}
4

3 回答 3

2

事实上,这很容易。不要使用匿名类。

例如,使用您的代码,您只需附加一个已定义的侦听器。例如 :

bCircle.addActionListener(new SampleActionListener(pan, new CircleShapeGenerator()));

这是 SampleActionListener 女巫实现 ActionListener 接口

public class SampleActionListener implements ActionListener {

    private final DrawingCanvas canvas;
    private final ShapeGenerator shapeGenerator;

    public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
        this.canvas = canvas;
        this.shapeGenerator = shapeGenerator;
    }

    public void actionPerformed(ActionEvent event) {
       this.canvas.setShapeGenerator(shapeGenerator);
    }
}

这是类 CircleShapeGenerator

public class CircleShapeGenerator implements ShapeGenerator {
    public Shape getGeneratedShape(int x, int y) {
        return new Ellipse2D.Float(x, y, 10, 10);
    }
}

和接口 ShapeGenerator

public interface ShapeGenerator {
      Shape getGeneratedShape(int x, int y);
}

而且,如果你想在矩形按钮上添加动作监听器,现在真的很容易。创建此类:

public class RectangleShapeGenerator implements ShapeGenerator {
     public Shape getGeneratedShape(int x, int y) {
       return new Rectangle2D.Float(x, y, 10, 10);
      }
}

并在您的应用程序类中,添加以下代码

toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
bRectangle.addActionListerner(pan, new RectangleShapeGenerator() )

我认为,对于您在 DrawingCanvas 中绘制的方法,您应该使用如下代码:

for (Shape s : shapes) {
       Graphics2D g2 = (Graphics2D) g;
       g2.draw(s);
}

BR,帕图什

对不起我的英语,我知道它不是很完美......

于 2012-12-09T02:06:51.687 回答
0

这是您的问题的解决方案。但它真的很脏......就像我说的那样,拥有从 JPanel 继承的 Shape 是没有意义的!

public class Application extends JFrame implements ActionListener {

    {
        // Set appearance Look & Feel for the window
        try {
            javax.swing.UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private final DrawingCanvas pan = new DrawingCanvas();
    // don't use to many field, it's confusing and not necessary.
    // you can do local var instead.
    private final JPanel container = new JPanel();

    private final JPanel commandes = new JPanel();

    private final JMenuBar menu = new JMenuBar();

    private final JMenu newFile = new JMenu();

    private final JMenu open = new JMenu();

    private final JMenu save = new JMenu();

    private JFileChooser fileChooser;

    private final JToolBar toolBar = new JToolBar();

    private final JButton bSquare = new JButton("Square");

    private final JButton bRectangle = new JButton("Rectangle");

    private final JButton bCircle = new JButton("Circle");

    private final JButton bTriangle = new JButton("Triangle");

    private final JButton bErase = new JButton("CLEAR");

    public Application() {

        this.setTitle("Animation");
        this.setSize(579, 432);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setVisible(true);

        container.setBackground(Color.white);
        container.setLayout(new BorderLayout());
        container.add(pan, BorderLayout.CENTER);
        this.setContentPane(container);

        toolBar.add(Box.createHorizontalGlue());
        toolBar.add(Box.createVerticalGlue());
        toolBar.add(bSquare, toolBar.getComponentCount() - 1);
        toolBar.add(bCircle, toolBar.getComponentCount() - 1);
        bCircle.addActionListener(new SampleActionListener(pan, new CircleShapeGenerator()));
        toolBar.add(bRectangle, toolBar.getComponentCount() - 1);
        // bRectangle.addActionListener(new SampleActionListener(pan, new
        // RectangleShapeGenerator()));
        toolBar.add(bTriangle, toolBar.getComponentCount() - 1);
        toolBar.add(bErase, toolBar.getComponentCount() - 1);
        toolBar.setOrientation(SwingConstants.VERTICAL);
        container.add(toolBar, BorderLayout.WEST);

        menu.add(newFile);
        newFile.setIcon(new ImageIcon("src/images/new.png"));
        menu.add(open);
        open.setIcon(new ImageIcon("src/images/open.png"));
        menu.add(save);
        save.setIcon(new ImageIcon("src/images/save.png"));
        this.setJMenuBar(menu);

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Application App = new Application();
    }
}

我们保留 CircleShapeGenerator 类

public class CircleShapeGenerator implements ShapeGenerator {

    @Override
    public CircleShape getGeneratedShape(int x, int y) {
        CircleShape c = new CircleShape();
        c.setCanvasX(x);
        c.setCanvasY(y);
        return c;
    }

}

圆形

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;

public class CircleShape extends Shape {

    private final Ellipse2D.Float ellipse2D;

    public CircleShape() {
        this.ellipse2D = new Ellipse2D.Float();
        this.setRadius(20);
    }


    private void setRadius(int r) {
        this.ellipse2D.height = r;
        this.ellipse2D.width = r;
    }

    @Override
    public void setCanvasX(int canvasX) {
        this.canvasX = canvasX;
        this.ellipse2D.x = canvasX;
    }

    @Override
    public void setCanvasY(int canvasY) {
        this.canvasY = canvasY;
        this.ellipse2D.y = canvasY;
    }

    @Override
    public java.awt.Shape getTrueShape() {
        return this.ellipse2D;
    }

}

用于编辑形状的上下文菜单类

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

class ContextualShapeMenu extends JPopupMenu {

    private final Shape shape;

    public ContextualShapeMenu(Shape shape) {
        this.shape = shape;
        JMenuItem anItem = new JMenuItem("Edit the size");
        add(anItem);
    }
}

DrawingCanvas 类

import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

import com.google.common.collect.Lists;

public class DrawingCanvas extends JPanel implements MouseListener {

    protected ArrayList<Shape> shapes = new ArrayList<Shape>();

    private ShapeGenerator shapeGenerator;

    public ArrayList<Shape> getShapes() {
        return shapes;
    }

    public void setShapes(ArrayList<Shape> shapes) {
        this.shapes = shapes;
    }

    public DrawingCanvas() {
        super();
        addMouseListener(this);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        for (Shape s : shapes) {
            s.paint(g);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        switch (e.getButton()) {
        case MouseEvent.BUTTON1:
            shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
            break;
        default:
            Shape shape = getShapeUnderMouse(e);
            if (shape != null) {
                ContextualShapeMenu menu = new ContextualShapeMenu(shape);
                menu.show(e.getComponent(), e.getX(), e.getY());
            }
        }
        repaint();
    }

    private Shape getShapeUnderMouse(MouseEvent e) {
        List<Shape> reversed = Lists.reverse(this.shapes);
        for (Shape s : reversed) {
            if (s.contains(e.getX(), e.getY())) {
                return s;
            }
        }
        return null;
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // Do nothing
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // Do nothing
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // Do nothing
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // Do nothing
    }

    public void setShapeGenerator(ShapeGenerator shapeGenerator) {
        this.shapeGenerator = shapeGenerator;
    }
}

仍然是 ActionListener。重命名它。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SampleActionListener implements ActionListener {

    private final DrawingCanvas canvas;

    private final ShapeGenerator shapeGenerator;

    public SampleActionListener(DrawingCanvas canvas, ShapeGenerator shapeGenerator) {
        this.canvas = canvas;
        this.shapeGenerator = shapeGenerator;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        this.canvas.setShapeGenerator(shapeGenerator);
    }
}

形状生成器接口

public interface ShapeGenerator {

    Shape getGeneratedShape(int x, int y);

}

至少,最愚蠢的课程:Shape

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

public abstract class Shape extends JPanel implements java.awt.Shape {

    protected int canvasX;

    protected int canvasY;

    public int getCanvasX() {
        return canvasX;
    }

    public abstract java.awt.Shape getTrueShape();

    public abstract void setCanvasX(int canvasX);

    public int getCanvasY() {
        return canvasY;
    }

    public abstract void setCanvasY(int canvasY);

    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.draw(this.getTrueShape());
    }

    @Override
    public Rectangle getBounds() {
        return getTrueShape().getBounds();
    }

    @Override
    public Rectangle2D getBounds2D() {
        return getTrueShape().getBounds2D();
    }

    @Override
    public boolean contains(int x, int y) {
        return this.getTrueShape().contains(x, y);
    }

    @Override
    public boolean contains(double x, double y) {
        return this.getTrueShape().contains(x, y);
    }

    @Override
    public boolean contains(Point2D p) {
        return this.getTrueShape().contains(p);
    }

    @Override
    public boolean contains(Point p) {
        return this.getTrueShape().contains(p);
    }

    @Override
    public boolean intersects(double x, double y, double w, double h) {
        return this.getTrueShape().intersects(x, y, w, h);
    }

    @Override
    public boolean intersects(Rectangle2D r) {
        return this.getTrueShape().intersects(r);
    }

    @Override
    public boolean contains(double x, double y, double w, double h) {
        return this.getTrueShape().contains(x, y, w, h);
    }

    @Override
    public boolean contains(Rectangle2D r) {
        return this.getTrueShape().contains(r);
    }

    @Override
    public PathIterator getPathIterator(AffineTransform at) {
        return this.getTrueShape().getPathIterator(at);
    }

    @Override
    public PathIterator getPathIterator(AffineTransform at, double flatness) {
        return this.getTrueShape().getPathIterator(at, flatness);
    }

}

我已经添加了番石榴库,所以,你不会找到 Lists 类。将它添加到您的项目中,使用其他库或创建一种方法来反转您的列表。

祝你好运,以后不要做这样的事情!!!这是编码的恐怖。

顺便说一句,我来自法国。

于 2012-12-10T22:50:02.877 回答
0

首先,删除你的类 Shape。你不需要。Shape是Java定义的接口。请改用此界面。

DrawingCanvas 类中 ShapeGenerator 的设置器什么也不做。所以添加它。你的方法油漆不正确。

public class DrawingCanvas extends JPanel implements MouseListener {

    // Shape here is the java.awt.Shape from java.
    private ArrayList<Shape> shapes = new ArrayList<>();
    private ShapeGenerator shapeGenerator;

    ...
    ...

    public void paint(Graphics g){
        super.paint(g);
        for (Shape s : shapes) {
            Graphics2D g2 = (Graphics2D) g;
            g2.draw(s);
        } 
    }

    ...

    @Override
    public void mousePressed(MouseEvent e) {
        shapes.add(this.shapeGenerator.getGeneratedShape(e.getX(), e.getY()));
        repaint();
    }


    public void setShapeGenerator(ShapeGenerator shapeGenerator) {
        this.shapeGenerator = shapeGenerator;
    }
}

你的类 Circle 真的很复杂。它很简单,这种方法不需要任何绘画方法。你的 Circle 类真的很简单:

public class Circle implements ShapeGenerator{

    public Shape getGeneratedShape(int x, int y) {
        // This will return a java.awt.Shape instance
        return new Ellipse2D.Float(x, y, 10, 10);
    }
}

我认为,仅此而已。

于 2012-12-09T22:43:13.027 回答