java - 当 setLabelsClipped 为 true 时,顶点标签在顶点外部、滚动条上和其他组件上绘制

标签 java paint repaint jgraph jgraphx

我使用 JGraph 一段时间了,当您将标签裁剪设置为 true 时,似乎存在绘画问题:

Overpainting example

下面的简化示例显示了您可能会遇到的实际应用程序中的问题:

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();
    }
}

值得注意的是,覆盖仅发生在顶点的范围内。以下是剪掉的名称:

Not Clipped

并进行剪辑:

Clipped

我现在正在研究 JGraphx 源代码,看看问题出在哪里。以前有人解决过这个问题吗?显然,设置 graph.setLabelsClipped(false) 可以解决这个问题,但我不想让我的顶点标签溢出到我的顶点的边界上。

最佳答案

我找到了问题所在。

从 com.mxgraph.view.mxGraph 中,如果添加一点点绘制代码,您可以看到剪辑被错误地设置为一个矩形,如我的示例所示,该矩形可能位于实际图形之外组件。

        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);
        }

如果我们绘制标签正在使用的剪切区域,我们就可以看到问题所在。

Bogus Clipping Area

实际上,我们应该只绘制原始 Canvas 和新剪切矩形的交集。下图显示了剪裁矩形在被新矩形践踏之前的样子:

Original Clipping Area

解决这个问题很简单:

        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);
            }
        }

我很想知道原始代码是否有意进行剪辑设置。我有点怀疑。

我的修复也默认为他们的实现,以防有人对他们的剪辑形状做了一些古怪的事情,就像某种 CYA 一样。可能不需要,因为剪裁不能保证适用于矩形以外的任何东西:

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

代码似乎位于 github 上,所以希望我能将修复推送到那里:

https://github.com/jgraph/jgraphx

关于java - 当 setLabelsClipped 为 true 时,顶点标签在顶点外部、滚动条上和其他组件上绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18776252/

相关文章:

java - 从菜单按钮启动 Activity ?

java - 从直线嵌套抛物线

Android:如何为 TextView 和 Layout 关闭抗锯齿

java - repaint() 方法未按预期运行

java - mouseListener react 慢(重画)

java - 部分应用程序神秘地无法重绘

java - Grails:急切加载不起作用

Java Eclipse 错误 'Source not found.'

java - TableRowSorter 和 RowFilter - 搜索可见和渲染的列

java - OFFSET 在带有可变参数的 repaint() 方法中起什么作用?