现在接到一个做流程图的活,要求用java实现,我试着用java作了个面板,新建环节用矩形控件显示,新建条件用菱形显示,当新建环节或者分支条件时,就自动画出一条带箭头的连接线段表示流向,由于以前没做过这方面的开发,以上我只能想到这些,可是要求中还特别提到:可以拖动环节或者条件也就是矩形和菱形,而且在拖动的同时,带箭头的连接线要根据控件拖动自动伸长或缩短,而且各个连线不能重叠。
看到这我就不知道如何实现了,应该怎样处理呢,求高手指点方法?

解决方案 »

  1.   

    我觉得可以在组件上加个事件,如果坐标发生变化就重绘连接线,至于怎样不重叠我Java的图形部分没学,不清楚怎样处理。
      

  2.   

    我没学Java的绘图部分,不过以我对Java的理解,绘出的线应该也是一个对象。你试试看是不是可以先生成一个线的类,其绘出线的属性是可以根据传入的参数变化的,这样在画线的时候只是生成这个类的对象即可,这样就可以在上面添加右键等事件处理了。(只是提供思路,方法可能是错的,如果是错的也请见谅!)
      

  3.   

    这样一定要用到java的swing解决
      

  4.   

    在JDK自带的applet的例子中有连线和图元运动这方面的,现在没装JDK,没法查找,可以一个一个试,找出来后看一下源码,你就会知道怎么做了。每个图形元件都是一个对象,陵形,矩形甚至连线,当画图区接收到鼠标按下事件后,遍历所有的图形元件对象,找出是与哪个图形元件相交或者接近到一定的程度,拖动鼠标时,修改选中图形元件的属性值,然后重绘所有图形元件。因为这个以前有同学写过。重叠部分用数学的方法,求出连线交点,然后处理,如在相交处画一小段弧,这段弧的起始点和结束点用线相交处附近在两条线上某一条上的两个点即可。保存时,用序列化把所有图形元件的对象保存到文件,打开时读入就行了。还有把已经画上去的图形保存为jpg等图形。
      

  5.   

    GhostAdai 说的有道理!连线做成一个类,将线经过的路径的折点记录为一个表,通过这个来计算线的重叠处,根据得到的重叠处的坐标来重画重叠处,这样应该可以的吧?
      

  6.   

    对画图的JPanel进行鼠标事件监听,取得鼠标的坐标,然后与对象在JPanel中的位置进行比较,可得出鼠标是选中哪一个图形对象. 不要把线做成控件,千万不要,因为控件总是矩形区域,即使是透明的,你看不到他实际占有的区域,但还是会占据一个矩形区域,而画出来的线就不一样了.
      

  7.   

    用JAVA的图形没有问题能实现你说的要求的。给你一个橡皮筋的小程序。
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.util.*;
    public class elastic { /**
      * @param args
      */
     public static void main(String[] args) {
      // TODO Auto-generated method stub
          JFrame f = new DrawFrame();
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.show();
     }}
    class DrawFrame extends JFrame
    {
     public DrawFrame()
     {
      setTitle("橡皮筋程序");
      setSize(WIDTH,HEIGHT);
      Container contentPane = getContentPane();
      DrawPanel p = new DrawPanel();
      contentPane.add(p);
      contentPane.add(p.statusPanel,BorderLayout.SOUTH);
     }
     public static final int WIDTH = 600;
     public static final int HEIGHT = 600;
     
    }
    class DrawPanel extends JPanel implements MouseListener,MouseMotionListener
    {
     public DrawPanel()
     {
      lines = new ArrayList();
      colors = new ArrayList();
      setBackground(Color.WHITE);
      this.addMouseMotionListener(this);
      this.addMouseListener(this);
      statusPanel= new JPanel();
      //statusPanel.setSize(40, 200);
      //statusPanel.setBackground(Color.RED);
      statusPanel.setLayout(new BorderLayout());
      statusLabel = new JLabel(" " );
      
      statusPanel.add(statusLabel,BorderLayout.CENTER);
     }
     public void setDrawColor()
     {
      setForeground(focucolor);
     }
     public void mouseDragged(MouseEvent e)
     {
      x2 = e.getX();
            y2 = e.getY();
            statusLabel.setText("  横坐标为:"+x2+"纵坐标为:"+y2);
            repaint();
     }
     public void mouseMoved(MouseEvent e)
     {
      
     }
     /////下面五个方法是实现MouseListener的接口的方法
     public void mousePressed(MouseEvent e)
     {
      x1 = e.getX();
            y1 = e.getY();
            x2 = -1;
            repaint();
      
     }
     public void mouseReleased(MouseEvent e)
     {
       colors.add(getForeground());
             lines.add(new Line2D.Double(x1, y1, e.getX(), e.getY()));
             x2 = -1;
             statusLabel.setText("  ");
             repaint();
     }
     public void mouseEntered(MouseEvent e)
     {
      
     }
     public void mouseExited(MouseEvent e)
     {
      
     }
     public void mouseClicked(MouseEvent e)
     {
      
     }
     public void paintComponent(Graphics g)
     {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)g;
      g2.setColor(this.getForeground());
      int count = lines.size();
      for(int i = 0;i<count;i++)
      {
       Line2D.Double line = (Line2D.Double)lines.get(i);
       g2.setColor((Color)colors.get(i));
       g2.draw(line);
       
      }
      if (x2 != -1)
       g2.drawLine(x1, y1, x2, y2);
     }
     //用来清除图像
     public void clearCanvas()
     {
      lines.clear();
      colors.clear();
      x2 = -1;
      repaint();
     }
     private ArrayList lines;
     private ArrayList colors;
     private int x1,y1,x2,y2;
     private Color focucolor;
     private JLabel statusLabel;
     JPanel statusPanel;
    }
      

  8.   

    Inhibitory(),你说的通过鼠标点击在JPanel上的坐标位置与线对象的坐标位置进行对比来获得事件操作是个好方法,我试了一下,对于直线来说可以通过获得当前鼠标点击在JPanel上的坐标位置,如果这个坐标是在直线的两点坐标的区间中,就算是选中了这条线;不过对于斜线就没那么容易了,问一下线的对象里有没有这样一种方法?就是线是由点的集合组成,坐标都是整型的,能不能把组成这条线的各个点的整型坐标都遍历出来呢?
      

  9.   

    不过对于斜线就没那么容易了,问一下线的对象里有没有这样一种方法?就是线是由点的集合组成,坐标都是整型的,能不能把组成这条线的各个点的整型坐标都遍历出来呢?
    ----------------------------------------------------------------------
    你说的应该是指曲线吧,如果是曲线,做法也是一样的,曲线也是由一些小直线段逼近组成的,对每个小直线段进行判断就行了,这个主要的就是算法,没有必须把曲线中的所有点都求出来,那样比较浪费空间.或许你说的是如果是水平或垂直的线很容易实现,对有倾斜度不为0或90的线不容易,其实是一样的,因为最后都是用像素(整形值)来进行指定的,所以计算时要用一个近似值,取鼠标的X坐标来计算斜线上的Y坐标,如果与鼠标坐标的差值在指定范围内,一般是用(int)Math.floor(Y + 0.5) == 鼠标的Y坐标,那么就判断定鼠标的Y坐标在斜线上.这样,对一条斜线会处理了,对整个曲线也就会处理了.
      

  10.   

    谢谢指点!还有最后一个问题:
    我看过Eclipse里的用struts配置文件可以建流程图的功能,它新建两个环节之间的流向线的同时还在流向线段上加了文字标签,如果我用java想实现这个功能应该如何做呢?