精华内容
下载资源
问答
  • Viso边框上写字最终要实现的效果如下:1、一开始画好如下: 具体查看如下步骤: OK了!!

    Viso画流程图在文本边、框矩形边框线上添加文字、写文字

    最终要实现的效果如下:

    效果图

    1、一开始画好如下图:
    第一张

    具体查看如下步骤:
    action

    OK了!!

    展开全文
  • 最有时间优化了一下activiti的绘制图片工具类,主要用于领导审批的时候展示的漂亮,直接上代码吧, /** 放在我们的业务代码中,穿个流程实例id进来,返回一个字符数组,然后该怎么处理你们应该知道怎么做了吧 */...

    最有时间优化了一下activiti的绘制图片工具类,主要用于在领导审批的时候展示的漂亮,直接上代码吧,

    /** 放在我们的业务代码中,穿个流程实例id进来,返回一个字符数组,然后该怎么处理你们应该知道怎么做了吧
    */
    public byte[] getImage(String processInstanceId) throws ServiceRuntimeException
    {
        try
        {
            //  获取历史流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processInstanceId).singleResult();
            if (historicProcessInstance != null)
            {
                // 获取流程定义
                ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                        .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
                List<HistoricActivityInstance> historicActivityInstanceList = historyService
                        .createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
    
                // 已执行的节点ID集合
                List<String> executedActivityIdList = new ArrayList<String>();
                int index = 1;
                for (HistoricActivityInstance activityInstance : historicActivityInstanceList)
                {
                    executedActivityIdList.add(activityInstance.getActivityId());
                    index++;
                }
                // 获取流程图图像字符流
                InputStream imageStream = ProcessDiagramGenerator.generateDiagram(processDefinition, "png", executedActivityIdList,processInstanceId);
    
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = -1;
                while((len = imageStream.read(buffer)) != -1){
                    outStream.write(buffer, 0, len);
                }
                outStream.close();
                imageStream.close();
                return outStream.toByteArray();
    
            }
            return null;
        }
        catch (Exception e)
        {
            throw new RuntimeException("获取流程图失败!" + e.getMessage());
        }
    }
    剩下的就是两个绘制流程图的工具类,直接复制就可以了
    /* Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     * 
     *      http://www.apache.org/licenses/LICENSE-2.0
     * 
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package *
    
    import com.cfne.cuckoo.oa.domain.entity.category.FlowCategoryEntity;
    import com.cfne.cuckoo.oa.service.category.FlowCategoryService;
    import com.cfne.cuckoo.oa.service.flow.history.ActHiProcinstExtService;
    import com.cfne.cuckoo.oa.service.flow.history.ActHiTaskinstService;
    import com.cfne.cuckoo.oa.service.flow.running.ActRuTaskService;
    import com.cfne.cuckoo.oa.utils.SpringUtil;
    import jdk.nashorn.internal.runtime.ECMAException;
    import org.activiti.bpmn.model.*;
    import org.activiti.bpmn.model.Process;
    import org.activiti.engine.impl.bpmn.parser.BpmnParse;
    import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
    import org.activiti.engine.impl.pvm.PvmActivity;
    import org.activiti.engine.impl.pvm.PvmTransition;
    import org.activiti.engine.impl.pvm.process.*;
    import org.activiti.engine.impl.pvm.process.Lane;
    import org.apache.log4j.Logger;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    
    import javax.annotation.*;
    import javax.annotation.Resource;
    import java.io.InputStream;
    import java.util.*;
    
    /**
     * 绘制流程工具类
     * 
     *
     */
    public class ProcessDiagramGenerator  {
        static final Logger logger = Logger.getLogger(ProcessDiagramGenerator.class);
        protected static final Map<String, ActivityDrawInstruction> activityDrawInstructions = new HashMap<String, ActivityDrawInstruction>();
    
        static {
            // start event
            activityDrawInstructions.put("startEvent", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawNoneStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // start timer event
            activityDrawInstructions.put("startTimerEvent", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawTimerStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // signal catch
            activityDrawInstructions.put("intermediateSignalCatch", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // signal throw
            activityDrawInstructions.put("intermediateSignalThrow", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawThrowingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // end event
            activityDrawInstructions.put("endEvent", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawNoneEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // error end event
            activityDrawInstructions.put("errorEndEvent", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawErrorEndEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // error start event
            activityDrawInstructions.put("errorStartEvent", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawErrorStartEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // task
            activityDrawInstructions.put("task", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // user task
            activityDrawInstructions.put("userTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawUserTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // script task
            activityDrawInstructions.put("scriptTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawScriptTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // service task
            activityDrawInstructions.put("serviceTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawServiceTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // receive task
            activityDrawInstructions.put("receiveTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawReceiveTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // send task
            activityDrawInstructions.put("sendTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawSendTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // manual task
            activityDrawInstructions.put("manualTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawManualTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // businessRuleTask task
            activityDrawInstructions.put("businessRuleTask", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawBusinessRuleTask((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // exclusive gateway
            activityDrawInstructions.put("exclusiveGateway", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawExclusiveGateway(activityImpl, activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // inclusive gateway
            activityDrawInstructions.put("inclusiveGateway", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawInclusiveGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // parallel gateway
            activityDrawInstructions.put("parallelGateway", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawParallelGateway(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
            // Boundary timer
            activityDrawInstructions.put("boundaryTimer", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // Boundary catch error
            activityDrawInstructions.put("boundaryError", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCatchingErroEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // Boundary signal event
            activityDrawInstructions.put("boundarySignal", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCatchingSignalEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // timer catch event
            activityDrawInstructions.put("intermediateTimer", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCatchingTimerEvent(activityImpl.getX(), activityImpl.getY(), activityImpl.getWidth(),
                            activityImpl.getHeight());
                }
            });
    
            // subprocess
            activityDrawInstructions.put("subProcess", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    Boolean isExpanded = (Boolean) activityImpl.getProperty(BpmnParse.PROPERTYNAME_ISEXPANDED);
                    Boolean isTriggeredByEvent = (Boolean) activityImpl.getProperty("triggeredByEvent");
                    if (isTriggeredByEvent == null) {
                        isTriggeredByEvent = Boolean.TRUE;
                    }
                    if (isExpanded != null && isExpanded == false) {
                        processDiagramCreator.drawCollapsedSubProcess((String) activityImpl.getProperty("name"), activityImpl.getX(),
                                activityImpl.getY(), activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent);
                    } else {
                        processDiagramCreator.drawExpandedSubProcess((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                                activityImpl.getWidth(), activityImpl.getHeight(), isTriggeredByEvent);
                    }
                }
            });
    
            // call activity
            activityDrawInstructions.put("callActivity", new ActivityDrawInstruction() {
                @Override
                public void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl) {
                    processDiagramCreator.drawCollapsedCallActivity((String) activityImpl.getProperty("name"), activityImpl.getX(), activityImpl.getY(),
                            activityImpl.getWidth(), activityImpl.getHeight());
                }
            });
    
        }
    
        /**
         * Generates a PNG diagram image of the given process definition, using the
         * diagram interchange information of the process.
         */
        public static InputStream generatePngDiagram(ProcessDefinitionEntity processDefinition,String processInstanceId) throws Exception {
            return generateDiagram(processDefinition, "png", Collections.<String>emptyList(),processInstanceId);
        }
    
        /**
         * Generates a JPG diagram image of the given process definition, using the
         * diagram interchange information of the process.
         */
        public static InputStream generateJpgDiagram(ProcessDefinitionEntity processDefinition,String processInstanceId) throws  Exception{
            return generateDiagram(processDefinition, "jpg", Collections.<String>emptyList(),processInstanceId);
        }
    
        protected static ProcessDiagramCanvas initProcessDiagramCanvas(ProcessDefinitionEntity processDefinition) {
            int minX = Integer.MAX_VALUE;
            int maxX = 0;
            int minY = Integer.MAX_VALUE;
            int maxY = 0;
    
            if (processDefinition.getParticipantProcess() != null) {
                ParticipantProcess pProc = processDefinition.getParticipantProcess();
    
                minX = pProc.getX();
                maxX = pProc.getX() + pProc.getWidth();
                minY = pProc.getY();
                maxY = pProc.getY() + pProc.getHeight();
            }
    
            for (ActivityImpl activity : processDefinition.getActivities()) {
    
                // width
                if (activity.getX() + activity.getWidth() > maxX) {
                    maxX = activity.getX() + activity.getWidth();
                }
                if (activity.getX() < minX) {
                    minX = activity.getX();
                }
                // height
                if (activity.getY() + activity.getHeight() > maxY) {
                    maxY = activity.getY() + activity.getHeight();
                }
                if (activity.getY() < minY) {
                    minY = activity.getY();
                }
    
                for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
                    List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
                    for (int i = 0; i < waypoints.size(); i += 2) {
                        // width
                        if (waypoints.get(i) > maxX) {
                            maxX = waypoints.get(i);
                        }
                        if (waypoints.get(i) < minX) {
                            minX = waypoints.get(i);
                        }
                        // height
                        if (waypoints.get(i + 1) > maxY) {
                            maxY = waypoints.get(i + 1);
                        }
                        if (waypoints.get(i + 1) < minY) {
                            minY = waypoints.get(i + 1);
                        }
                    }
                }
            }
    
           if (processDefinition.getLaneSets() != null && processDefinition.getLaneSets().size() > 0) {
                for (LaneSet laneSet : processDefinition.getLaneSets()) {
                    if (laneSet.getLanes() != null && laneSet.getLanes().size() > 0) {
                        for (Lane lane : laneSet.getLanes()) {
                            // width
                            if (lane.getX() + lane.getWidth() > maxX) {
                                maxX = lane.getX() + lane.getWidth();
                            }
                            if (lane.getX() < minX) {
                                minX = lane.getX();
                            }
                            // height
                            if (lane.getY() + lane.getHeight() > maxY) {
                                maxY = lane.getY() + lane.getHeight();
                            }
                            if (lane.getY() < minY) {
                                minY = lane.getY();
                            }
                        }
                    }
                }
            }
            return new ProcessDiagramCanvas(maxX + 10, maxY + 10, minX, minY);
        }
    
    
        protected interface ActivityDrawInstruction {
            void draw(ProcessDiagramCanvas processDiagramCreator, ActivityImpl activityImpl);
        }
    
        /**
         * [生成流程图,返回输入流]
         *
         * @param processDefinition
         * @param imageType
         * @param highLightedActivities
         * @return
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        public static InputStream generateDiagram(ProcessDefinitionEntity processDefinition, String imageType, List<String> highLightedActivities,String processInstanceId) throws Exception {
            // 通过流程图画布绘制出对应图像类型的流程图图片
            return generateDiagram(processDefinition, highLightedActivities,processInstanceId).generateImage(imageType);
        }
    
        /**
         * [生成流程图,返回流程图画布]
         *
         * @param processDefinition
         * @param highLightedActivities
         * @return
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        protected static ProcessDiagramCanvas generateDiagram(ProcessDefinitionEntity processDefinition, List<String> highLightedActivities,String processInstanceId) throws Exception {
            ProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(processDefinition);
    
            // Draw pool shape, if process is participant in collaboration
            if (processDefinition.getParticipantProcess() != null) {
                ParticipantProcess pProc = processDefinition.getParticipantProcess();
                processDiagramCanvas.drawPoolOrLane(pProc.getName(), pProc.getX(), pProc.getY(), pProc.getWidth(), pProc.getHeight());
            }
            // Draw lanes
            if (processDefinition.getLaneSets() != null && processDefinition.getLaneSets().size() > 0) {
                for (LaneSet laneSet : processDefinition.getLaneSets()) {
                    if (laneSet.getLanes() != null && laneSet.getLanes().size() > 0) {
                        for (Lane lane : laneSet.getLanes()) {
                            processDiagramCanvas.drawPoolOrLane(lane.getName(), lane.getX(), lane.getY(), lane.getWidth(), lane.getHeight());
                        }
                    }
                }
            }
    
            // Draw activities and their sequence-flows
            // 循环当前流程定义中的所有节点,绘制节点和节点上的流程线,如果节点已经执行过这高亮显示
           /* for (ActivityImpl activity : processDefinition.getActivities()) {
                drawActivity(processDiagramCanvas, activity, highLightedActivities);
            }*/
            String id2=drawActivitys(processDiagramCanvas, processDefinition, highLightedActivities,processInstanceId);
    
            // 绘制当前所有已执行的节点的所有流出流程线,如果流程线已被执行过,则高亮显示
            for (int index = 1; index <= highLightedActivities.size(); index++) {
                for (ActivityImpl activity : processDefinition.getActivities()) {
                    if (highLightedActivities.get(index - 1).equals(activity.getId())) {
                        drawActivityFlowHighLight(processDiagramCanvas, activity, highLightedActivities, index,id2);
                      /*  // 最后一个节点红色显示
                        if (index == highLightedActivities.size()) {
                            drawCurrentActivityRed(processDiagramCanvas, activity);
                        }*/
                    }
                }
            }
    
            return processDiagramCanvas;
        }
    
    
        /**
         * [绘制流程图中高亮显示的流程线]
         *
         * @param processDiagramCanvas
         * @param activity
         * @param highLightedActivities
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        protected static void drawActivityFlowHighLight(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity, List<String> highLightedActivities, int index,String id2) throws  Exception{
            //logger.info("第【" + index + "】个节点=" + activity.getId());
            // Outgoing transitions of activity
            // 绘制当前节点的所有流出流程线,如果流程线已被执行过,则高亮显示
            int flowIndex = 1;
            boolean isHighLightedFlow;
            boolean flag;
            boolean timeFlag;
            String id = null;
            List<Integer> waypoints = null;
            ActivityImpl lastActivityImpl = null;
            String type = (String) activity.getProperty("type");
    //遍历当前节点的所有走向
            for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
                //logger.info("节点的第[" + flowIndex + "]条流出流程线=" + sequenceFlow.getId());
                //变蓝标识
                isHighLightedFlow = false;
                //变红标识
                flag = false;
                timeFlag = false;
                // 当前流程线对应的后续节点
                lastActivityImpl = (ActivityImpl) sequenceFlow.getDestination();
                //logger.info("流程线[" + sequenceFlow.getId() + "]对应的后续节点ID=[" + lastActivityImpl.getId() + "]");
                // 当前节点的后续节点在需高亮显示的节点List中,并且当前节点已经执行过就是也在高亮显示的节点List中,
                if (highLightedActivities.contains(lastActivityImpl.getId()) && highLightedActivities.contains(activity.getId())) {
                    // 获取在已执行节点List中当前节点的下一个节点ID
                    // 【注意:以下处理对于并发的处理可能不完善,遇到时再进行具体处理】
    // 如果下一个节点是当前流程线指向的节点,则流程线高亮显示
                    if (index >= highLightedActivities.size()) {
                        // 没有下一个节点,当前的流程线不高亮显示
                        // logger.info("流程线[" + sequenceFlow.getId() + "]不需要高亮显示");
                    } else if (lastActivityImpl.getId().equals(highLightedActivities.get(index))) {
                        isHighLightedFlow = true;
                        //判断是否包含倒数第三个节点(当前节点为起草人)
                        if(id2!=null){
                            //如果该节点是当前节点赋值变红标识
                            if(id2.equals(activity.getId())){
                                flag=true;
                            }
                        }
                        //判断节点类型是否为现在的节点类型是否为包含网关或排他网关
                        if (type.equals("exclusiveGateway") || type.equals("inclusiveGateway")) {
                            //h获取流程走向中的条件
                            Object conditionText = sequenceFlow.getProperty("conditionText");
                            //如果条件不为空
                            if(conditionText!=null) {
                                //如果条件包含不同意
                                if (conditionText.toString().contains("不同意")) {
                                    flag = true;
                                }
                            }
                        }
    
                        //  logger.info("流程线【" + sequenceFlow.getId() + "】需要高亮显示");
                    } else {
                        if (type.equals("parallelGateway")) {
                            isHighLightedFlow = true;
                        }
                        if (highLightedActivities.contains(activity.getId()) && type.equals("userTask")) {
                            isHighLightedFlow = true;
                        }
                      /* */
    
                    }
                } else {
                    if (type.equals("userTask") && !activity.getActivities().isEmpty()) {
                        //绘制定时任务的线条
                        if (activity.getActivities().get(0).getProperty("type").equals("boundaryTimer")) {
                            if (highLightedActivities.contains(activity.getActivities().get(0).getOutgoingTransitions().get(0).getDestination().getId())) {
                                isHighLightedFlow = true;
                                timeFlag = true;
                                waypoints = ((TransitionImpl) activity.getActivities().get(0).getOutgoingTransitions().get(0)).getWaypoints();
                            }
                        }
                    }
                    // logger.info("---流程线[" + sequenceFlow.getId() + "]不需要高亮显示");
                }
                /*如果是定时任务获取定时任务的坐标*/
                if (!timeFlag) {
                    waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
                }
                for (int i = 2; i < waypoints.size(); i += 2) { // waypoints.size() // minimally 4: x1, y1, // x2, y2
                    boolean drawConditionalIndicator = (i == 2) && sequenceFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION) != null
                            && !((String) activity.getProperty("type")).toLowerCase().contains("gateway");
                    if (i < waypoints.size() - 2) {
                        // 绘制一条流程线中不带箭头的直线部分
                        if (isHighLightedFlow) {
    
                            if (flag) {
                                processDiagramCanvas.drawHighLightSequenceflowWithoutArrow2(waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i),
                                        waypoints.get(i + 1), drawConditionalIndicator);
                            } else {
                                processDiagramCanvas.drawHighLightSequenceflowWithoutArrow(waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i),
                                        waypoints.get(i + 1), drawConditionalIndicator);
                            }
                        }
                    } else {
                        // 绘制一条流程线中带箭头的直线部分
                        if (isHighLightedFlow) {
                            String name = null;
                            if (sequenceFlow.getProperty("name") != null) {
                                name = sequenceFlow.getProperty("name").toString();
                            }
                            if (flag) {
                                /*绘制红色*/
                                processDiagramCanvas.drawHighLightSequenceflow2(waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i), waypoints.get(i + 1),
                                        drawConditionalIndicator);
                            } else {
                                /*绘制蓝色*/
                                processDiagramCanvas.drawHighLightSequenceflow(waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i), waypoints.get(i + 1),
                                        drawConditionalIndicator);
                            }
                        }
                    }
                }
                flowIndex++;
            }
    
            // Nested activities (boundary events)
            // 循环绘制当前节点下的子节点
            for (ActivityImpl nestedActivity : activity.getActivities()) {
                drawActivity(processDiagramCanvas, nestedActivity, highLightedActivities);
            }
        }
    
        /**
         * [绘制流程图中的节点和节点上的流程线]
         *
         * @param processDiagramCanvas
         * @param activity
         * @param highLightedActivities
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        protected static void drawActivity(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity, List<String> highLightedActivities) throws Exception{
            // 获取节点类型
            String type = (String) activity.getProperty("type");
            ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(type);
            if (drawInstruction != null) {
    
                drawInstruction.draw(processDiagramCanvas, activity);
    
                // Gather info on the multi instance marker
                boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = false;
                String multiInstance = (String) activity.getProperty("multiInstance");
                if (multiInstance != null) {
                    if ("sequential".equals(multiInstance)) {
                        multiInstanceSequential = true;
                    } else {
                        multiInstanceParallel = true;
                    }
                }
    
                // Gather info on the collapsed marker
                Boolean expanded = (Boolean) activity.getProperty(BpmnParse.PROPERTYNAME_ISEXPANDED);
                if (expanded != null) {
                    collapsed = !expanded;
                }
    
                // Actually draw the markers
                processDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(),
                        multiInstanceSequential, multiInstanceParallel, collapsed);
    
                // Draw highlighted activities
                // 如果高亮节点List中包含当前节点,则当前节点绘制为高亮样式
    //            logger.info("当前节点=【" + activity.getId() + "】");
    //            logger.info("节点类型:[" + type + "]");
    
                if (highLightedActivities.contains(activity.getId())) {
                    //最后一个节点高亮显示(橙色)
                    String id = "";
                    if (highLightedActivities.get(highLightedActivities.size() - 1).equals(activity.getId())) {
                        //修改背景颜色
                        if (type.equals("userTask")) {
                            processDiagramCanvas.drawUserTask3((String) activity.getProperty("name"), activity.getX(), activity.getY(),
                                    activity.getWidth(), activity.getHeight());
                            if (activity.getIncomingTransitions() != null) {
                                List<PvmTransition> incomingTransitions = activity.getIncomingTransitions();
                                for (PvmTransition p : incomingTransitions) {
                                    if (p.getProperty("conditionText") != null) {
                                        if (p.getProperty("conditionText").toString().contains("不同意")) {
                                            if (highLightedActivities.get(highLightedActivities.size() - 2).equals(p.getSource().getId())) {
                                                ActivityImpl source = (ActivityImpl) p.getSource();
                                                String types = (String) source.getProperty("type");
                                                id = source.getId();
                                                processDiagramCanvas.drawExclusive(source.getX(), source.getY(), source.getWidth(), source.getHeight());
                                              /*  processDiagramCanvas.drawUserTask3((String) source.getProperty("name"), source.getX(), source.getY(),
                                                        activity.getWidth(), activity.getHeight());*/
                                            }
    
                                        }
                                    }
                                }
                            }
                        }
                        drawCurrentActivityRed(processDiagramCanvas, activity);
                    } else {
                        if (type.equals("userTask")) {
                            if (!id.equals(activity.getId())) {
                                processDiagramCanvas.drawUserTask2((String) activity.getProperty("name"), activity.getX(), activity.getY(),
                                        activity.getWidth(), activity.getHeight());
                            }
                        }
                        //已执行过的(高亮显示蓝色)
                        drawHighLight(processDiagramCanvas, activity);
                    }
                } /*else {
    
                    //未执行过的显示深蓝色(不包括定时边界任务)
                    if (!type.equals("exclusiveGateway") && !type.equals("boundaryTimer")) {
                        drawCurrentActivityRed2(processDiagramCanvas, activity);
                    }
    
                }*/
    
            }
    
            // Outgoing transitions of activity
    
            for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
    
                List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
                for (int i = 2; i < waypoints.size(); i += 2) { // waypoints.size() // minimally 4: x1, y1, // x2, y2
                    boolean drawConditionalIndicator = (i == 2) && sequenceFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION) != null
                            && !((String) activity.getProperty("type")).toLowerCase().contains("gateway");
                    String name = null;
                    if (sequenceFlow.getProperty("name") != null) {
                        name = sequenceFlow.getProperty("name").toString();
                    }
                    if (i < waypoints.size() - 2) {
                        // 绘制一条流程线中不带箭头的直线部分
                        processDiagramCanvas.drawSequenceflowWithoutArrow(name, waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i),
                                waypoints.get(i + 1), drawConditionalIndicator);
                    } else {
                        processDiagramCanvas.drawSequenceflow(name, waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i), waypoints.get(i + 1),
                                drawConditionalIndicator);
                    }
                }
            }
    
            // Nested activities (boundary events)
            // 循环绘制当前节点下的子节点
            for (ActivityImpl nestedActivity : activity.getActivities()) {
                drawActivity(processDiagramCanvas, nestedActivity, highLightedActivities);
            }
        }
    
        protected static String drawActivitys(ProcessDiagramCanvas processDiagramCanvas, ProcessDefinitionEntity processDefinition, List<String> highLightedActivities,String processInstanceId) throws Exception {
            // 获取节点类型
            String id = "";
            //倒数第三以执行节点
            String id2 = "";
            for (ActivityImpl activity : processDefinition.getActivities()) {
                String type = (String) activity.getProperty("type");
                ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(type);
                if (drawInstruction != null) {
                    if (!id.equals(activity.getId()) &&!id2.equals(activity.getId())) {
                        drawInstruction.draw(processDiagramCanvas, activity);
                    }
                    // Gather info on the multi instance marker
                    boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = false;
                    String multiInstance = (String) activity.getProperty("multiInstance");
                    if (multiInstance != null) {
                        if ("sequential".equals(multiInstance)) {
                            multiInstanceSequential = true;
                        } else {
                            multiInstanceParallel = true;
                        }
                    }
    
                    // Gather info on the collapsed marker
                    Boolean expanded = (Boolean) activity.getProperty(BpmnParse.PROPERTYNAME_ISEXPANDED);
                    if (expanded != null) {
                        collapsed = !expanded;
                    }
    
                    // Actually draw the markers
                    processDiagramCanvas.drawActivityMarkers(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight(),
                            multiInstanceSequential, multiInstanceParallel, collapsed);
    
    
                    if (highLightedActivities.contains(activity.getId())) {
                        //最后一个节点高亮显示(橙色)
                        if (highLightedActivities.get(highLightedActivities.size() - 1).equals(activity.getId())) {//是否是最后一个节点
                            //修改背景颜色
                            //判断是否用户节点
                            if (type.equals("userTask")) {
                                //传入参数  processInstanceId 流程实例id和taskDefKey 已完成流程id
                                processDiagramCanvas.putParamMap("processInstanceId",processInstanceId);
                                processDiagramCanvas.putParamMap("taskDefKey",activity.getId());
                                //修改单前节点背景为橙色
                                processDiagramCanvas.drawUserTask3((String) activity.getProperty("name"), activity.getX(), activity.getY(),
                                        activity.getWidth(), activity.getHeight());
                                //判断单前节点的上一个节点是否为空
                                if (activity.getIncomingTransitions() != null) {
                                    //获取当前节点的所有上一个节点
                                    List<PvmTransition> incomingTransitions = activity.getIncomingTransitions();
                                    for (PvmTransition p : incomingTransitions) {
                                        if (p.getProperty("conditionText") != null) {
                                            //判断是否是不同意来源
                                            if (p.getProperty("conditionText").toString().contains("不同意")) {
                                                //判断以执行节点中倒数第二个是否包含当前节点的上一个节点
                                                if (highLightedActivities.get(highLightedActivities.size() - 2).equals(p.getSource().getId())) {
                                                    //类型转换
                                                    ActivityImpl source = (ActivityImpl) p.getSource();
                                                    String types = (String) source.getProperty("type");
                                                    id = source.getId();
                                                    //判断是否是排他网关
                                                    if(types.equals("exclusiveGateway")||types.equals("parallelGateway")||types.equals("inclusiveGateway")){
                                                        //绘制当前节点的上一个节点为红色
                                                        drawHighLight3(processDiagramCanvas, source);
                                                    }
                                                    //通过当前节点的上个一节点找到上个节点上所有来源
                                                    List<PvmTransition> incomingTransitions1 = source.getIncomingTransitions();
                                                    for (PvmTransition pt : incomingTransitions1) {
                                                        ActivityImpl source1 = (ActivityImpl) pt.getSource();
                                                        //找到倒数第三个节点
                                                        if (highLightedActivities.get(highLightedActivities.size() - 3).equals(source1.getId())) {
    
                                                            id2=drawUserTaskAndUser(processDiagramCanvas,source1,processInstanceId);
    
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            //修改单前节点边框为橙色
                            drawCurrentActivityRed(processDiagramCanvas, activity);
                        } else {//如果不是最后一个节点
                            if (type.equals("userTask")) { //type 是否为 userTask
                                if (!id.equals(activity.getId()) && !id2.equals(activity.getId())) {
                                    //传入参数  processInstanceId 流程实例id和taskDefKey 已完成流程id
                                    processDiagramCanvas.putParamMap("processInstanceId",processInstanceId);
                                    processDiagramCanvas.putParamMap("taskDefKey",activity.getId());
                                    processDiagramCanvas.drawUserTask2((String) activity.getProperty("name"), activity.getX(), activity.getY(),
                                            activity.getWidth(), activity.getHeight());
                                }
                            }
                            //已执行过的(高亮显示蓝色)
                            if (!id.equals(activity.getId()) && !id2.equals(activity.getId())) {
                                if(type.equals("exclusiveGateway")||type.equals("parallelGateway")||type.equals("inclusiveGateway")){
                                    drawHighLight2(processDiagramCanvas, activity);
                                }else{
                                drawHighLight(processDiagramCanvas, activity);}
                            }
    
                        }
                    }
                }
    
                for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
    
                    List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
                    for (int i = 2; i < waypoints.size(); i += 2) { // waypoints.size() // minimally 4: x1, y1, // x2, y2
                        boolean drawConditionalIndicator = (i == 2) && sequenceFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION) != null
                                && !((String) activity.getProperty("type")).toLowerCase().contains("gateway");
                        String name = null;
                        if (sequenceFlow.getProperty("name") != null) {
                            name = sequenceFlow.getProperty("name").toString();
                        }
                        if (i < waypoints.size() - 2) {
                            // 绘制一条流程线中不带箭头的直线部分
                            if (i >= 4) {
                                name = null;
                            }
                            //绘制线条增加显示名称
                            processDiagramCanvas.drawSequenceflowWithoutArrow(name, waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i),
                                    waypoints.get(i + 1), drawConditionalIndicator);
                        } else {
                            if (waypoints.size() > 4) {
                                name = null;
                            }
                            //绘制线条增加显示名称
                            processDiagramCanvas.drawSequenceflow(name, waypoints.get(i - 2), waypoints.get(i - 1), waypoints.get(i), waypoints.get(i + 1),
                                    drawConditionalIndicator);
                        }
                    }
                }
    
                // Nested activities (boundary events)
                // 循环绘制当前节点下的子节点
                for (ActivityImpl nestedActivity : activity.getActivities()) {
                    drawActivity(processDiagramCanvas, nestedActivity, highLightedActivities);
                }
            }
            return id2;
        }
    
        private static void drawHighLight(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity) {
            processDiagramCanvas.drawHighLight(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
        }
    
        private static String drawUserTaskAndUser(ProcessDiagramCanvas processDiagramCanvas,ActivityImpl source1,String processInstanceId) throws Exception{
            String types1 = (String) source1.getProperty("type");
            String  id2 = source1.getId();
            if(types1.equals("userTask")) {
                //传入参数  processInstanceId 流程实例id和taskDefKey 当前流程id
                processDiagramCanvas.putParamMap("processInstanceId",processInstanceId);
                processDiagramCanvas.putParamMap("taskDefKey",source1.getId());
                //修改背景颜色
                processDiagramCanvas.drawUserTask4((String) source1.getProperty("name"), source1.getX(), source1.getY(),
                        source1.getWidth(), source1.getHeight());
                //修改边框颜色
                processDiagramCanvas.drawExclusive(source1.getX(), source1.getY(), source1.getWidth(), source1.getHeight());
            }else if(types1.equals("exclusiveGateway")||types1.equals("parallelGateway")||types1.equals("inclusiveGateway")){
                drawHighLight3(processDiagramCanvas, source1);
            }
            return id2;
        }
        /**
         * [绘制高亮显示的节点]
         *
         * @param processDiagramCanvas
         * @param activity
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        private static void drawHighLight2(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity) {
            processDiagramCanvas.drawHighLight2(activity,activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
        }
        private static void drawHighLight3(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity) {
            processDiagramCanvas.drawHighLight3(activity,activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
        }
        /**
         * [绘制当前节点红色显示]
         *
         * @param processDiagramCanvas
         * @param activity
         * @Author: [Double]
         * @CreateDate: [2015-10-22]
         * @Version: [v2.0.0]
         */
        private static void drawCurrentActivityRed(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity) {
            processDiagramCanvas.drawHighLightRed(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
        }
    
        private static void drawCurrentActivityRed2(ProcessDiagramCanvas processDiagramCanvas, ActivityImpl activity) {
            processDiagramCanvas.drawHighLightRed2(activity.getX(), activity.getY(), activity.getWidth(), activity.getHeight());
        }
    
        public static ProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel) {
            // We need to calculate maximum values to know how big the image will be in its entirety
            double minX = Double.MAX_VALUE;
            double maxX = 0;
            double minY = Double.MAX_VALUE;
            double maxY = 0;
    
            for (Pool pool : bpmnModel.getPools()) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
                minX = graphicInfo.getX();
                maxX = graphicInfo.getX() + graphicInfo.getWidth();
                minY = graphicInfo.getY();
                maxY = graphicInfo.getY() + graphicInfo.getHeight();
            }
    
            List<FlowNode> flowNodes = gatherAllFlowNodes(bpmnModel);
    
            for (FlowNode flowNode : flowNodes) {
                GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                // width
                if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {
                    maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();
                }
                if (flowNodeGraphicInfo.getX() < minX) {
                    minX = flowNodeGraphicInfo.getX();
                }
                // height
                if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {
                    maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();
                }
                if (flowNodeGraphicInfo.getY() < minY) {
                    minY = flowNodeGraphicInfo.getY();
                }
    
                for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
                    List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
                    for (GraphicInfo graphicInfo : graphicInfoList) {
                        // width
                        if (graphicInfo.getX() > maxX) {
                            maxX = graphicInfo.getX();
                        }
                        if (graphicInfo.getX() < minX) {
                            minX = graphicInfo.getX();
                        }
                        // height
                        if (graphicInfo.getY() > maxY) {
                            maxY = graphicInfo.getY();
                        }
                        if (graphicInfo.getY() < minY) {
                            minY = graphicInfo.getY();
                        }
                    }
                }
            }
    
            int nrOfLanes = 0;
            for (Process process : bpmnModel.getProcesses()) {
                for (org.activiti.bpmn.model.Lane l : process.getLanes()) {
    
                    nrOfLanes++;
    
                    GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
                    // // width
                    if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {
                        maxX = graphicInfo.getX() + graphicInfo.getWidth();
                    }
                    if (graphicInfo.getX() < minX) {
                        minX = graphicInfo.getX();
                    }
                    // height
                    if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {
                        maxY = graphicInfo.getY() + graphicInfo.getHeight();
                    }
                    if (graphicInfo.getY() < minY) {
                        minY = graphicInfo.getY();
                    }
                }
            }
    
            // Special case, see http://jira.codehaus.org/browse/ACT-1431
            if (flowNodes.size() == 0 && bpmnModel.getPools().size() == 0 && nrOfLanes == 0) {
                // Nothing to show
                minX = 0;
                minY = 0;
            }
    
            return new ProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY);
        }
    
        protected static List<FlowNode> gatherAllFlowNodes(FlowElementsContainer flowElementsContainer) {
            List<FlowNode> flowNodes = new ArrayList<FlowNode>();
    
            for (FlowElement flowElement : flowElementsContainer.getFlowElements()) {
                if (flowElement instanceof FlowNode) {
                    flowNodes.add((FlowNode) flowElement);
                }
    
                if (flowElement instanceof FlowElementsContainer) {
                    flowNodes
                            .addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement));
                }
            }
    
            return flowNodes;
        }
    
        protected static List<FlowNode> gatherAllFlowNodes(BpmnModel bpmnModel) {
            List<FlowNode> flowNodes = new ArrayList<FlowNode>();
    
            for (Process process : bpmnModel.getProcesses()) {
                flowNodes.addAll(gatherAllFlowNodes(process));
            }
    
            return flowNodes;
        }
    
    
    }
    

    --------------------------------------------------------------------------------------------------------------------------------------------

    import com.cfne.cuckoo.oa.domain.entity.category.FlowCategoryEntity;
    import com.cfne.cuckoo.oa.service.category.FlowCategoryService;
    import com.cfne.cuckoo.oa.service.flow.history.ActHiTaskinstService;
    import org.activiti.engine.ActivitiException;
    import org.activiti.engine.impl.pvm.process.ActivityImpl;
    import org.activiti.engine.impl.util.IoUtil;
    import org.activiti.engine.impl.util.ReflectUtil;
    import org.apache.commons.collections.map.HashedMap;
    import org.apache.poi.ss.formula.functions.T;
    import sun.rmi.runtime.Log;
    
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Line2D;
    import java.awt.geom.RoundRectangle2D;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.*;
    import java.util.logging.Logger;
    
    /**
     */
    public class ProcessDiagramCanvas extends  BaseProcessDiagramCanvas{
    
        protected static final Logger LOGGER = Logger.getLogger(ProcessDiagramCanvas.class.getName());
    
        // Predefined sized
        protected static final int ARROW_WIDTH = 5;
    
        protected static final int CONDITIONAL_INDICATOR_WIDTH = 16;
    
        protected static final int MARKER_WIDTH = 12;
    
        // Colors
        protected static Color TASK_COLOR = new Color(255, 255, 255);//节点背景颜色19, 185, 156
    /*
        protected static Color BOUNDARY_EVENT_COLOR = new Color(13, 179, 166);
    
       protected static Color CONDITIONAL_INDICATOR_COLOR = new Color(13, 179, 166);
    
       protected static Color HIGHLIGHT_COLOR = new Color(13, 179, 166); //Color.CYAN;*/
    
    
        protected static Color BOUNDARY_EVENT_COLOR = new Color(19, 185, 156);//边界事件背景颜色颜色
    
        protected static Color CONDITIONAL_INDICATOR_COLOR = new Color(19, 185, 156);//已执行线条颜色
    
        protected static Color HIGHLIGHT_COLOR = new Color(19, 185, 156); //Color.CYAN;已执行节点颜色
        protected static Color HIGHLIGHT_RED = new Color(255, 0, 0); //Color.CYAN;已执行b被打回颜色
        /*protected static Color HIGHLIGHT_COLOR_RED = new Color(166, 131, 65);  // Color.YELLOW;*/
        protected static Color HIGHLIGHT_COLOR_RED = new Color(230, 130, 70);  // 流程走到该节点的边框颜色;
        protected static Color HIGHLIGHT_COLOR_RED2 = new Color(0, 0, 0);  // 流程未走过的颜色
        // Strokes
        protected static Stroke THICK_TASK_BORDER_STROKE = new BasicStroke(3.0f);
    
        protected static Stroke GATEWAY_TYPE_STROKE = new BasicStroke(3.0f);
    
        protected static Stroke END_EVENT_STROKE = new BasicStroke(3.0f);
    
        protected static Stroke MULTI_INSTANCE_STROKE = new BasicStroke(1.3f);
    
        protected static Stroke EVENT_SUBPROCESS_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, new float[]{1.0f},
                0.0f);
    
        // icons
        protected static int ICON_SIZE = 16;
    
        protected static Image USERTASK_IMAGE;
    
        protected static Image SCRIPTTASK_IMAGE;
    
        protected static Image SERVICETASK_IMAGE;
    
        protected static Image RECEIVETASK_IMAGE;
    
        protected static Image SENDTASK_IMAGE;
    
        protected static Image MANUALTASK_IMAGE;
    
        protected static Image BUSINESS_RULE_TASK_IMAGE;
    
        protected static Image TIMER_IMAGE;
    
        protected static Image ERROR_THROW_IMAGE;
    
        protected static Image ERROR_CATCH_IMAGE;
    
        protected static Image SIGNAL_CATCH_IMAGE;
    
        protected static Image SIGNAL_THROW_IMAGE;
    
        // icons are statically loaded for performace
        static {
            try {
               /* ImageIO.read(this.getClass().getClassLoader().getResourceAsStream("stencilset.json"));*/
                USERTASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/user.png"));
                SCRIPTTASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/script.png"));
                SERVICETASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/service.png"));
                RECEIVETASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/receive.png"));
                SENDTASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/send.png"));
                MANUALTASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/manual.png"));
                BUSINESS_RULE_TASK_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/business_rule.png"));
                TIMER_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/timer.png"));
                ERROR_THROW_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/error_throw.png"));
                ERROR_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/error_catch.png"));
                SIGNAL_CATCH_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/signal_catch.png"));
                SIGNAL_THROW_IMAGE = ImageIO.read(ReflectUtil.getResourceAsStream("org/activiti/engine/impl/bpmn/deployer/signal_throw.png"));
            } catch (IOException e) {
                LOGGER.warning("Could not load image for process diagram creation: " + e.getMessage());
            }
        }
    
        protected int canvasWidth = -1;
    
        protected int canvasHeight = -1;
    
        protected int minX = -1;
    
        protected int minY = -1;
    
        protected BufferedImage processDiagram;
    
        protected Graphics2D g;
    
        protected FontMetrics fontMetrics;
    
        protected boolean closed;
    
        /**
         * Creates an empty canvas with given width and height.
         */
        public ProcessDiagramCanvas(int width, int height) {
            this.canvasWidth = width;
            this.canvasHeight = height;
            this.processDiagram = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            this.g = processDiagram.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setPaint(Color.BLACK);
    
            Font font = new Font("宋体", Font.BOLD, 11);
            g.setFont(font);
            this.fontMetrics = g.getFontMetrics();
        }
    
        /**
         * Creates an empty canvas with given width and height.
         * <p>
         * Allows to specify minimal boundaries on the left and upper side of the
         * canvas. This is useful for diagrams that have white space there (eg
         * Signavio). Everything beneath these minimum values will be cropped.
         *
         * @param minX Hint that will be used when generating the image. Parts that fall
         *             below minX on the horizontal scale will be cropped.
         * @param minY Hint that will be used when generating the image. Parts that fall
         *             below minX on the horizontal scale will be cropped.
         */
        public ProcessDiagramCanvas(int width, int height, int minX, int minY) {
            this(width, height);
            this.minX = minX;
            this.minY = minY;
        }
    
        /**
         * Generates an image of what currently is drawn on the canvas.
         * <p>
         * Throws an {@link ActivitiException} when {@link #close()} is already
         * called.
         */
        public InputStream generateImage(String imageType) {
            if (closed) {
                throw new ActivitiException("ProcessDiagramGenerator already closed");
            }
    
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                // Try to remove white space
                minX = (minX <= 5) ? 5 : minX;
                minY = (minY <= 5) ? 5 : minY;
                BufferedImage imageToSerialize = processDiagram;
                if (minX >= 0 && minY >= 0) {
                    imageToSerialize = processDiagram.getSubimage(minX - 5, minY - 5, canvasWidth - minX + 5, canvasHeight - minY + 5);
                }
                ImageIO.write(imageToSerialize, imageType, out);
            } catch (IOException e) {
                throw new ActivitiException("Error while generating process image", e);
            } finally {
                IoUtil.closeSilently(out);
            }
            return new ByteArrayInputStream(out.toByteArray());
        }
    
        /**
         * Closes the canvas which dissallows further drawing and releases graphical
         * resources.
         */
        public void close() {
            g.dispose();
            closed = true;
        }
    
        public void drawNoneStartEvent(int x, int y, int width, int height) {
            drawStartEvent(x, y, width, height, null);
        }
    
        public void drawTimerStartEvent(int x, int y, int width, int height) {
            drawStartEvent(x, y, width, height, TIMER_IMAGE);
        }
    
        public void drawStartEvent(int x, int y, int width, int height, Image image) {
            g.draw(new Ellipse2D.Double(x, y, width, height));
            if (image != null) {
                g.drawImage(image, x, y, width, height, null);
            }
    
        }
    
        public void drawNoneEndEvent(int x, int y, int width, int height) {
            Stroke originalStroke = g.getStroke();
            g.setStroke(END_EVENT_STROKE);
            g.draw(new Ellipse2D.Double(x, y, width, height));
            g.setStroke(originalStroke);
        }
    
        public void drawErrorEndEvent(int x, int y, int width, int height) {
            drawNoneEndEvent(x, y, width, height);
            g.drawImage(ERROR_THROW_IMAGE, x + 3, y + 3, width - 6, height - 6, null);
        }
    
        public void drawErrorStartEvent(int x, int y, int width, int height) {
            drawNoneStartEvent(x, y, width, height);
            g.drawImage(ERROR_CATCH_IMAGE, x + 3, y + 3, width - 6, height - 6, null);
        }
    
        public void drawCatchingEvent(int x, int y, int width, int height, Image image) {
            // event circles
            Ellipse2D outerCircle = new Ellipse2D.Double(x, y, width, height);
            int innerCircleX = x + 3;
            int innerCircleY = y + 3;
            int innerCircleWidth = width - 6;
            int innerCircleHeight = height - 6;
            Ellipse2D innerCircle = new Ellipse2D.Double(innerCircleX, innerCircleY, innerCircleWidth, innerCircleHeight);
    
            Paint originalPaint = g.getPaint();
            g.setPaint(BOUNDARY_EVENT_COLOR);
            g.fill(outerCircle);
    
            g.setPaint(originalPaint);
            g.draw(outerCircle);
            g.draw(innerCircle);
    
            g.drawImage(image, innerCircleX, innerCircleY, innerCircleWidth, innerCircleHeight, null);
        }
    
        public void drawCatchingTimerEvent(int x, int y, int width, int height) {
            drawCatchingEvent(x, y, width, height, TIMER_IMAGE);
        }
    
        public void drawCatchingErroEvent(int x, int y, int width, int height) {
            drawCatchingEvent(x, y, width, height, ERROR_CATCH_IMAGE);
        }
    
        public void drawCatchingSignalEvent(int x, int y, int width, int height) {
            drawCatchingEvent(x, y, width, height, SIGNAL_CATCH_IMAGE);
        }
    
        public void drawThrowingSignalEvent(int x, int y, int width, int height) {
            drawCatchingEvent(x, y, width, height, SIGNAL_THROW_IMAGE);
        }
    
        public void drawSequenceflowWithoutArrow(String name, int srcX, int srcY, int targetX, int targetY, boolean conditional) {
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
            if (name != null) {
                g.setColor(Color.BLACK);
                if (srcY == targetY) {
                    if (srcX >= targetX) {
                        srcX = srcX - 40;
                        srcY=srcY-5;
                    } else {
                        srcX = srcX + 7;
                        srcY=srcY-5;
                    }
                } else if (srcX == targetX) {
                    if (srcY <= targetY) {
                        srcY = srcY + 15;
                        srcX = srcX - 10;
                    } else {
                        srcY = srcY - 20;
                        srcX = srcX - 10;
                    }
                    //斜左上
                }else if(targetX<srcX&&targetY<srcY){
                    srcY = srcY - 15;
                    srcX = srcX - 15;
                    //斜左下
                }else if(targetX<srcX&&targetY>srcY){
                    srcY = srcY + 15;
                    srcX = srcX - 15;
                    //斜右上
                }else if(targetX>srcX&&targetY<srcY){
                    srcY = srcY - 15;
                    srcX = srcX + 15;
                    //斜右下
                }else if(targetX>srcX&&targetY>srcY){
                    srcY = srcY + 15;
                    srcX = srcX + 15;
                }
    
                g.drawString(name, srcX, srcY);
    
            }
        }
    
        // 绘制高亮显示的不带箭头的流程线
        public void drawHighLightSequenceflowWithoutArrow(int srcX, int srcY, int targetX, int targetY, boolean conditional) {
    
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_COLOR);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
    
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        // 绘制高亮显示的不带箭头的流程线
        public void drawHighLightSequenceflowWithoutArrow2(int srcX, int srcY, int targetX, int targetY, boolean conditional) {
    
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_RED);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
    
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
    
    
        }
    
        public void drawArrowHead(Line2D.Double line) {
            int doubleArrowWidth = 2 * ARROW_WIDTH;
            Polygon arrowHead = new Polygon();
            arrowHead.addPoint(0, 0);
            arrowHead.addPoint(-ARROW_WIDTH, -doubleArrowWidth);
            arrowHead.addPoint(ARROW_WIDTH, -doubleArrowWidth);
    
            AffineTransform transformation = new AffineTransform();
            transformation.setToIdentity();
            double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
            transformation.translate(line.x2, line.y2);
            transformation.rotate((angle - Math.PI / 2d));
    
            AffineTransform originalTransformation = g.getTransform();
            g.setTransform(transformation);
            g.fill(arrowHead);
            g.setTransform(originalTransformation);
        }
    
        public void drawConditionalSequenceFlowIndicator(Line2D.Double line) {
            int horizontal = (int) (CONDITIONAL_INDICATOR_WIDTH * 0.7);
            int halfOfHorizontal = horizontal / 2;
            int halfOfVertical = CONDITIONAL_INDICATOR_WIDTH / 2;
    
            Polygon conditionalIndicator = new Polygon();
            conditionalIndicator.addPoint(0, 0);
            conditionalIndicator.addPoint(-halfOfHorizontal, halfOfVertical);
            conditionalIndicator.addPoint(0, CONDITIONAL_INDICATOR_WIDTH);
            conditionalIndicator.addPoint(halfOfHorizontal, halfOfVertical);
    
            AffineTransform transformation = new AffineTransform();
            transformation.setToIdentity();
            double angle = Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
            transformation.translate(line.x1, line.y1);
            transformation.rotate((angle - Math.PI / 2d));
    
            AffineTransform originalTransformation = g.getTransform();
            g.setTransform(transformation);
            g.draw(conditionalIndicator);
    
            Paint originalPaint = g.getPaint();
            g.setPaint(CONDITIONAL_INDICATOR_COLOR);
            g.fill(conditionalIndicator);
    
            g.setPaint(originalPaint);
            g.setTransform(originalTransformation);
        }
    
        public void drawTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height, false);
        }
    
        public void drawTask2(String name, int x, int y, int width, int height, int flag) throws Exception{
            drawTask2(name, x, y, width, height, false, flag);
        }
    
    
        public void drawPoolOrLane(String name, int x, int y, int width, int height) {
            g.drawRect(x, y, width, height);
    
            // Add the name as text, vertical
            if (name != null && name.length() > 0) {
                // Include some padding
                int availableTextSpace = height - 6;
    
                // Create rotation for derived font
                AffineTransform transformation = new AffineTransform();
                transformation.setToIdentity();
                transformation.rotate(270 * Math.PI / 180);
    
                Font currentFont = g.getFont();
                Font theDerivedFont = currentFont.deriveFont(transformation);
                g.setFont(theDerivedFont);
    
                String truncated = fitTextToWidth(name, availableTextSpace);
                int realWidth = fontMetrics.stringWidth(truncated);
    
                g.drawString(truncated, x + 2 + fontMetrics.getHeight(), 3 + y + availableTextSpace - (availableTextSpace - realWidth) / 2);
                g.setFont(currentFont);
            }
        }
    
        protected void drawTask(String name, int x, int y, int width, int height, boolean thickBorder) {
            Paint originalPaint = g.getPaint();
            g.setPaint(TASK_COLOR);
    
            // shape
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.fill(rect);
            g.setPaint(originalPaint);
    
            if (thickBorder) {
                Stroke originalStroke = g.getStroke();
                g.setStroke(THICK_TASK_BORDER_STROKE);
                g.draw(rect);
                g.setStroke(originalStroke);
            } else {
                g.draw(rect);
            }
    
            // text
            if (name != null) {
                String text = fitTextToWidth(name, width);
    
                int textX = x + ((width - fontMetrics.stringWidth(text)) / 2);
                int textY = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight();
    
                if (text.length() > 7 && text.length() <= 14) {
                    String text2 = fitTextToWidth(name.substring(0, 7), width);
                    int textX2 = x + ((width - fontMetrics.stringWidth(text2)) / 2);
                    int textY2 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() - 9;
    
                    String text3 = fitTextToWidth(name.substring(7, name.length()), width);
                    int textX3 = x + ((width - fontMetrics.stringWidth(text3)) / 2);
                    int textY3 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() + 15;
                    g.setColor(Color.BLACK);
                    g.drawString(text2, textX2, textY2);
                    g.drawString(text3, textX3, textY3);
    
                } else if (text.length() > 14) {
                    String text2 = fitTextToWidth(name.substring(0, 7), width);
                    int textX2 = x + ((width - fontMetrics.stringWidth(text2)) / 2);
                    int textY2 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() - 12;
    
                    String text3 = fitTextToWidth(name.substring(7, 14), width);
                    int textX3 = x + ((width - fontMetrics.stringWidth(text3)) / 2);
                    int textY3 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() + 4;
                    String text4;
                    if (name.length() > 16) {
                        text4 = fitTextToWidth(name.substring(14, 16) + "...", width);
                    } else {
                        text4 = fitTextToWidth(name.substring(14, name.length()), width);
                    }
                    int textX4 = x + ((width - fontMetrics.stringWidth(text4)) / 2);
                    int textY4 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() + 17;
                    g.setColor(Color.BLACK);
                    g.drawString(text2, textX2, textY2);
                    g.drawString(text3, textX3, textY3);
                    g.drawString(text4, textX4, textY4);
                } else {
                    g.setColor(Color.BLACK);
                    g.drawString(text, textX, textY);
                }
            }
            // g.setColor(TASK_COLOR);
    
        }
    
    
    
        protected void drawTask2(String name, int x, int y, int width, int height, boolean thickBorder, int flag) throws Exception{
            Paint originalPaint = g.getPaint();
            if (flag == 2) {
                g.setPaint(HIGHLIGHT_COLOR);
            } else if (flag == 3) {
                g.setPaint(HIGHLIGHT_COLOR_RED);
            } else if (flag == 4) {
                g.setPaint(HIGHLIGHT_RED);
            }
            // shape
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.fill(rect);//绿色填充 背景框
            g.setPaint(originalPaint);
    
            if (thickBorder) {
                Stroke originalStroke = g.getStroke();
                g.setStroke(THICK_TASK_BORDER_STROKE);
                g.draw(rect);
                g.setStroke(originalStroke);
            } else {
                g.draw(rect);
            }
            /**
             * 获取流程的审批人
             *  如果传入参数为  已完成流程 则取的是已完成流程的 审批人
             *  如果传入参数为  当前流程,则取的是当前流程的审批人
             *  因为 此方法有 已完成流程 和 当前流程 两种情况调用
             */
            String reviewName = getTaskReviewName();
    
            // 绘制流程图 流程名称
            if (name != null) {
                String text = fitTextToWidth(name, width);
                int textX = x + ((width - fontMetrics.stringWidth(text)) / 2);
                int textY = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight();
                if (text.length() > 7 && text.length() <= 14) {
                    String text2 = fitTextToWidth(name.substring(0, 7), width);
                    int textX2 = x + ((width - fontMetrics.stringWidth(text2)) / 2);
                    int textY2 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() - 13;
    
                    String text3 = fitTextToWidth(name.substring(7, name.length()), width);
                    int textX3 = x + ((width - fontMetrics.stringWidth(text3)) / 2);
                    int textY3 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight()-1 ;
                    g.setColor(Color.BLACK);
                    g.drawString(text2, textX2, textY2);
                    g.drawString(text3, textX3, textY3);
    
                    //绘制 增加审批人
                    int textYName = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() +12;
                    if(reviewName.length()>9){//当审核人姓名长度大于9 (一行显示不下)
                        g.drawString(reviewName.substring(0,9), x, textYName);//第一行 不空格,靠左顶格显示
                        g.drawString(reviewName.substring(9,reviewName.length()), x, textYName+12);//第二行
                    }else{
                        int textXName = x ;
                        if(fontMetrics.stringWidth(reviewName)<width){
                            textXName = x + ((width - fontMetrics.stringWidth(reviewName)) / 2);
                        }
                        g.drawString(reviewName, textXName, textYName);
                    }
    
                } else if (text.length() > 14) {
                    String text2 = fitTextToWidth(name.substring(0, 7), width);
                    int textX2 = x + ((width - fontMetrics.stringWidth(text2)) / 2);
                    int textY2 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() - 14;
    
                    String text3 = fitTextToWidth(name.substring(7, 14), width);
                    int textX3 = x + ((width - fontMetrics.stringWidth(text3)) / 2);
                    int textY3 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() ;
                    String text4;
                    if (name.length() > 16) {
                        text4 = fitTextToWidth(name.substring(14, 16) + "...", width);
                    } else {
                        text4 = fitTextToWidth(name.substring(14, name.length()), width);
                    }
                    int textX4 = x + ((width - fontMetrics.stringWidth(text4)) / 2);
                    int textY4 = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() + 14;
                    g.setColor(Color.BLACK);
                    g.drawString(text2, textX2, textY2);
    
                    g.drawString(text3, textX3, textY3);
                    g.drawString(text4, textX4, textY4);
    
                    int textYName = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() +26;
                    if(reviewName.length()>9){//当审核人姓名长度大于9 (一行显示不下)
                        g.drawString(reviewName.substring(0,9), x, textYName);//第一行 不空格,靠左顶格显示
                        g.drawString(reviewName.substring(9,reviewName.length()), x, textYName+12);//第二行
                    }else{
                        int textXName = x ;
                        if(fontMetrics.stringWidth(reviewName)<width){
                            textXName = x + ((width - fontMetrics.stringWidth(reviewName)) / 2);
                        }
                        g.drawString(reviewName, textXName, textYName);
                    }
                } else {
                    g.setColor(Color.BLACK);
                    g.drawString(text, textX, textY);
    
                    //绘制 增加审批人
                    int textYName = y + ((height - fontMetrics.getHeight()) / 2) + fontMetrics.getHeight() +15;
                    if(reviewName.length()>9){//当审核人姓名长度大于9 (一行显示不下)
                        g.drawString(reviewName.substring(0,9), x, textYName);//第一行 不空格,靠左顶格显示
                        g.drawString(reviewName.substring(9,reviewName.length()), x, textYName+12);//第二行
                    }else{
                        int textXName = x ;
                        if(fontMetrics.stringWidth(reviewName)<width){
                            textXName = x + ((width - fontMetrics.stringWidth(reviewName)) / 2);
                        }
                        g.drawString(reviewName, textXName, textYName);
                    }
                }
            }
        }
    
        protected String fitTextToWidth(String original, int width) {
            // remove length for "..."
            /*int maxWidth = width - 10;
    
          while (fontMetrics.stringWidth(text + "...") > maxWidth && text.length() > 0) {
             text = text.substring(0, text.length() - 1);
          }
    
          if (!text.equals(original)) {
             text = text + "...";
          }*/
            return original;
        }
    
        public void drawUserTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(USERTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawUserTask2(String name, int x, int y, int width, int height) throws Exception{
            drawTask2(name, x, y, width, height, 2);
            //绘制 背景图的小头像
            g.drawImage(USERTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawUserTask3(String name, int x, int y, int width, int height) throws Exception{
            drawTask2(name, x, y, width, height, 3);
            g.drawImage(USERTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawUserTask4(String name, int x, int y, int width, int height) throws Exception{
            drawTask2(name, x, y, width, height, 4);
            g.drawImage(USERTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawScriptTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(SCRIPTTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawServiceTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(SERVICETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawReceiveTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(RECEIVETASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawSendTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(SENDTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawManualTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(MANUALTASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawBusinessRuleTask(String name, int x, int y, int width, int height) {
            drawTask(name, x, y, width, height);
            g.drawImage(BUSINESS_RULE_TASK_IMAGE, x + 7, y + 7, ICON_SIZE, ICON_SIZE, null);
        }
    
        public void drawExpandedSubProcess(String name, int x, int y, int width, int height, Boolean isTriggeredByEvent) {
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
    
            // Use different stroke (dashed)
            if (isTriggeredByEvent) {
                Stroke originalStroke = g.getStroke();
                g.setStroke(EVENT_SUBPROCESS_STROKE);
                g.draw(rect);
                g.setStroke(originalStroke);
            } else {
                g.draw(rect);
            }
    
            String text = fitTextToWidth(name, width);
            g.drawString(text, x + 10, y + 15);
        }
    
        public void drawCollapsedSubProcess(String name, int x, int y, int width, int height, Boolean isTriggeredByEvent) {
            drawCollapsedTask(name, x, y, width, height, false);
        }
    
        public void drawCollapsedCallActivity(String name, int x, int y, int width, int height) {
            drawCollapsedTask(name, x, y, width, height, true);
        }
    
        protected void drawCollapsedTask(String name, int x, int y, int width, int height, boolean thickBorder) {
            // The collapsed marker is now visualized separately
            drawTask(name, x, y, width, height, thickBorder);
        }
    
        public void drawCollapsedMarker(int x, int y, int width, int height) {
            // rectangle
            int rectangleWidth = MARKER_WIDTH;
            int rectangleHeight = MARKER_WIDTH;
            Rectangle rect = new Rectangle(x + (width - rectangleWidth) / 2, y + height - rectangleHeight - 3, rectangleWidth, rectangleHeight);
            g.draw(rect);
    
            // plus inside rectangle
            Line2D.Double line = new Line2D.Double(rect.getCenterX(), rect.getY() + 2, rect.getCenterX(), rect.getMaxY() - 2);
            g.draw(line);
            line = new Line2D.Double(rect.getMinX() + 2, rect.getCenterY(), rect.getMaxX() - 2, rect.getCenterY());
            g.draw(line);
        }
    
        public void drawActivityMarkers(int x, int y, int width, int height, boolean multiInstanceSequential, boolean multiInstanceParallel,
                                        boolean collapsed) {
            if (collapsed) {
                if (!multiInstanceSequential && !multiInstanceParallel) {
                    drawCollapsedMarker(x, y, width, height);
                } else {
                    drawCollapsedMarker(x - MARKER_WIDTH / 2 - 2, y, width, height);
                    if (multiInstanceSequential) {
                        drawMultiInstanceMarker(true, x + MARKER_WIDTH / 2 + 2, y, width, height);
                    } else if (multiInstanceParallel) {
                        drawMultiInstanceMarker(false, x + MARKER_WIDTH / 2 + 2, y, width, height);
                    }
                }
            } else {
                if (multiInstanceSequential) {
                    drawMultiInstanceMarker(true, x, y, width, height);
                } else if (multiInstanceParallel) {
                    drawMultiInstanceMarker(false, x, y, width, height);
                }
            }
        }
    
        /**
         *  绘制多边形
         */
        public void drawGateway(int x, int y, int width, int height) {
            Polygon rhombus = new Polygon();
            rhombus.addPoint(x, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y + height);
            rhombus.addPoint(x + width, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y);
            g.draw(rhombus);
        }
    
        //修改网关颜色为蓝色
        public void drawGateway2(int x, int y, int width, int height) {
            Polygon rhombus = new Polygon();
            g.setPaint(HIGHLIGHT_COLOR);
            rhombus.addPoint(x, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y + height);
            rhombus.addPoint(x + width, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y);
            g.draw(rhombus);
        }
    
        //修改网关颜色为红色
        public void drawGateway3(int x, int y, int width, int height) {
            Polygon rhombus = new Polygon();
            g.setPaint(HIGHLIGHT_RED);
            rhombus.addPoint(x, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y + height);
            rhombus.addPoint(x + width, y + (height / 2));
            rhombus.addPoint(x + (width / 2), y);
            g.draw(rhombus);
        }
    
        public void drawParallelGateway(int x, int y, int width, int height) {
            // rhombus
            drawGateway(x, y, width, height);
    
            // plus inside rhombus
            Stroke orginalStroke = g.getStroke();
            g.setStroke(GATEWAY_TYPE_STROKE);
            Line2D.Double line = new Line2D.Double(x + 10, y + height / 2, x + width - 10, y + height / 2); // horizontal
            g.draw(line);
            line = new Line2D.Double(x + width / 2, y + height - 10, x + width / 2, y + 10); // vertical
            g.draw(line);
            g.setStroke(orginalStroke);
        }
    
        public void drawExclusiveGateway(ActivityImpl activityImpl, int x, int y, int width, int height) {
            // rhombus
            //绘制多边形
            drawGateway(x, y, width, height);
    
            int quarterWidth = width / 4;
            int quarterHeight = height / 4;
    
            // X inside rhombus
            //线宽
            Stroke orginalStroke = g.getStroke();
            g.setStroke(GATEWAY_TYPE_STROKE);
            Line2D.Double line = new Line2D.Double(x + quarterWidth + 3, y + quarterHeight + 3, x + 3 * quarterWidth - 3, y + 3 * quarterHeight - 3);
            g.draw(line);
            line = new Line2D.Double(x + quarterWidth + 3, y + 3 * quarterHeight - 3, x + 3 * quarterWidth - 3, y + quarterHeight + 3);
            g.draw(line);
    
            g.setStroke(orginalStroke);
            if (activityImpl.getProperty("name") != null) {
                g.setColor(Color.BLACK);
                if (activityImpl.getProperty("name").toString().length() > 7) {
                    x = x - 20;
                }
                g.drawString(activityImpl.getProperty("name").toString(), x - 10, y - 5);
            }
        }
    
        public void drawExclusive(int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_RED);
            g.setStroke(THICK_TASK_BORDER_STROKE);
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);
    
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
    
    
        }
    
        public void drawInclusiveGateway(int x, int y, int width, int height) {
            // rhombus
            drawGateway(x, y, width, height);
    
            int diameter = width / 2;
    
            // circle inside rhombus
            Stroke orginalStroke = g.getStroke();
            g.setStroke(GATEWAY_TYPE_STROKE);
            Ellipse2D.Double circle = new Ellipse2D.Double(((width - diameter) / 2) + x, ((height - diameter) / 2) + y, diameter, diameter);
            g.draw(circle);
            g.setStroke(orginalStroke);
        }
    
        public void drawMultiInstanceMarker(boolean sequential, int x, int y, int width, int height) {
            int rectangleWidth = MARKER_WIDTH;
            int rectangleHeight = MARKER_WIDTH;
            int lineX = x + (width - rectangleWidth) / 2;
            int lineY = y + height - rectangleHeight - 3;
    
            Stroke orginalStroke = g.getStroke();
            g.setStroke(MULTI_INSTANCE_STROKE);
    
            if (sequential) {
                g.draw(new Line2D.Double(lineX, lineY, lineX + rectangleWidth, lineY));
                g.draw(new Line2D.Double(lineX, lineY + rectangleHeight / 2, lineX + rectangleWidth, lineY + rectangleHeight / 2));
                g.draw(new Line2D.Double(lineX, lineY + rectangleHeight, lineX + rectangleWidth, lineY + rectangleHeight));
            } else {
                g.draw(new Line2D.Double(lineX, lineY, lineX, lineY + rectangleHeight));
                g.draw(new Line2D.Double(lineX + rectangleWidth / 2, lineY, lineX + rectangleWidth / 2, lineY + rectangleHeight));
                g.draw(new Line2D.Double(lineX + rectangleWidth, lineY, lineX + rectangleWidth, lineY + rectangleHeight));
            }
    
            g.setStroke(orginalStroke);
        }
    
        //修改以走过流程节点为蓝色
        public void drawHighLight(int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
            g.setPaint(HIGHLIGHT_COLOR);//椭圆矩形 背景色
            g.setStroke(THICK_TASK_BORDER_STROKE);//线宽
            //绘制背景椭圆矩形
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);
            //设置背景色
            g.setPaint(originalPaint);
            //设置线宽
            g.setStroke(originalStroke);
        }
    
        //修改以走过流程网关为蓝色
        public void drawHighLight2(ActivityImpl activity, int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
            drawGateway2(x, y, width, height);
            g.setPaint(HIGHLIGHT_COLOR);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
       /*     RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);*/
            int quarterWidth = width / 4;
            int quarterHeight = height / 4;
            if (activity.getProperty("type").equals("parallelGateway")) {
                Line2D.Double line = new Line2D.Double(x + 10, y + height / 2, x + width - 10, y + height / 2); // horizontal
                g.draw(line);
                line = new Line2D.Double(x + width / 2, y + height - 10, x + width / 2, y + 10); // vertical
                g.draw(line);
            } else if (activity.getProperty("type").equals("inclusiveGateway")) {
                int diameter = width / 2;
                Ellipse2D.Double circle = new Ellipse2D.Double(((width - diameter) / 2) + x, ((height - diameter) / 2) + y, diameter, diameter);
                g.draw(circle);
            } else {
                Line2D.Double line = new Line2D.Double(x + quarterWidth + 3, y + quarterHeight + 3, x + 3 * quarterWidth - 3, y + 3 * quarterHeight - 3);
                g.draw(line);
                line = new Line2D.Double(x + quarterWidth + 3, y + 3 * quarterHeight - 3, x + 3 * quarterWidth - 3, y + quarterHeight + 3);
                g.draw(line);
            }
            if (activity.getProperty("name") != null) {
                g.setColor(Color.BLACK);
                if (activity.getProperty("name").toString().length() > 7) {
                    x = x - 20;
                }
                g.drawString(activity.getProperty("name").toString(), x - 10, y - 5);
            }
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        //修改不同意打回节点为红色
        public void drawHighLight3(ActivityImpl activity, int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
            drawGateway3(x, y, width, height);
            g.setPaint(HIGHLIGHT_RED);
            g.setStroke(THICK_TASK_BORDER_STROKE);
       /*     RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);*/
            int quarterWidth = width / 4;
            int quarterHeight = height / 4;
            if (activity.getProperty("type").equals("parallelGateway")) {
                Line2D.Double line = new Line2D.Double(x + 10, y + height / 2, x + width - 10, y + height / 2); // horizontal
                g.draw(line);
                line = new Line2D.Double(x + width / 2, y + height - 10, x + width / 2, y + 10); // vertical
                g.draw(line);
            } else if (activity.getProperty("type").equals("inclusiveGateway")) {
                int diameter = width / 2;
                Ellipse2D.Double circle = new Ellipse2D.Double(((width - diameter) / 2) + x, ((height - diameter) / 2) + y, diameter, diameter);
                g.draw(circle);
            } else {
                Line2D.Double line = new Line2D.Double(x + quarterWidth + 3, y + quarterHeight + 3, x + 3 * quarterWidth - 3, y + 3 * quarterHeight - 3);
                g.draw(line);
                line = new Line2D.Double(x + quarterWidth + 3, y + 3 * quarterHeight - 3, x + 3 * quarterWidth - 3, y + quarterHeight + 3);
                g.draw(line);
            }
            if (activity.getProperty("name") != null) {
                g.setColor(Color.BLACK);
                if (activity.getProperty("name").toString().length() > 7) {
                    x = x - 20;
                }
                g.drawString(activity.getProperty("name").toString(), x - 10, y - 5);
            }
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        public void drawHighLightRed(int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_COLOR_RED);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);
    
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        public void drawHighLightRed2(int x, int y, int width, int height) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_COLOR_RED2);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
            g.draw(rect);
    
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        public void drawHighLightSequenceflow(int srcX, int srcY, int targetX, int targetY, boolean conditional) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_COLOR);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
            drawArrowHead(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
        }
    
        public void drawHighLightSequenceflow2(int srcX, int srcY, int targetX, int targetY, boolean conditional) {
            Paint originalPaint = g.getPaint();
            Stroke originalStroke = g.getStroke();
    
            g.setPaint(HIGHLIGHT_RED);
            g.setStroke(THICK_TASK_BORDER_STROKE);
    
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
            drawArrowHead(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
            g.setPaint(originalPaint);
            g.setStroke(originalStroke);
    
        }
    
        public void drawSequenceflow(String name, int srcX, int srcY, int targetX, int targetY, boolean conditional) {
            Line2D.Double line = new Line2D.Double(srcX, srcY, targetX, targetY);
            g.draw(line);
            drawArrowHead(line);
    
            if (conditional) {
                drawConditionalSequenceFlowIndicator(line);
            }
            if (name != null) {
                if (srcY == targetY) {
                    if (srcX >= targetX) {
                        srcX = srcX - 40;
                        srcY=srcY-5;
                    } else {
                        srcX = srcX + 7;
                        srcY=srcY-5;
                    }
                } else if (srcX == targetX) {
                    if (srcY <= targetY) {
                        srcY = srcY + 15;
                        srcX = srcX - 10;
                    } else {
                        srcY = srcY - 20;
                        srcX = srcX - 10;
                    }
                    //斜左上
                }else if(targetX<srcX&&targetY<srcY){
                    srcY = srcY - 15;
                    srcX = srcX - 15;
                    //斜左下
                }else if(targetX<srcX&&targetY>srcY){
                    srcY = srcY + 15;
                    srcX = srcX - 15;
                    //斜右上
                }else if(targetX>srcX&&targetY<srcY){
                    srcY = srcY - 15;
                    srcX = srcX + 15;
                    //斜右下
                }else if(targetX>srcX&&targetY>srcY){
                    srcY = srcY + 15;
                    srcX = srcX + 15;
                }
    
                g.setColor(Color.BLACK);
                g.drawString(name, srcX, srcY);
    
            }
        }
    }
    
    展开全文
  • 流程图就是通过图表和文字绘制出一个流动过程的图。流程图广泛应用于各个行业,尤其是IT业、建筑业和数字统计行业。学习中,也常会利用流程图帮助记忆,比如树状图、模型图等。 一、流程图的类型 1、基本流程图 ...

    什么是流程图?流程图就是通过图表和文字绘制出一个流动过程的图。流程图广泛应用于各个行业,尤其是IT业、建筑业和数字统计行业。在学习中,也常会利用流程图帮助记忆,比如树状图、模型图等。

    一、流程图的类型

    1、基本流程图

    用于定义工作或是记录工作数据、财务流动、生产方向等的流程图,以便于提高工作效率。

    2、业务流程图

    用于把各单位、人员之间的关系、作业和信息流向整理成一条工作链的图表,是一种业务工作模型图。


    3、数据流程图

    用于描述系统数据流程的图,可以将数据分离出来,以图文的方式去描述工作的流程。


    4、系统流程图

    是一种系统模型图,以图形符号描述系统中的每个部件,并以简单的文字进行表述部件之间的关系和流动走向的情况。

    一般是系统分析员、管理员和业务操作员相互沟通和交流的方式。


    二、流程图怎么画

    以前可以利用微软工具绘制出一些简单的流程图,但是真要制作比较专业的流程图还是使用流程图制作软件更为适合,如今市面上的流程图制作软件也很多,但真正好用的也就那几个。今天小编就推荐这款小编使用后觉得还挺顺手的流程图制作软件——迅捷流程图制作软件,这款软件操作还是挺简单的,功能也是挺完善的,是一款实用的绘制工具。

    接下来就来看这款软件要怎么绘制图形了。

    (1)将软件打开后,可以选择创建图表和打开已有的图表。点击创建图表后,软件会出现一个选择模型的对话框,选择其中一个图表即可。

    (2)图表创建成功后,就可以开始绘图了。在软件左右两侧都有一个面板,左侧的是图形模板面板,右侧是格式面板。


    (3)在左侧模型面板中可以选择一个图形模型,点击后图形就会被添加到图中。选中图形,单击节点拉伸可以调整图形的长和宽。


    (4)在其他功能中,有一个连接时复制的选项。勾选后,将鼠标移至图形,点击图形四周的几个半蓝色的箭头移动到空白位置上,就会出现连接箭头,在箭头另一端还会出现相同的图形。


    (5)而在右侧格式面板中,可以看到有三种功能:样式、文本和排列。选中图形后,在样式中可以勾选填充功能,为图形填充颜色,还可以改变图形线型和线型颜色;选中并双击图形则可以在图形中添加文字,并且可以在文本功能中修改文字的格式、大小和颜色;排列则可以调整图形的排列顺序、大小、位置和角度等。


    根据这些基本操作,就可以绘制出一张流程图了,还可以利用软件的导入功能,将找到的图形素材导入图中,绘制出更加精美的流程图。

    以上就是关于流程图的基本信息,希望能帮到需要的人。

    展开全文
  • 我们工作生活中经常能看到各式各样的流程图流程图主要由线条、几何图框以及文字构成,根据应用场景分为:业务流程图、数据流程图、页面流程图等。职场小白也许会认为流程图是个很复杂的东西,其实啊,它一点也不...

    我们在工作生活中经常能看到各式各样的流程图。流程图主要由线条、几何图框以及文字构成,根据应用场景分为:业务流程图、数据流程图、页面流程图等。职场小白也许会认为流程图是个很复杂的东西,其实啊,它一点也不复杂,听我向你简单讲讲,不用五分钟就能吃透一张流程图的画法了。

    上面提到流程图主要由线条、图形、文字三大部分组成,接下来我们就先谈谈流程图中的图形:

    如图所示,流程图中的每个图形都有其对应的含义,不是你认为的哪个好看用哪个,是有一套规则在里面的。否则你画出来的流程图就只能给你自己看,别人都看不懂,你说是吧?所以,画流程图的第一步就是选择合适的图形,自然就需要你了解清楚每个图形的含义了,其实也就十几个图形,常用的差不多十个,很容易记住。

    然后,我们来了解一下流程图的基本结构,这是构成流程图的框架。

    基本结构也就三种,很容易记。了解了常用图形和基本结构后,下面我们就可以开始画一张流程图了。

    1、进入软件官网,为了省事我们直接点击“在线版”在线画流程图即可。

    2、然后创建流程图模板,这里我选择的是空白图表。

    3、接下来创建图形,别忘了前面提到的图形含义哦。


    4、然后就是添加图形文本了,直接双击图形即可。


    5、接着创建图形连接线,直接拉动图形的蓝色三角形即可。


    6、如果你想自定义图形的样式,可以选中图形在右侧面板中设置。


    OK,掌握这6步就可以画一张流程图了,我说的画流程图一点也不复杂吧,快去试试吧。

    展开全文
  • Activiti5学习-在流程图中为带条件的顺序流添加提示信息 Activiti5 中没有对顺序流添加提示,生成的图片没有办法看出顺序流所表示的条件,   研究代码后: ProcessDiagramCanvas 中添加...
  • 流程图画的好可以让自己的设计思路更加简洁明了,不仅是对自己对使用者来说也会更加的方便。...进入Word之后,菜单栏中的工具中选择插入操作,之后点击下面的形状选项,在流程图区域选择流程图图形添加...
  • 流程图中如何将文字置于底层?

    千次阅读 2018-01-23 16:32:00
     在流程图中有一个功能是将文字或图片置于底层或是置于表面,这样可以节约一定的空间,也可以使其内容增添一些个性,那么该如何操作呢? 1.运行电脑中的流程图的软件,没有软件的可以去下载安装迅捷流程图制作...
  • Activiti流程图乱码

    万次阅读 2016-04-15 17:52:15
     这种方式部署后引擎会自动生成流程图,存在的问题:Activiti Designer里面设计与自动生成的流程图坐标不一致,还有中文乱码问题(可以通过添加字体解决)和Flow上文字不显示或者坐标错位等问题。  解决乱码...
  • 无论是办公还是生活中,流程图都是一个必不可少的重要辅助工具,大到建筑设计小到生活计划都需要使用流程图来帮助我们更好的完成每一件事情!  但是流程图怎么做呢?很多朋友还是不知道的,今天小编给大家带来...
  • 流程图制作之Giffy Diagrams

    千次阅读 2016-05-04 14:57:17
    流程图:使用图形表示算法的思路是一种极好的方法,因为千言万语不如一张图。Gliffy Diagrams是一款相当实用的Chrome套件,支持离线使用,可以绘制各种图表,且透过模组化的物件来制作图表,将大大提高工作效率,...
  • 一款合格的流程图应用程序,应该可以同时满足业务流程图、组织结构图、数据流程图、程序流程图、思维导图的绘制。并且可以直接通过图表,对数据进行可视化、分析以及整理归类,将大量数据化繁为简。如果可以的话,还...
  • Web流程图绘制使用raphael

    万次阅读 2015-09-14 15:35:14
    本文要实现一个流程图的绘制,最终的目标是实现流程图的自动绘制,并可进行操作,直接点击流程图上对应的方框就可以让后台跑相应的程序。
  • 流程图是以特定的符号加上文字说明组合而成的图,是流经一个系统的信息流、观点流或部件流的图形代表。 一些企业中,流程图主要用来说明一些工艺流程或系统流程,也是完成作业中的一项管理过程。 二、怎么做流程...
  • 我们生活中见过各种各样的流程图车站见过购票流程图单位见过财务报销流程图家里见过电器故障排除图等等。这些图都有一个共同的特点,就是指导你一步步如何进行下一步操作,你只要按照流程图一步步执行...
  • 作为一名职业经理人,流程图是我的办公必备工具,经过多年的工作总结经验,总结出一首打油诗(五个特点)供大家参考;一个好的流程图制作软件必须有以下几个特点: 在线制作云储存 操作便捷高效率; 功能齐全不...
  • XMIND 画流程图

    千次阅读 2020-04-22 14:12:25
    如果之前word做过流程图,无非是需要什么图形,就插入找什么图形。但是请注意,xmind,要添加图形可不是插入找。一句话,就是所有图形都是双击空白处添加的,所有的箭头都是插入--联系这里加的,...
  • 企业中,流程图主要用来说明某一过程。这种过程既可以是生产线上的工艺流程,也可以是完成一项任务的管理过程。流程图是揭示和掌握封闭系统运动状况的有效方式。作为诊断工具,它能够辅助决策制定,让管理者清楚地...
  • 页面流程图

    千次阅读 2019-03-11 13:01:06
    有一些同学看过了我写的《如何绘制业务流程图》,发私信过来希望我谈谈页面流程图。 这个话题其实我也酝酿过,但一直没有写出来。细究起来,除了懒,原因其实有好几条: 这一年半来的工作都是围绕数据平台建设,不是...
  • 流程图画法教程

    千次阅读 2018-12-28 11:08:08
    企业中经常会遇到绘制工作流程图流程图可以让我们工作的步骤显示的更加清晰,让读者更快明白流程图要表达的意思,相较于大幅度的文字而言,能够为读者节省大量的阅读时间,这也是提高工作效率的方法,既然流程图...
  • MarkDown中写流程图的方法

    千次阅读 2019-04-03 21:57:36
    Mermaid FlowChat(中译为美人鱼,就好比一条美人鱼流动),是一种MarkDown中以特定格式的文字生成流程图或是图标的方法。 一种简单的降价式脚本语言,用于通过javascript从文本生成图表。 (官方文档点这里) ...
  • 使用mxGraph绘制流程图

    万次阅读 2018-08-14 16:54:56
    mxGraph是一个强大的JavaScript流程图前端库,可以快速创建交互式图表和图表应用程序,国内外著名的ProcessOne和draw.io都是使用该库创建的强大的在线流程图绘制网站. 这个库相当强大和复杂,以至于初次接触会...
  • 微信提现流程图

    千次阅读 2020-07-16 16:17:38
    简单对整个流程图做一个文字说明: 1,用户发起提现申请 这里没有什么可以说的.无非就是输入提现金额之类的操作. 2,做一些校验,主要校验用户余额是否满足提现的要求. 3,余额都不足就不要提现了撒 (想P呢..) 4,如果...
  • Visio 画流程图 入门

    万次阅读 多人点赞 2017-08-15 12:44:51
    1、下载 Visio 2013下载还是比较简单的,此就不载详细讲解,...3、开始画流程图拖拽即可将图形拉至画板上。如果编辑区比较小,你可以:设计--->大小 画板上会有绿色的尺寸线、对中线等提示,辅助图形定位,使得图
  • word中画基本的流程图

    千次阅读 2012-03-10 16:14:03
    流程图是最基本的流程图,也是我们平常用到最多的一种。(如下图)  制作步骤开始:  1、单击“绘图”工具栏上的“自选图形”,然后选择“流程图”,这里就可以看到众多制作流程图时所用到的形状了,...
  • Word中流程图

    千次阅读 2012-05-15 01:45:35
    第一种流程图制作  此流程图是最基本的流程图,也是我们平常用到最多的一种。(如下图)  制作步骤开始:  1、单击“绘图”工具栏上的“自选图形”,然后选择“流程图”,这里就可以看到众多制作...
  • 如何Word 2010中画流程图

    万次阅读 2012-03-10 16:00:34
    核心提示:Word2010文档中,利用自选图形库提供的丰富的流程图形状和连接符可以制作各种用途的流程图,制作步骤如下所述  Word2010文档中,利用自选图形库提供的丰富的流程图形状和连接符可以制作各种用途的...
  • 无论是办公还是生活中,流程图都是一个必不可少的重要辅助工具,大到建筑设计小到生活计划都需要使用流程图来帮助我们更好的完成每一件事情! 但是流程图怎么做呢?很多朋友还是不知道的,今天小编给大家带来...
  • 如何画流程图?画流程图真的有那么难吗?

    千次阅读 热门讨论 2019-01-07 10:58:17
    流程图是为了达到特定的目标而进行的一系列有逻辑性的操作过程,它可以不规范,可以充满问题,但它确确实实存在着。只要有事情或任务,就... 流程图是用来描述某个系统不同的情况下,如何应对用户的状态、决定和...
  • 流程图就是一种利用特定的图形、箭头和文字形成的一种表达算法和过程的图。如今流程图应用领域逐渐扩大,如工程行业、IT行业等。 二、怎么画流程图 接下来小编就来分享如何通过软件来画流程图,具体操作如下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,113
精华内容 26,045
关键字:

如何在流程图里添加文字