所以基本上我正在编写一个程序,用户点击并将鼠标拖动到他/她想要的大小,然后放开,根据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);
}
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()等等。
答案 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对象。