2011-05-27 37 views
2

我在JXMultiSplitPane中調整分離器期間似乎正在頻繁地重新繪製請求。 (見下面的程序)JXMultiSplitPane在滑塊調整過程中會導致重繪嗎?

爲什麼?

我有setContinuousLayout(false)


只是爲了澄清:我的理解重繪應該發生後分裂窗格調整。但期間分配器調整,沒有任何正在調整大小;分配器在屏幕上移動。


import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.LinkedList; 
import java.util.List; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import org.jdesktop.swingx.JXMultiSplitPane; 
import org.jdesktop.swingx.MultiSplitLayout; 

public class MultiVerticalPane<T extends Component> extends JPanel 
{ 
    final private List<T> components; 
    public MultiVerticalPane(List<? extends T> components, 
      List<Double> weights) 
    { 
     this.components = new ArrayList<T>(components); 
     final int n = this.components.size(); 
     if (weights != null && weights.size() != n) 
      throw new IllegalArgumentException(
        "weights and components should have same length"); 

     JXMultiSplitPane msp = new JXMultiSplitPane(); 
     msp.setContinuousLayout(false); 
     msp.getMultiSplitLayout().setModel(createSplitModel(weights)); 
     int i = 0; 
     for (T component : components) 
     { 
      msp.add(component, nodeTitle(i++)); 
     } 

     setLayout(new BorderLayout()); 
     add(msp, BorderLayout.CENTER); 
    } 
    private MultiSplitLayout.Split createSplitModel(
      List<Double> weights) 
    { 
     LinkedList<MultiSplitLayout.Node> nodes = 
      new LinkedList<MultiSplitLayout.Node>(); 
     int i = 0; 
     double wtot = 0; 
     for (double w : weights) 
     { 
      wtot += w; 
     } 
     for (double w : weights) 
     {   
      if (i > 0) 
       nodes.addFirst(new MultiSplitLayout.Divider()); 
      MultiSplitLayout.Leaf leaf = 
       new MultiSplitLayout.Leaf(nodeTitle(i++)); 
      leaf.setWeight(w/wtot); 
      nodes.addFirst(leaf); 
     } 
     MultiSplitLayout.Split split = 
      new MultiSplitLayout.Split(); 
     split.setRowLayout(false); 
     split.setChildren(nodes); 
     return split; 
    } 
    private String nodeTitle(int i) { 
     return String.format("%02d", i); 
    } 

    /************ test methods *************/ 

    private interface Painter 
    { 
     public void paint(Graphics g, Rectangle bounds); 
    } 

    static private class RelativeGraphics 
    { 
     final private Graphics g; 
     final private double xofs; 
     final private double yofs; 
     final private double xscale; 
     final private double yscale; 
     private double cx; 
     private double cy; 

     public RelativeGraphics(Graphics g, Rectangle bounds) 
     { 
      this.g = g; 
      this.cx = 0; 
      this.cy = 0; 
      this.xofs = bounds.getMinX(); 
      this.yofs = bounds.getMaxY(); 
      this.xscale = bounds.getWidth(); 
      this.yscale = -bounds.getHeight(); 
     } 
     public void moveTo(double x, double y) 
     { 
      this.cx = x; 
      this.cy = y; 
     } 
     public void lineTo(double x, double y) 
     { 
      this.g.drawLine(
       (int)(this.cx*this.xscale+this.xofs), 
       (int)(this.cy*this.yscale+this.yofs), 
       (int)(x*this.xscale+this.xofs), 
       (int)(y*this.yscale+this.yofs) 
      ); 
      moveTo(x,y); 
     }   
     public void rmoveTo(double dx, double dy) 
     { 
      moveTo(this.cx+dx, this.cy+dy); 
     }   
     public void rlineTo(double dx, double dy) 
     { 
      lineTo(this.cx+dx, this.cy+dy); 
     }   
    } 

    // adapted from http://en.wikipedia.org/wiki/Hilbert_curve#Java 
    static private class HilbertCurve 
    { 
     final private RelativeGraphics rg; 
     final private double d; 
     public HilbertCurve(RelativeGraphics rg, int level) 
     { 
      this.rg = rg; 
      double d0 = 1.0; 
      for (int i = level; i > 0; i--) 
       d0 /= 2; 
      this.d = d0; 
      rg.rmoveTo(d0/2, d0/2); 
      drawCurveUp(level); 
     } 
     private void drawCurveUp(int n) 
     {   
      if (n > 0) { 
       drawCurveLeft(n-1); this.rg.rlineTo(0, this.d); 
       drawCurveUp(n-1);  this.rg.rlineTo(this.d, 0); 
       drawCurveUp(n-1);  this.rg.rlineTo(0, -this.d); 
       drawCurveRight(n-1); 
      } 
     } 

     private void drawCurveLeft(int n) 
     { 
      if (n > 0) { 
       drawCurveUp(n-1);  this.rg.rlineTo(this.d, 0); 
       drawCurveLeft(n-1); this.rg.rlineTo(0, this.d); 
       drawCurveLeft(n-1); this.rg.rlineTo(-this.d, 0); 
       drawCurveDown(n-1); 
      } 
     } 

     private void drawCurveRight(int n) 
     { 
      if (n > 0) { 
       drawCurveDown(n-1);  this.rg.rlineTo(-this.d, 0); 
       drawCurveRight(n-1); this.rg.rlineTo(0, -this.d); 
       drawCurveRight(n-1); this.rg.rlineTo(this.d, 0); 
       drawCurveUp(n-1); 
      } 
     } 

     private void drawCurveDown(int n) 
     { 
      if (n > 0) { 
       drawCurveRight(n-1); this.rg.rlineTo(0, -this.d); 
       drawCurveDown(n-1);  this.rg.rlineTo(-this.d, 0); 
       drawCurveDown(n-1);  this.rg.rlineTo(0, this.d); 
       drawCurveLeft(n-1); 
      } 
     } 
    } 

    static private class HilbertPainter implements Painter 
    { 
     final private int level; 
     public HilbertPainter(int level) { this.level = level; } 
     @Override public void paint(Graphics g, Rectangle bounds) { 
      new HilbertCurve(
       new RelativeGraphics(g, 
        new Rectangle(new Point(0,0),bounds.getSize())), 
       this.level); 
     } 
    } 

    static private class PainterPanel extends JPanel 
    { 
     final private Painter painter; 

     public PainterPanel(Painter painter) 
     { 
      this.painter = painter; 
      setBackground(Color.WHITE); 
      setForeground(Color.RED); 
     } 
     @Override public void paintComponent(Graphics g) 
     { 
      super.paintComponent(g); 
      this.painter.paint(g, getBounds()); 
     } 
    } 

    public static void main(String[] args) { test(); } 
    private static void test() 
    { 
     JFrame frame = new JFrame("MultiVerticalPane test"); 
     List<JPanel> panels = new ArrayList<JPanel>(); 
     List<Double> weights = Arrays.asList(1.0,1.0,2.0,4.0,8.0); 

     for (int i = 0; i < 5; ++i) 
     { 
      panels.add(new PainterPanel(new HilbertPainter(i+4) 
       { 
        int count = 0; 
        @Override public void paint(Graphics g, 
          Rectangle bounds) 
        { 
         super.paint(g, 
          new Rectangle(bounds.getLocation(), 
           new Dimension(bounds.width, 
            bounds.height-10))); 
         g.drawString(String.format("%d", this.count++), 
           0, bounds.height); 
        } 
       } 
      )); 
     }  
     MultiVerticalPane<Component> mvp = 
      new MultiVerticalPane<Component>(panels, weights); 
     mvp.setPreferredSize(new Dimension(360,720)); 
     frame.setContentPane(mvp); 
     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 
} 
+0

+1有趣的問題,我認爲。我想知道其他人對此有何評論。 – Boro 2011-05-27 16:12:02

+0

@Jason S您是否注意到使用這種方法實際上可以節省大量的重新繪畫,並且重新繪製效果有所不同? setContinuousLayout(true)在鼠標釋放後不會導致其他組件重新繪製。 – Boro 2011-05-27 16:31:28

+0

@Jason S爲什麼你寫了自己的方法名爲Painter,同名的方法是從Java1.6_02X爲NimbusL&F實現的,SwingX有自己的Painter,但我認爲這也取決於Native OS和L&F – mKorbel 2011-05-27 17:24:33

回答

1

看起來像setContinuousLayout()影響revalidate()而不是repaint()

1

它不是一個 '直接' 的答案。我只是把它放在這裏,因爲我在評論中用完了空間。

我不認爲這太頻繁?你爲什麼會認爲你把它與其他任何組件進行比較?

我認爲每個調整組件的大小都會檢測到它調用了重繪。最重要的是佈局管理器如何處理大小調整。請注意,例如,當您調整最上方的面板並將其拖下時,它很少會被重新粉刷,您無法對其鄰居進行說明。當您向上拖動滑塊時,情況會逆轉。

順便說一句:我可能問你爲什麼會擔心分割窗格的頻率和部分被重新繪製?

請記住,我不是這個組件的重繪機制的內部專家,但我懷疑SwingX的人會從這方面的默認值中跳出來。

+0

沒有人知道,但這裏comings http://stackoverflow.com/questions/6144232/javaswing-efficient-over-of-rectangle-or-other-sprite – mKorbel 2011-05-27 17:29:55

+0

「我認爲每個調整組件的大小都會檢測到它調用了repaint」 - 當然,但調整大小不會發生在調整之後分配器已完成。 – 2011-05-27 19:51:37

+0

「我可能會問你爲什麼會擔心多久」 - 因爲複雜的繪畫需要很長時間(參見mKorbel鏈接的另一個問題6144232),而且如果我不喜歡使用bitblts來緩存繪圖不必。 – 2011-05-27 19:54:26

相關問題