2011-05-27 80 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

相关问题