2013-03-29 34 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