2012-10-26 104 views
3

我想創建一個佈局管理器,它將面板劃分爲單元格,並且可以將組件添加到指定單元格(行,列)的面板中。單元格的寬度和高度應該在重新調整面板大小時更新(這是問題所在,它不會重新調整單元格的大小)。這些類本身可以工作,但是在調整大小時不會更新單元大小,它似乎甚至不會調用LayoutManager::SetBounds(int, int)。之所以我創建一個單獨的類是因爲我將爲其他容器使用相同的佈局管理器,例如GroupBox。這裏是我的代碼在C中爲面板創建佈局時遇到問題#

public class Insets 
{ 
    public int bottom = 0; 
    public int top = 0; 
    public int left = 0; 
    public int right = 0; 

    public Insets(int top, int left, int bottom, int right) { 
     this.top = top; 
     this.left = left; 
     this.bottom = bottom; 
     this.right = right; 
    } 
} 

/* 
* LayoutManager class 
*/ 

using System; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Collections.Generic; 



public class LayoutManager 
{ 
    public enum Constraints{ 
     HORIZONTAL, 
     VERTICAL, 
     NONE 
    }; 

    public Insets insets = new Insets(0, 0, 0, 0); 
    public Constraints fill = Constraints.NONE; 
    public Panel container = null; 
    public int cellheight = 1; 
    public int cellwidth = 1; 

    private List <int> indices = new List <int>(); 
    private int columns = 1; 
    private int rows = 1; 
    private int dh = 0; 
    private int dw = 0; 

    public LayoutManager(){ 
    } 
    private int Index2DTo1D(int row, int column){ 
     return (column + (row * columns)); 
    } 
    private int Index1DToRow2D(int index){ 
     return index/columns; 
    } 
    private int Index1DToColumn2D(int index){ 
     return index/rows; 
    } 
    private void SetGridMatrix(int rows, int columns) { 
     if (rows >= this.rows){ 
      this.rows = rows + 1; 
     } 
     if (columns >= this.columns){ 
      this.columns = columns + 1; 
     } 
    } 
    public void RepaintChildrenComponents() { 
     if(container != null){ 
      foreach(Control control in container.Controls){ 
       ((CheckBox)control).Text = container.Width.ToString(); 
      }  
     } 
    } 
    public void SetBounds(int width, int height) { 
     SetCellsDimensions(width, height); 
     RepaintChildrenComponents(); 
    } 
    public void SetCellsDimensions(int width, int height){ 
     this.dw = width/columns; 
     this.dh = height/rows; 
    } 
    public void SetContainer(ref Panel container) { 
     this.container = container; 
    } 
    public Point GetChildComponentXY(int x, int y){ 
     if(x >= 0 && y >= 0){ 
      return new Point((x * dw) + insets.right, (y * dh) + insets.top); 
     } 
     throw new System.ArgumentOutOfRangeException(""); 
    } 
    public Size GetComputedComponentSize(){ 
     return new Size((cellwidth * dw) - (insets.left + insets.right), 
         (cellheight * dh) - (insets.top + insets.bottom));    
    } 
    public void AddComponent(Control control, Point location, LayoutManager.Constraints fill){ 
     if(container != null && control != null){ 
      indices.Insert(container.Controls.Count, Index2DTo1D(location.X, location.Y)); 
      container.Controls.Add(SetChildComponentBounds(control, location)); 
      SetGridMatrix(location.X, location.Y); 
      SetCellsDimensions(container.Width, container.Height); 
     }else{ 
      throw new NullReferenceException(""); 
     } 
    } 
    protected Control SetChildComponentBounds(Control control, Point location) { 
     control.Location = GetChildComponentXY(location.X, location.Y); 
     control.Size = GetComputedComponentSize(); 
     return control; 
    } 
    public void AddComponent(Control control, Point location){ 
     AddComponent(control, location, LayoutManager.Constraints.NONE); 
    } 
} 

/* 
* 
* JPanel class 
*/ 


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 
using System.Windows.Forms; 


class JPanel : Panel 
{ 
    private LayoutManager layman; 

    public JPanel(){ 
     layman = new JComponent.LayoutManager(); 

     Panel container = this; 
     layman.SetContainer(ref container); 


     string[] elems = { "Multiplication", "Division", "Addition", "Subtraction"}; 
     int e = 0; 

     this.Size = new Size(300, 125); 

     foreach(string str in elems){ 

      CheckBox box = new CheckBox(); 
      box.Text = str; 
      layman.AddComponent(box, new Point(0, e++)); 
      //this.Controls.Add(box); 
     } 

    } 
    public JPanel(LayoutManager layman) { 
     LayoutManager = layman; 
    } 

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified){ 
     if(layman != null){ 
      layman.SetBounds(width, height); 
     } 
     base.SetBoundsCore(x, y, width, height, specified); 
    } 
    public LayoutManager LayoutManager{ 
     set{ 
      layman = value; 
     } 
     get{ 
      return layman; 
     } 
    } 
} 
+0

你想創建一個自定義數據網格(UserControl/OwnerDraw)? –

+0

我同意上面的這張海報,我認爲這正是Grid所做的。如果您正在尋找將網格功能添加到其他控件,爲什麼不把網格添加到控件的孩子,並讓它成爲你想要的。您可以輕鬆創建一個可以自動爲您執行此操作的方法。 – Nomad101

回答

0

請看看TableLayoutPanel類。我認爲這個控制正在做你正在努力達到的目標。 TableLayoutPanel允許您在表單編輯器中定義行/列並以編程方式,將控件放置在單元格內,合併行/列,根據內容自動調整面板大小或根據面板大小自動調整內容大小。

下面是關於如何在Windows窗體布點工作一個非常有趣的文檔:

https://docs.google.com/viewer?a=v&q=cache:nePz-uaPReYJ:www.windowsclient.net/samples/go%2520to%2520market/layout/layoutgtm.doc+Whidbey+Layout+tablelayoutpanel&hl=de&gl=de&pid=bl&srcid=ADGEEShlobh-RfSTegC1NuOc72m0vRPu6RsF3USTSPnSasU-9qSklTbJzclRol6Nxg5sxEUXZOWYZwgrSdZdAjJ5EXhCft7qj5jBr4-kkkX6380-0itVaHkG-TAvK4KvNtDymEFlUXM6&sig=AHIEtbTnyasKOG5tuZwub59LBw8UeZL8Lg

可惜的是我只能找到通過谷歌搜索緩存文件。原來的鏈接似乎被刪除。