【问题标题】:Graphstream rendering disappears sporadically when displayed in docked panel of IntelliJ在 IntelliJ 的停靠面板中显示时,Graphstream 渲染偶尔会消失
【发布时间】:2017-12-18 13:38:49
【问题描述】:

我正在将 graphstream (www.graphstream-project.org) 集成到 JetBrains MPS(即 IntelliJ)中。图表显示在 IntelliJ 的“工具窗口”中(侧面的面板,见截图)。

如果面板处于“浮动”模式(未停靠),则可以正常工作(就像单独使用 graphstream 时一样,即在 JFrame 中)。但在“停靠”模式下(如屏幕截图所示),图表在某些情况下会消失,即工具窗口显示一个空白区域。

我无法重现导致问题的确切原因,但它似乎与 UI 相关。有时调整停靠面板的大小或在 IntelliJ 的某些完全不相关的部分显示工具提示会触发“消失”,有时不会。如果再次获得焦点,图表总是会重新出现(例如单击空白区域)。

我觉得这是 IntelliJ 中的一个错误,但如果有任何想法如何进一步调查该问题(我可以从哪里开始调试等...),我将不胜感激。

代码 - 简短版本:有一个 JPanel 包含由 graphstream 使用 Viewer.getDefaultView() 创建的 DefaultView 实例。这将移交给 MPS / IntelliJ API。

完整代码:

// construct the graph
Graph graph = new SingleGraph("Graph");
graph.addAttribute("ui.quality");
graph.addAttribute("ui.antialias");

// ... calls to graph.addNode(), graph.addEdge() to generate some content

// construct Viewer and ViewPanel (ViewPanel extends JPanel)
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
ViewPanel viewPanel = viewer.getDefaultView();

// ViewPanel is added to another JPanel as the latter will include a toolbar later
JPanel panel = new JPanel(new BorderLayout());
panel.add(BorderLayout.CENTER, viewPanel);

// The panel is returned to MPS, which uses the IntelliJ API to
// create respective tool window. This part is not under my control.
// If you think it is relevant please mention it.
return panel;

/编辑:

在进一步调查此问题时,我发现一定有某事会触发错误行为。一开始一切正常,但一段时间后,事情表现得很奇怪并继续这样做,直到我重新创建 IntelliJ 工具窗口。我制作了一个简短的视频片段来说明这一点,请参阅YouTube

我不知道什么可能是“触发器”。我假设存在一些竞争条件/线程相关问题。

【问题讨论】:

  • 这个完整的example有什么不同吗?
  • 没有。如前所述:在 JFrame 中没有问题,就像在垃圾上帝的链接示例中一样。问题仅发生在 停靠 IntelliJ 窗口中。我上面的例子是完整的。您需要 MPS (=IntelliJ) 来重现该问题。在链接的示例中,您会看到“显示”JFrame 的代码,在我的例子中,这部分是由 IntelliJ 完成的。可能在那里可以找到问题的原因。所以我在询问如何进一步调试它。
  • GRAPH_IN_ANOTHER_THREAD有什么区别?
  • 好点,我当然试过了。没有区别...
  • 是否强制重绘,例如切换应用程序或从上下文菜单中选择“调整大小”,恢复显示?可以试试这个approach 来检查 EDT 违规吗?

标签: swing intellij-idea awt graphstream mps


【解决方案1】:

我发现只有在 ToolWindowsPane.paintChildren() 的上下文中调用 graphstream ViewPanelpaintComponent() 时才会擦除绘图。在大多数情况下,paintComponent() 的调用方式不同(堆栈中的方法较少,尤其是 ToolWindowsPane 中没有任何方法)。

ToolWindowsPane.paintChildren() 似乎每次在 IntelliJ 中的某处显示工具提示时都会被调用,例如。因此,绕过该问题的一个肮脏的技巧是实现一个自定义的ViewPanel,并覆盖paintComponent。这很简单,因为 DefaultView 的 graphstream 可以扩展。

以下代码查看调用层次结构并在必要时发出repaint()。这解决了问题,但会导致额外的渲染工作,但在我的情况下这似乎不是问题。

public class CustomView extends DefaultView { 

  public CustomView(Viewer viewer, String identifier, GraphRenderer graphRenderer) { 
    super(viewer, identifier, graphRenderer); 
  } 

  @Override 
  public void paintComponent(Graphics g) {  
    StackTraceElement[] stackElements = Thread.currentThread().getStackTrace(); 
    for (int i = 0; i < stackElements.length; i++) { 
      if (stackElements[i].getClassName().equals(ToolWindowsPane.class.getName())) { 
        repaint(); 
        break; 
      } 
    } 
    super.paintComponent(g); 
  } 

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-09
    • 2013-11-24
    • 1970-01-01
    • 2017-06-08
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    相关资源
    最近更新 更多