weasis调节窗位相关代码分析

来源:互联网 发布:js。push Array[0] 编辑:程序博客网 时间:2024/06/07 02:33

首先从事件监听器说起

View2d  getMouseAdapter中获取相关的监听器

该监听器在EventManager初始化时注册

private EventManager() {
        iniAction(moveTroughSliceAction = getMoveTroughSliceAction(20, TIME.second, 0.1));
        iniAction(windowAction = newWindowAction());
        iniAction(levelAction = newLevelAction());

可以得出该监听器是SliderChangeListener

    protected SliderChangeListener newWindowAction() {

        return new SliderChangeListener(ActionW.WINDOW, WINDOW_SMALLEST, WINDOW_LARGEST, WINDOW_DEFAULT, true, 1.25) {

            @Override
            public void stateChanged(BoundedRangeModel model) {
                firePropertyChange(action.cmd(), null, model.getValue());
            }
        };
    }

该类也实现了相应的鼠标事件

    @Override
    public void mousePressed(MouseEvent e) {
        int buttonMask = getButtonMaskEx();
        if (!e.isConsumed() && (e.getModifiersEx() & buttonMask) != 0) {
            lastPosition = isMoveOnX() ? e.getX() : e.getY();
            dragAccumulator = getValue();
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        int buttonMask = getButtonMaskEx();
        int modifier = e.getModifiersEx();
        // dragAccumulator == Double.NaN when the listener did not catch the Pressed MouseEvent (could append in
        // multisplit container)
        if (!e.isConsumed() && (modifier & buttonMask) != 0 && dragAccumulator != Double.MAX_VALUE) {
            int position = isMoveOnX() ? e.getX() : e.getY();
            int mask = (InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK);
            // Accelerate the action if ctrl or shift is down
            double acceleratorKey = (modifier & mask) == 0 ? 1.0 : (modifier & mask) == mask ? 5.0 : 2.5;
            double val = (position - lastPosition) * getMouseSensivity() * acceleratorKey;
            if (val == 0.0) {
                return;
            }
            lastPosition = position;
            if (isInverse()) {
                dragAccumulator -= val;
            } else {
                dragAccumulator += val;
            }
            // logger.debug("val:" + val + " accu: " + dragAccumulator);
            if (val < 0.0) {
                setValue((int) Math.ceil(dragAccumulator));
            } else {
                setValue((int) Math.floor(dragAccumulator));
            }
        }
    }

修改它的值,然后触发他自己的stateChanged事件,然后又触发了firePropertyChange

这时DefaultView2d的propertyChange就会收到事件

else if (command.equals(ActionW.WINDOW.cmd())) {
            actionsInView.put(command, ((Integer) evt.getNewValue()).floatValue());
            imageLayer.updateImageOperation(WindowLevelOperation.name);
        }
里面携带了当前的窗位值,然后调用那个了RenderedImageLayer的updateImageOperation方法

    @Override
    public void updateImageOperation(String operation) {
        displayImage = operations.updateOperation(operation);
        fireImageChanged();
    }

这个方法会调用操作集合器生成更新后的图像

public RenderedImage updateOperation(String name) {
        RenderedImage result = null;
        int index = getOperationIndex(name);
        if (index == 0) {
            result = updateAllOperations();
        } else if (index > 0) {
            if (operations.size() > 0) {
                result = operations.get(index - 1).getRenderedImageNode();
                for (int i = index; i < operations.size(); i++) {
                    if (result == null) {
                        return updateAllOperations();
                    }
                    result = operations.get(i).getRenderedImage(result, imageOperation);
                }
            }
        }
        return result;
    }

然后触发层改变事件

    public void fireImageChanged() {
        if (displayImage == null) {
            operations.clearCacheNodes();
        }
        PlanarImage img = null;
        if (buildIterator && sourceImage != null) {
            img = sourceImage.getImage(preprocessing);
        }
        readIterator = (img == null) ? null : RandomIterFactory.create(img, null);
        fireLayerChanged();
    }

最后调用监听器的handleLayerChanged事件

    public void fireLayerChanged() {
        for (int i = 0; i < listenerList.size(); i++) {
            listenerList.get(i).handleLayerChanged(this);
        }
    }

监听器注册在Default2d的如下方法中

    public void registerDefaultListeners() {
        addFocusListener(this);
        ToolTipManager.sharedInstance().registerComponent(this);
        imageLayer.addLayerChangeListener(this);
    }

最后具体方法在View2d的一下中触发

    @Override
    public void handleLayerChanged(ImageLayer layer) {
        repaint();
    }

重绘会调用到DefaultView2d的draw方法,部分代码如下

/** paint routine */
    @Override
    public synchronized void paintComponent(Graphics g) {
        if (g instanceof Graphics2D) {
            draw((Graphics2D) g);
        }
    }

    protected void draw(Graphics2D g2d) {
        Stroke oldStroke = g2d.getStroke();
        Paint oldColor = g2d.getPaint();
        double viewScale = getViewModel().getViewScale();
        double offsetX = getViewModel().getModelOffsetX() * viewScale;
        double offsetY = getViewModel().getModelOffsetY() * viewScale;
        // Paint the visible area
        g2d.translate(-offsetX, -offsetY);
        // Set font size for computing shared text areas that need to be repainted in different zoom magnitudes.
        Font defaultFont = getFont();
        g2d.setFont(defaultFont);

        imageLayer.drawImage(g2d);

刚好看到drawImage方法,详细代码如下

    public void drawImage(Graphics2D g2d) {
        // Get the clipping rectangle
        if (!visible || displayImage == null) {
            return;
        }
        // Rectangle clipBounds = g2d.getClipBounds();
        // if (clipBounds == null || clipBounds.isEmpty()) {
        // clipBounds =
        // new Rectangle(displayImage.getMinX(), displayImage.getMinY(), displayImage.getWidth(),
        // displayImage.getHeight());
        // g2d.setClip(clipBounds);
        // }
        Shape clip = g2d.getClip();
        if (clip instanceof Rectangle2D) {
            Rectangle2D rect =
                new Rectangle2D.Double(displayImage.getMinX(), displayImage.getMinY(), displayImage.getWidth() - 1,
                    displayImage.getHeight() - 1);
            rect = rect.createIntersection((Rectangle2D) clip);
            if (rect.isEmpty()) {
                return;
            }
            g2d.setClip(rect);
        }

        try {
            g2d.drawRenderedImage(displayImage, AffineTransform.getTranslateInstance(0, 0));
        } catch (OutOfMemoryError e1) {
            System.gc();
            try {
                Thread.sleep(100);
            } catch (InterruptedException et) {
            }
        }
        g2d.setClip(clip);

    }

此处调用了java中最基础的g2d.drawRenderedImage绘制经过操作管理器生成的displayImage图片。

就此整个流程已经分析完成。

其他相关的缩放,移动等功能大体都类似,就不一一分析了

0 0