Vertex labels painting outside of vertex, over scrollbars and onto other components when setLabelsClipped is true

隐身守侯 提交于 2019-12-11 02:47:48

问题


I've been working with JGraph for a while and it appears there is a painting issue when you set label clipping to true:

The following boiled-down example shows the problem in a living application that you can mess with:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;

/** it's an app! */
public class GraphApp extends JFrame {
    private mxGraph graph;
    private mxGraphComponent graphComponent;
    private boolean labelsClipped = false;

    /** @return the splitpane */
    public JSplitPane getSplitpane() {
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        graph = new mxGraph();
        graph.getModel().beginUpdate();
        graph.removeCells(graph.getChildCells(graph.getDefaultParent(), true, true));
        for (int i = 0; i < 10; i++)
            graph.insertVertex(null, null, "very_very_long_vertex_" + i, 10 * i, 10 * i, 100, 50);
        graph.getModel().endUpdate();
        graph.setLabelsClipped(labelsClipped);
        graphComponent = new mxGraphComponent(graph);
        JTextArea area = new JTextArea("There's overpaint below this text."); //$NON-NLS-1$
        splitPane.add(graphComponent, JSplitPane.LEFT);
        splitPane.add(area, JSplitPane.RIGHT);
        splitPane.setDividerLocation(70);
        return splitPane;
    }

    private JButton getButton() {
        JButton button = new JButton(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                labelsClipped = !labelsClipped;
                graph.setLabelsClipped(labelsClipped);
                GraphApp.this.repaint();
            }
        });
        button.setText("Swap setLabelsClipped");
        return button;
    }

    private JPanel getPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.add(getSplitpane(), BorderLayout.CENTER);
        panel.add(getButton(), BorderLayout.SOUTH);
        return panel;
    }

    public static void main(String[] args) {
        GraphApp app = new GraphApp();
        app.add(app.getPanel());
        app.setPreferredSize(new Dimension(300, 100));
        app.setVisible(true);
        app.pack();
    }
}

It's also interesting to note, that overpaint only happens within the confines of the vertex. Here are the names with clipping off:

And with clipping on:

I'm looking into the JGraphx source now to see where the problem lies. Has anyone worked around this before? Obviously setting graph.setLabelsClipped(false) works around it, but I'd rather not have my vertex labels spill out over the bounds of my vertices.


回答1:


I found where the issue lies.

From com.mxgraph.view.mxGraph, if you add this little bit of painting code, you can see that the clip is incorrectly getting set to a rectangle that can be, as evidenced in my example, outside of the actual graph component.

        if (clippedCanvas instanceof mxGraphics2DCanvas)
        {
            System.out.println("setting new clip");
            Graphics g = ((mxGraphics2DCanvas) clippedCanvas).getGraphics();
            clip = g.getClip();
            g.setClip(newClip);
            ((mxGraphics2DCanvas) clippedCanvas).paintRectangle(((mxGraphics2DCanvas) clippedCanvas).getGraphics().getClipBounds(), Color.GREEN, Color.WHITE);
        }

If we paint the clipping area that the label is working with, we can see where the problem lies.

Realistically, we should only be painting the intersection of the original canvas, and the new clipping rectangle. This image shows what the clipping rectangle was before being trampled by the new one:

The fix for this is a simple one:

        if (clippedCanvas instanceof mxGraphics2DCanvas)
        {
            Graphics g = ((mxGraphics2DCanvas) clippedCanvas).getGraphics();
            clip = g.getClip();
            if (clip instanceof Rectangle)
            {
                g.setClip(newClip.intersection((Rectangle) clip));
            }
            else
            {
                g.setClip(newClip);
            }
        }

I'd be interested to hear if the original code did the clip setting as it did intentionally. I kind of doubt it.

My fix also defaults to their implementation in the case that someone does something wacky with their clip shapes, just as a sort of CYA. Probably not needed as clipping isn't guaranteed to work with anything other than rectangles:

http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Graphics.html#setClip(java.awt.Shape)

It appears that the code lives here on github, so hopefully I can get the fix pushed there:

https://github.com/jgraph/jgraphx



来源:https://stackoverflow.com/questions/18776252/vertex-labels-painting-outside-of-vertex-over-scrollbars-and-onto-other-compone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!