如何使用Canvas根据用户输入绘制多个矩形?

时间:2012-02-20 01:15:31

标签: java swing mouse-listeners

所以基本上我正在编写一个程序,用户点击并将鼠标拖动到他/她想要的大小,然后放开,根据JComboBox中的选项填充矩形。

basic layout

我实现的是MouseListener和MouseMotionListener来跟踪鼠标的位置,并根据用户首次点击的位置绘制一个矩形,直到它被放走的位置。

当用户点击并拖动(但不放手)时,有一个drawRect()但不是fillRect()(因为,矩形没有填充 - 只有当用户释放鼠标时才会填充矩形用颜色)。

这个类创建一个Rect对象,它在构造函数中有另一个部分,它是所选择的颜色(在下面的ColorListener类中确定)。

这是我包含我的实例变量的地方,所有内容都在下面的构造函数中实例化:

private ArrayList<Rect> rectList;
private Color currentColor;
private Canvas canvas;
private JPanel controlPanel;
private JButton undo, erase;
private JComboBox comboBox;
private int xStart, yStart, xEnd, yEnd;
private Graphics page;
private Point pt = null;
private PointListener pointListener;
private ColorListener colorListener;

public WholePanel()
{
    // here we use black to draw a rectangle
    currentColor = Color.black;
    pointListener = new PointListener();
    addMouseListener(pointListener);
    addMouseMotionListener(pointListener);

    String[] listOfColors = {"black", "red", "blue", "green", "orange"};

    comboBox = new JComboBox(listOfColors);
    comboBox.setSelectedIndex(0);

    rectList = new ArrayList<Rect>();
    controlPanel = new JPanel(new GridLayout(1,3));

    undo = new JButton("Undo");
    erase = new JButton("Erase");
    controlPanel.add(comboBox);
    controlPanel.add(undo);
    controlPanel.add(erase);
    undo.addActionListener(new ButtonListener());
    erase.addActionListener(new ButtonListener());

    canvas = new Canvas();

    JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, canvas);

    setLayout(new BorderLayout());
    add(sp);
}

Rect类可以创建稍后使用的Rect对象。

public class Rect
{
private int x1, y1, width1, height1;
private Color color1;

public Rect(int x, int y, int width, int height, Color color)
{
    x1 = x;
    y1 = y;
    width1 = width;
    height1 = height;
    color1 = color;
}

public void draw(Graphics page)
{
    page.setColor(color1);
    page.drawRect(x1,y1,width1,height1);
}
}

Canvas类创建允许绘制对象的空间。

private class Canvas extends JPanel
{

    public void paintComponent(Graphics page)
    {
        super.paintComponent(page);
        setBackground(Color.white);
        if (pt != null)
        {
            Rect rect = new Rect(xStart, yStart, xEnd-xStart, yEnd-yStart, currentColor);
            rect.draw(page);
        }
    }
}

PointListener类查找那里的所有点,例如用户单击的位置,用户拖动的位置以及用户释放的位置。

private class PointListener implements MouseListener, MouseMotionListener
{
    public void mousePressed(MouseEvent event)
    {
        pt = event.getPoint();
        xStart = pt.x;
        yStart = pt.y;
    }
    public void mouseReleased(MouseEvent event)
    {
        pt = event.getPoint();
        if (pt != null)
        {
            xEnd = pt.x;
            yEnd = pt.y;
            page.fillRect(xStart, yStart, xEnd-xStart, yEnd-yStart);
        }
    }
    public void mouseClicked(MouseEvent event) {}
    public void mouseEntered(MouseEvent event) {}
    public void mouseExited(MouseEvent event) {}
    public void mouseDragged(MouseEvent event)
    {
        pt = event.getPoint();
        if (pt != null)
        {
            xEnd = pt.x;
            yEnd = pt.y;
            Rect rect = new Rect(xStart, yStart, xEnd-xStart, yEnd-yStart, currentColor);
            rect.draw(page);
        }
        repaint();
    }
    public void mouseMoved(MouseEvent event) {}

}

ColorListener找到在main()方法中确定的JComboBox中选择的对象类型,并将currentColor设置为它(它将作为上面Rect构造函数中的颜色放回)。

private class ColorListener implements ActionListener
{
    public void actionPerformed(ActionEvent event)
    {
        if (event.getSource().equals("black"))
        {
            currentColor = Color.black;
            comboBox.setSelectedIndex(0);
        }
        else if (event.getSource().equals("red"))
        {
            currentColor = Color.red;
            comboBox.setSelectedIndex(1);
        }
        else if (event.getSource().equals("blue"))
        {
            currentColor = Color.blue;
            comboBox.setSelectedIndex(2);
        }
        else if (event.getSource().equals("green"))
        {
            currentColor = Color.green;
            comboBox.setSelectedIndex(3);
        }
        else if (event.getSource().equals("orange"))
        {
            currentColor = Color.orange;
            comboBox.setSelectedIndex(4);
        }
    }
}

所以我遇到的麻烦就是能够画画。我在上面的程序中没有看到逻辑上的任何缺陷,也没有任何东西可以被绘制到Canvas上(不要担心JButtons Undo和Erase,因为它们很容易与ArrayList和remove()和clear()等等。

1 个答案:

答案 0 :(得分:2)

您的程序应该没有作为类字段的图形字段(您的页面类字段)。我很惊讶你没有看到NullPointException与你在鼠标监听器类中尝试使用它的方式:

public void mouseReleased(MouseEvent event)
{
    pt = event.getPoint();
    if (pt != null)
    {
        xEnd = pt.x;
        yEnd = pt.y;


        // !!!! don't do this !!!!
        page.fillRect(xStart, yStart, xEnd-xStart, yEnd-yStart);
    }
}

相反,Graphics对象只能从JVM中获取,应该只存在于paintComponent方法中,并且只能在同一个paintComponent方法中使用(例外是使用paintComponent调用的任何传递此对象的方法,当然还有从BufferedImage获取的图形对象)。 MouseListener / MouseMotionListener应在mouseDragged期间填写x-start,y-start,x-end和y-end变量,然后在mouseRelease上使用这些变量创建一个放置在rectList中的新Rect对象,然后重新打电话。

然后paintComponent应该遍历rectList,填充它在那里找到的每个Rect对象。