2013-03-29 33 views
1

我在JScrollPane内部有一个JTree,当我使用滚动条时,树会变得模糊起来,如下图所示。JTree在滚动时模糊不清

如果我做了一些重绘,比如最小化和恢复窗口,或者单击树中的某个节点以使节点展开或折叠(但是如果拖动模糊不会消失,它将恢复正常窗户离开屏幕并返回,或拖动它前面的另一个窗口)。

JTree有一个自定义TreeModel和单元格渲染器。最近的变化是针对TreeModel;单元格渲染器在那里已经很久了,并且工作正常。单元格渲染器是DefaultTreeCellRenderer的子类,只覆盖getTreeCellRendererComponent方法(显示自定义图标)。

我曾经从包含要显示的数据的数据结构中填充DefaultMutableTreeNode,但是当节点数量很大时(例如超过10,000),这会带来性能问题。由于我所拥有的数据已经是树形结构,我意识到在不使用任何DefaultMutableTreeNode的情况下创建一个自定义TreeModel会相当简单。这使得JTree填充更快,但现在我留下了这个模糊的滚动问题。

Blurred JTree

下面的代码是不是从应用程序,但它编译为现在和将来都说明问题。删除tree.setBackground行停止模糊的行为。

package stackoverflow; 

import javax.swing.event.TreeModelListener; 
import javax.swing.tree.TreeModel; 
import javax.swing.tree.TreePath; 
import javax.swing.*; 
import java.awt.Color; 


public class NumberTreeModel implements TreeModel { 

    public static final int ROOT_NUMBER = 100; 

    public Object getChild(Object parent, int index) { 
     return index; 
    } 

    public int getChildCount(Object node) { 
     return isLeaf(node) ? 0 : ROOT_NUMBER; 
    } 

    @Override 
    public int getIndexOfChild(Object parent, Object child) { 
     int parentValue = ((Integer) parent).intValue(); 
     int childValue = ((Integer) child).intValue(); 
     return parentValue == ROOT_NUMBER ? childValue : -1 ; 
    } 

    public Object getRoot() { 
     return ROOT_NUMBER; 
    } 

    public boolean isLeaf(Object node) { 
     return ((Integer) node).intValue() < ROOT_NUMBER; 
    } 

    public void addTreeModelListener(TreeModelListener listener) { } 
    public void removeTreeModelListener(TreeModelListener listener) { } 
    public void valueForPathChanged(TreePath path, Object obj) { } 

    public static void display() { 

     JFrame frame = new JFrame("Number JTree"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     NumberTree tree = new NumberTree(); 
     tree.setModel(new NumberTreeModel()); 
     tree.setBackground(new Color(0,0,0,0)); 
     JScrollPane scroll = new JScrollPane(tree); 
     frame.add(scroll); 
     scroll.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE); 
     tree.expandRow(0); 
     frame.pack(); 
     frame.setSize(300, 400); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static class NumberTree extends JTree { 
     static final long serialVersionUID = 1; 

     @Override 
     public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, 
       int row, boolean hasFocus) { 
     if (value instanceof Integer) { 
      int n = ((Integer) value).intValue(); 
      return n + "=========".substring(0, n % 10); 
     } else { 
      System.out.println("value class=" + value.getClass()); 
      return value.toString(); 
     } 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      display(); 
     } 
     }); 
    } 
} 
+0

请编辑您的问题包括[SSCCE(http://sscce.org/)表现出您所描述的问题。 – trashgod

+3

某些地方不符合Swing的透明度要求。 IE浏览器。尝试将背景颜色设置为透明或半透明值 – MadProgrammer

+0

删除CustomCellRenderer和重写JTree.convertValueToText后,它仍然会出现相同的问题。 – Gigatron

回答

0

解决方案:

  • 不要使用setColor改变JTree的背景与非不透明的颜色。

  • 为节点的视觉透明度,实现自定义TreeCellRenderergetBackgroundNonSelectionColorgetBackground返回null,如JTree set background of node to non-opaque

    • 描述设置JScrollPaneJViewport.SIMPLE_SCROLL_MODE的视窗模式有助于滚动模糊的问题,但不一定会通过扩展和折叠ndoes重新绘制问题。
+0

只是为了澄清:a)为_any_组件设置半透明背景需要将其不透明属性设置为false,否则您会遇到绘画假象。从技术上讲,这是@trashgod怀疑的错误(重写paintComponent而不调用超类)b)DefaultTreeCellRenderer有一个相当奇怪的实现(关于它的背景)(http://stackoverflow.com/q/13735987/203657) – kleopatra

2

我怀疑你已经覆盖paintComponent()而忽视super.paintComponent(g),如图所示here

不太可能,您可能会在滚动窗格的视口中尝试使用setScrollMode()

编辑您的问题以包含sscce可能会说明问题。

附录:作为参考,这里有一个例子,而不是显示问题中看到的渲染工件。

enter image description here

import java.awt.EventQueue; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTree; 

/** 
* @see https://stackoverflow.com/a/15696825/230513 
*/ 
public class Sscce { 

    private void display() { 
     JFrame f = new JFrame("Sscce"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JTree tree = new JTree(); 
     for (int i = 0; i < tree.getRowCount(); i++) { 
      tree.expandRow(i); 
     } 
     f.add(new JScrollPane(tree)); 
     f.pack(); 
     f.setSize(200, 200); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Sscce().display(); 
      } 
     }); 
    } 
} 
+0

我没有在任何地方覆盖'paintComponent'。我忽略了'JTree.convertValueToText',因此它会为每个节点显示一个合适的字符串,而不是toString()的默认功能,并且我会覆盖问题中提到的getTreeCellRendererComponent。 – Gigatron

+0

将视口滚动模式更改为SIMPLE_SCROLL_MODE可以防止模糊发生(其他两种模式仍然存在模糊)。但是当树很大时,当树被填充时,GUI会冻结很长时间。我认为我的自定义TreeModel的getIndexOfChild存在对性能改进的需求,所以我会研究它并看看会发生什么。 – Gigatron

+0

尽管SIMPLE_SCROLL_MODE解决了滚动模糊问题,但现在它还存在另一个问题,即在展开和折叠节点时有时无法正确刷新。但我认为我正在寻求解决方案。今天下午更多细节,包括一个SSCCE。 – Gigatron