我是java的新手,我需要实现一个绘图应用程序,我有点陷入困境,我设法将线条绘制到我添加到JFrame的JPanel中,但是绘制的每一行都重置了整个绘图,并在绘图区域中仅保留最后一行绘制。我希望我能让自己明白,这里是他的代码:
class Shapes extends JFrame {
public JFrame mf = new JFrame("Paint");
DrawArea da = new DrawArea();
JToggleButton lineButton = new JToggleButton(new ImageIcon("line.gif"));
JToggleButton brushButton = new JToggleButton();
JToggleButton pencilButton = new JToggleButton();
JToggleButton eraserButton = new JToggleButton(new ImageIcon("eraser_icon.png"));
JToggleButton rectangleButton = new JToggleButton();
JToggleButton ovalButton = new JToggleButton();
Shapes() {
da.setBounds(120, 50, 500, 350);
da.setBackground(Color.YELLOW);
mf.setSize(700, 500);
mf.setLayout(null);
lineButton.setBounds(0, 50, 40, 40);
brushButton.setBounds(40, 50, 40, 40);
eraserButton.setBounds(0, 90, 40, 40);
pencilButton.setBounds(40, 90, 40, 40);
rectangleButton.setBounds(0, 130, 40, 40);
ovalButton.setBounds(40, 130, 40, 40);
mf.setBackground(Color.red);
mf.add(lineButton);
mf.add(brushButton);
mf.add(pencilButton);
mf.add(eraserButton);
mf.add(rectangleButton);
mf.add(ovalButton);
mf.add(da);
mf.show();
mf.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
mf.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.out.println("x:" + e.getX() + "y:" + e.getY() + "\n" + "x2:" + e.getXOnScreen() + "y2:" + e.getYOnScreen());
}
});
eraserButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
eraserButton.setSelectedIcon(new ImageIcon("eraser_icon_selected.png"));
}
});
lineButton.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
lineButton.setSelectedIcon(new ImageIcon("line_selected.png"));
}
});
da.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
da.setXvalue(e.getX());
da.setYvalue(e.getY());
}
public void mouseReleased(MouseEvent e) {
da.setX2value(e.getX());
da.setY2value(e.getY());
da.repaint();
}
});
da.addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
da.repaint();
da.setX2value(e.getX());
da.setY2value(e.getY());
}
});
}
}
public class DrawArea extends JPanel {
int x1value,y1value,x2value,y2value;
public int getX2value() {
return x2value;
}
public void setX2value(int x2value) {
this.x2value = x2value;
}
public int getY2value() {
return y2value;
}
public void setY2value(int y2value) {
this.y2value = y2value;
}
public JPanel dra=new JPanel();
public int getXvalue() {
return x1value;
}
public void setXvalue(int xvalue) {
this.x1value = xvalue;
}
public int getYvalue() {
return y1value;
}
public void setYvalue(int yvalue) {
this.y1value = yvalue;
}
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.red);
g.drawLine(getXvalue(),getYvalue(),getX2value(),getY2value());
}
}
class Paint extends JPanel
{
public static void main(String args[])
{
Shapes s=new Shapes();
}
}
答案 0 :(得分:3)
有关两种解决方案,请参阅Custom Painting Approaches。这些示例绘制了矩形,但线条的概念是相同的。
答案 1 :(得分:1)
覆盖paintComponent(),而不是paint()。阅读此tutorial。当需要重新绘制面板时,可以调用面板 repaint()方法。
答案 2 :(得分:0)
当窗口管理器认为该区域“未刷新”时,它将被调用。如果你按照现在的方式进行,你将每次绘制最后一行。
执行此操作的正确方法是在内存中创建BufferedImage
并使用它。然后,在绘制方法中,将BufferedImage
blit到表面上。这也使得滚动和缩放非常容易。
无论何时执行此类操作,都会使曲面无效,以便窗口管理器为您调用paint方法。
答案 3 :(得分:0)
您只存储一行,并且每次都会覆盖它,因此当重新绘制组件时,旧的组件将被删除,新的组件将被重新绘制。
paintComponent
之类的期望是,每次调用时,您的实现都会绘制您想要显示的每个图形元素。
您应该创建一个存储这些值的x1
类或类似内容,而不是存储y1
,x2
,y2
,LineSegment
。然后,当您进行绘制时,为您存储的每个g.drawLine()
对象调用LineSegment
(可能是ArrayList
或类似对象)。然后,当重新绘制组件时,所有线段都应显示在屏幕上。
答案 4 :(得分:0)
有点偏离主题,但我有一些不舒服的分钟因为我使用update()而不是repaint()。我建议每个与SWING一起工作的人花一些时间检查哪些方法应该作为线程安全处理,哪些方法必须在EDT(事件调度程序线程)上以确保你不会得到一些意外错误。 This is a good article about this.
此外,在开始时想一想你是否想要在你的应用程序中使用撤消/重做系统... 如果是这样,那么您希望允许撤消多少步骤。如果您想要允许此功能,那么您不能仅仅绘制并忘记上次绘制的内容。 此外,存储到目前为止绘制的所有图像也不会节省内存。我不是专家,我不是说这是最好的做法,但我会这样做:
我会制作两个名单。
绘图操作将是一个接口,某些类将为每种特定类型的绘图操作(LineDrawAction,CirceDrawAction ...)实现它。
当您绘制新行或其他任何内容时,您将清空撤消操作列表并将其添加到已应用操作列表中。当有人撤消上一个操作时,我将从应用列表中删除最后一个绘图操作,并将添加到撤消列表(等等...)。根据您是否只允许在列表达到此x限制时撤消最后一个x操作,我将从列表或队列中删除第一个绘图操作并最终绘制到图片 - 这意味着永久绘图,这不能是撤消。
即使不直接回答你的问题,我希望它清晰有用。