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

Java 如何使用画布根据用户输入绘制多个矩形?,java,swing,mouse-listeners,Java,Swing,Mouse Listeners,因此,基本上我正在编写一个程序,用户点击并拖动鼠标到他/她想要的大小,然后放手,根据JComboBox中的选择填充一个矩形 我实现的是MouseListener和MouseMotionListener来跟踪鼠标的位置,并根据用户第一次单击的位置绘制一个矩形,然后将鼠标放在哪里 当用户单击并拖动(但不放手)时,会出现drawRect()而不是fillRect()(如中所示,矩形不会填充-只有当用户释放鼠标时,矩形才会填充颜色) 此类创建一个Rect对象,该对象在构造函数中有另一部分,即所选的颜色

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

我实现的是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);
}
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构造函数中作为颜色放回)


所以我现在有麻烦的是能画出来。到目前为止,我在程序中没有发现任何逻辑缺陷,也没有任何东西能够绘制到画布上(不要担心JButtons撤消和擦除,因为它们很容易使用ArrayList、remove()和clear()之类的东西)。

您的程序应该没有作为类字段的图形字段(您的页面类字段)。我很惊讶您在上面的鼠标侦听器类中尝试使用NullPointException时没有看到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);
    }
}
相反,图形对象应该只从JVM获取,应该只存在于paintComponent方法中,并且应该只在同一paintComponent方法中使用(例外情况是通过paintComponent调用的任何方法,这些方法传递给该对象,当然还有从BuffereImage获取的图形对象)。MouseListener/MouseMotionListener应在mouseDragged期间填写x-start、y-start、x-end和y-end变量,然后在mouseRelease上使用这些变量创建放置在rectList中的新Rect对象,然后调用重新绘制


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

它是我前面声明的一个实例变量,在整个类的构造函数中实例化,也就是WholePanel(我马上添加它)我仍然不明白为什么他们还没有画它们……你是说mousePressed应该得到按压的点,并将x坐标设置为xStart,y坐标设置为yStart,还是MouseDraged应该得到所有的4个点(这两个和xEnd和yEnd)?我只是对逻辑和东西还有什么问题感到困惑
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);
        }
    }
}
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);
    }
}