这周JAVA作业,要求用按钮实现画图,有关事件处理,第一次接触这种用户组件,不是很了解,
开始的想法是,
在一个线程里,创建一个框架Frame,添加组件在Frame里面,把按钮组件添加到一个画板Panel里,
把画板添加到Frame里,然后对每个按钮添加监听器,然后进行画图。。。结果没用布局管理器,自然是失败了,按钮画板把整个框架覆盖了,,画的内容显示不出来。
采用布局管理器之后,添加按钮的Panel到框架的东边。代码如下:
JButton sinButton = new JButton("Sin");
JButton cosButton = new JButton("Cos");
JButton lineButton = new JButton("Y-X");
buttonPanel = new JPanel();
buttonPanel.add(sinButton);
buttonPanel.add(cosButton);
buttonPanel.add(lineButton);
sinButton.addActionListener(new DrawSinAction());
cosButton.addActionListener(new DrawCosAction());
lineButton.addActionListener(new DrawLineAction());
this.getContentPane().add(BorderLayout.EAST,buttonPanel);//布局
在然后就是画图了,用内部类,针对每强调内容个按钮设置监听器,由于不太懂,这是第一次画的方法,待会写另一个方法。。
第一个:先想在每个监听器里,为每个曲线都创建一个myComponent用来画图,然后每个都添加到Frame里面,,但是这样会有个问题,第二次画的图与第一个画的图会重叠在一起,无法实现单独显示一个正弦曲线或余弦曲线,折腾了半天,终于找到解决办法,每次画完之后,把之前的组件用remove移除掉,
然后继续画下一个图,,不过这样很麻烦,待会说另一个,代码如下:
JComponent j1 = new DrawSinComponent();//为每个都写一个继承JComponent的组件
JComponent j2 = new DrawCosComponent();
JComponent j3 = new DrawYxComponent();
private class DrawSinAction implements ActionListener{
public void actionPerformed(ActionEvent event) {
add(j1);
setVisible(true);
remove(j2);
j2 = new DrawCosComponent();
remove(j3);
j3 = new DrawYxComponent();
}}
private class DrawCosAction implements ActionListener{
public void actionPerformed(ActionEvent event) {
add(j2);
remove(j1);
j1 = new DrawSinComponent();
remove(j3);
j3 = new DrawYxComponent();
private class DrawLineAction implements ActionListener{
public void actionPerformed(ActionEvent event) {
add(j3);
setVisible(true);
remove(j1);
j1 = new DrawSinComponent();
remove(j2);
j2 = new DrawCosComponent();
}}
//比如为Sin曲线写个DrawSinComponent;
public class DrawSinComponent extends JComponent {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for(double x=0;x<=360;x+=1)//一个周期
{
double y=Math.sin(x*Math. PI/180);//转化为弧度,1度=π/180弧度
y=(150-80*y);//放大
g2.drawLine((int)x, (int)y, (int)x,(int) y);//画点
}
g2.drawLine(0,150,400,150);//画x轴
g2.drawLine(180,0,180,400);//画y轴
g2.setStroke(new BasicStroke(3.0f));
g2.drawLine(170,10,180,0);//画x箭头
g2.drawLine(180,0,190,10);
g2.drawLine(390,140,400,150);//画y箭头
g2.drawLine(400,150,390,160);
}
}
上面这种对每个要画的曲线都写一种Component组件来画图很麻烦,而且每次移除添加组件很频繁,
好像有点奇怪(我是怎么觉得)。。然后就在想怎么在一个Component里面画不同的图,因为有个
repaint的方法可以对之前的重画,就不用反复移除组件,想了一下午之后。。忽然发现可以采用点集,
把每个曲线的点集先存起来,传入就好,然后每次点集更新完就重新画图。只要为要画的曲线创建点集就好啦,,代码如下,基本都差不多,监听器里面修改了下:
DrawXComponent J1=new DrawXComponent();//先在外面建立一个Component,几个曲线共用一个画图组件
//只需要改变传入的点集就好了
private class DrawSinAction implements ActionListener{
public void actionPerformed(ActionEvent event) {
SinPoints s=new SinPoints();//创建一个所需画的曲线的点集
J1.Draw(s.getPoints());//传入
add(J1);
setVisible(true);
//将传进来的点集合转化为线集合,画出,然后如果集合发生变化,就用repaint重画,就可以更新之前画的
public class DrawXComponent extends JComponent{
private List<Line2D> lines=null;
public DrawXComponent(){
}
public void Draw(List<Point2D> points){
lines=makeLine(points);//把点转换为线
repaint();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawLine(0,150,400,150);//画x轴
g2.drawLine(180,0,180,400);//画y轴
g2.setStroke(new BasicStroke(3.0f));
g2.drawLine(170,10,180,0);//画x箭头
g2.drawLine(180,0,190,10);
g2.drawLine(390,140,400,150);//画y箭头
g2.drawLine(400,150,390,160);
for(Line2D e:lines){
g2.draw(e);
}
}
//把给定的点数组转化为线数组的方法
private List<Line2D> makeLine(List<Point2D> points) {
if (points.size()<2) {
throw new IllegalArgumentException("点的数小于2,size="+points.size());
}
List<Line2D> lines = new ArrayList<Line2D>();
for (int i = 0; i < points.size()-1; i++) {
Point2D p1 = points.get(i);
Point2D p2 = points.get(i+1);
lines.add(new Line2D.Double(p1, p2));
}
return lines;
}
}
然后就可以实现按一个按钮画一个曲线,效果图贴上来麻烦,大概就这样了。。
刚开始学,方法应该是最土的,以后有改进的方法下次回来更新。。。
本文介绍了一个使用Java绘制正弦、余弦等函数图形的实践案例。作者通过按钮触发不同图形的绘制,并逐步优化了代码结构,从最初为每种图形创建独立组件到利用单一组件配合点集更新的方式提高效率。
1681

被折叠的 条评论
为什么被折叠?



