Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Windows窗体中实例化大量按钮?_C#_.net_Windows_Winforms - Fatal编程技术网

C# 如何在Windows窗体中实例化大量按钮?

C# 如何在Windows窗体中实例化大量按钮?,c#,.net,windows,winforms,C#,.net,Windows,Winforms,我正在开发一个剧院预订软件。我使用的是Windows窗体,座位由二维数组表示。我画的按钮如下: public void DrawSeats() { // pnl_seats is a Panel pnl_seats.Controls.Clear(); // Here I store all Buttons instance, to later add all buttons in one call (AddRange) to the Panel var btns

我正在开发一个剧院预订软件。我使用的是Windows窗体,座位由二维数组表示。我画的按钮如下:

public void DrawSeats()
{
    // pnl_seats is a Panel
    pnl_seats.Controls.Clear();
    // Here I store all Buttons instance, to later add all buttons in one call (AddRange) to the Panel
    var btns = new List<Control>();
    // Suspend layout to avoid undesired Redraw/Refresh
    this.SuspendLayout();
    for (int y = 0; y < _seatZone.VerticalSize; y++)
    {
        for (int x = 0; x < _seatZone.HorizontalSize; x++)
        {
            // Check if this seat exists
            if (IsException(x, y))
                continue;
            // Construct the button with desired properties. SeatSize is a common value for every button
            var btn = new Button
            {
                Width = SeatSize, 
                Height = SeatSize,
                Left = (x * SeatSize),
                Top = (y * SeatSize),
                Text = y + "" + x,
                Tag = y + ";" + x, // When the button clicks, the purpose of this is to remember which seat this button is.
                Font = new Font(new FontFamily("Microsoft Sans Serif"), 6.5f)
            };

            // Check if it is already reserved
            if (ExistsReservation(x, y))
                btn.Enabled = false;
            else
                btn.Click += btn_seat_Click; // Add click event

            btns.Add(btn);
        }
    }
    // As said before, add all buttons in one call
    pnl_seats.Controls.AddRange(btns.ToArray());
    // Resume the layout
    this.ResumeLayout();
}

编辑;有人向我指出,这在Windows窗体中不起作用

好吧,你正在按顺序完成它。 如果一次迭代花费1秒,整个过程将花费400*1的时间

也许你应该试着收集你的对象,并“并行”处理它

尝试.Net framework(4及以上版本)“parallel foreach”方法:

编辑:所以,如果你有一个列表按钮名,你可以说

buttonNames.ForEach(x=>CreateButton(x));
而您的CreateButton()方法如下所示:

public void DrawSeats()
{
    // pnl_seats is a Panel
    pnl_seats.Controls.Clear();
    // Here I store all Buttons instance, to later add all buttons in one call (AddRange) to the Panel
    var btns = new List<Control>();
    // Suspend layout to avoid undesired Redraw/Refresh
    this.SuspendLayout();
    for (int y = 0; y < _seatZone.VerticalSize; y++)
    {
        for (int x = 0; x < _seatZone.HorizontalSize; x++)
        {
            // Check if this seat exists
            if (IsException(x, y))
                continue;
            // Construct the button with desired properties. SeatSize is a common value for every button
            var btn = new Button
            {
                Width = SeatSize, 
                Height = SeatSize,
                Left = (x * SeatSize),
                Top = (y * SeatSize),
                Text = y + "" + x,
                Tag = y + ";" + x, // When the button clicks, the purpose of this is to remember which seat this button is.
                Font = new Font(new FontFamily("Microsoft Sans Serif"), 6.5f)
            };

            // Check if it is already reserved
            if (ExistsReservation(x, y))
                btn.Enabled = false;
            else
                btn.Click += btn_seat_Click; // Add click event

            btns.Add(btn);
        }
    }
    // As said before, add all buttons in one call
    pnl_seats.Controls.AddRange(btns.ToArray());
    // Resume the layout
    this.ResumeLayout();
}
私有按钮CreateButton(按钮的字符串名称){Button b=new Button();b.Text=nameOfButton;//做任何你想做的事。。。 返回b;}


不使用实际的按钮控件,只需绘制座椅的图像,然后当用户单击座椅时,平移鼠标X、Y坐标以确定单击了哪个座椅。这样会更有效率。当然,缺点是您必须编写将x,y坐标转换为座椅的方法,但这并不是那么困难

假设您将保留和排除的数组更改为

public List<string> _seatsExceptions = new List<string>();
public List<string> _seatsReservations = new List<string>();
您对排除和预订的检查可以更改为

bool IsException(int x, int y)
{
    string key = x.ToString() + ";" + y.ToString();
    return _seatsExceptions.Contains(key);
}
bool ExistsReservation(int x, int y)
{
    string key = x.ToString() + ";" + y.ToString();
    return _seatsReservations.Contains(key);
}
当然,我不知道你是否能在你的程序中做出这样的改变。然而,考虑早晚改变你的数组的搜索。


编辑我做了一些测试,虽然20x20按钮组成的虚拟网格工作正常(平均31毫秒0.775毫秒),但更大的按钮速度明显减慢。在200x50时,计时跳至10秒(平均10675秒)。因此,或许需要一种不同的方法。绑定DataGridView可能是一个更简单的解决方案,并且相对容易处理。

我也不会使用如此多的控件来实现这样的事情。相反,您可能应该创建自己的UserControl,它将所有座椅绘制为图像,并对单击事件作出反应

为了让你更容易一点,我创建了这样一个简单的用户控件,它将绘制所有的座位,并在鼠标点击改变状态时做出反应。这是:

public enum SeatState
{
    Empty,
    Selected,
    Full
}

public partial class Seats : UserControl
{
    private int _Columns;
    private int _Rows;
    private List<List<SeatState>> _SeatStates;

    public Seats()
    {
        InitializeComponent();
        this.DoubleBuffered = true;

        _SeatStates = new List<List<SeatState>>();
        _Rows = 40;
        _Columns = 40;
        ReDimSeatStates();

        MouseUp += OnMouseUp;
        Paint += OnPaint;
        Resize += OnResize;
    }

    public int Columns
    {
        get { return _Columns; }
        set
        {
            _Columns = Math.Min(1, value);
            ReDimSeatStates();
        }
    }

    public int Rows
    {
        get { return _Rows; }
        set
        {
            _Rows = Math.Min(1, value);
            ReDimSeatStates();
        }
    }

    private Image GetPictureForSeat(int row, int column)
    {
        var seatState = _SeatStates[row][column];

        switch (seatState)
        {
            case SeatState.Empty:
                return Properties.Resources.emptySeat;

            case SeatState.Selected:
                return Properties.Resources.choosenSeat;

            default:
            case SeatState.Full:
                return Properties.Resources.fullSeat;
        }
    }

    private void OnMouseUp(object sender, MouseEventArgs e)
    {
        var heightPerSeat = Height / (float)Rows;
        var widthPerSeat = Width / (float)Columns;

        var row = (int)(e.X / widthPerSeat);
        var column = (int)(e.Y / heightPerSeat);
        var seatState = _SeatStates[row][column];

        switch (seatState)
        {
            case SeatState.Empty:
                _SeatStates[row][column] = SeatState.Selected;
                break;

            case SeatState.Selected:
                _SeatStates[row][column] = SeatState.Empty;
                break;
        }

        Invalidate();
    }

    private void OnPaint(object sender, PaintEventArgs e)
    {
        var heightPerSeat = Height / (float)Rows;
        var widthPerSeat = Width / (float)Columns;

        e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

        for (int row = 0; row < Rows; row++)
        {
            for (int column = 0; column < Columns; column++)
            {
                var seatImage = GetPictureForSeat(row, column);
                e.Graphics.DrawImage(seatImage, row * widthPerSeat, column * heightPerSeat, widthPerSeat, heightPerSeat);
            }
        }
    }

    private void OnResize(object sender, System.EventArgs e)
    {
        Invalidate();
    }

    private void ReDimSeatStates()
    {
        while (_SeatStates.Count < Rows)
            _SeatStates.Add(new List<SeatState>());

        if (_SeatStates.First().Count < Columns)
            foreach (var columnList in _SeatStates)
                while (columnList.Count < Columns)
                    columnList.Add(SeatState.Empty);

        while (_SeatStates.Count > Rows)
            _SeatStates.RemoveAt(_SeatStates.Count - 1);

        if (_SeatStates.First().Count > Columns)
            foreach (var columnList in _SeatStates)
                while (columnList.Count > Columns)
                    columnList.RemoveAt(columnList.Count - 1);
    }
}
公共枚举座位状态
{
空的,,
挑选出来的,
满满的
}
公共部分类席位:UserControl
{
专用int_列;
私有整数行;
私人名单(SeatStates);;
公众席()
{
初始化组件();
this.DoubleBuffered=true;
_SeatStates=新列表();
_行=40;
_列=40;
ReDimSeatStates();
MouseUp+=OnMouseUp;
油漆+=油漆;
Resize+=OnResize;
}
公共int列
{
获取{return\u Columns;}
设置
{
_列=数学最小值(1,值);
ReDimSeatStates();
}
}
公共整数行
{
获取{返回_行;}
设置
{
_行=Math.Min(1,值);
ReDimSeatStates();
}
}
私有图像GetPictureForSeat(int行,int列)
{
var seatState=_SeatStates[行][列];
开关(座椅状态)
{
箱座状态。空:
返回Properties.Resources.emptySeat;
案例座位状态。已选择:
返回Properties.Resources.choosenSeat;
违约:
箱座状态。完整:
返回Properties.Resources.fullSeat;
}
}
MouseUp上的私有void(对象发送器、MouseEventArgs e)
{
var heightPerSeat=高度/(浮动)行;
var widthPerSeat=宽度/(浮动)列;
变量行=(整数)(e.X/T);
变量列=(整数)(e.Y/高度);
var seatState=_SeatStates[行][列];
开关(座椅状态)
{
箱座状态。空:
_SeatStates[行][列]=SeatState.选中;
打破
案例座位状态。已选择:
_SeatStates[行][列]=SeatState.Empty;
打破
}
使无效();
}
私有void OnPaint(对象发送方,PaintEventArgs e)
{
var heightPerSeat=高度/(浮动)行;
var widthPerSeat=宽度/(浮动)列;
e、 Graphics.CompositingQuality=System.Drawing.Drawing2D.CompositingQuality.HighQuality;
e、 Graphics.InterpolationMode=System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
e、 Graphics.PixelOffsetMode=System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
e、 Graphics.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.HighQuality;
对于(int row=0;row行)
_SeatStates.RemoveAt(_SeatStates.Count-1);
if(_SeatStates.First().Count>列)
foreach(var列列表在_SeatStates中)
while(columnList.Count>列)
columnList.RemoveAt(columnList.Count-1);
}
}
这将当前绘制40行和40列(因此有800个座位),您可以单击每个座位来更改其状态

这是
public enum SeatState
{
    Empty,
    Selected,
    Full
}

public partial class Seats : UserControl
{
    private int _Columns;
    private int _Rows;
    private List<List<SeatState>> _SeatStates;

    public Seats()
    {
        InitializeComponent();
        this.DoubleBuffered = true;

        _SeatStates = new List<List<SeatState>>();
        _Rows = 40;
        _Columns = 40;
        ReDimSeatStates();

        MouseUp += OnMouseUp;
        Paint += OnPaint;
        Resize += OnResize;
    }

    public int Columns
    {
        get { return _Columns; }
        set
        {
            _Columns = Math.Min(1, value);
            ReDimSeatStates();
        }
    }

    public int Rows
    {
        get { return _Rows; }
        set
        {
            _Rows = Math.Min(1, value);
            ReDimSeatStates();
        }
    }

    private Image GetPictureForSeat(int row, int column)
    {
        var seatState = _SeatStates[row][column];

        switch (seatState)
        {
            case SeatState.Empty:
                return Properties.Resources.emptySeat;

            case SeatState.Selected:
                return Properties.Resources.choosenSeat;

            default:
            case SeatState.Full:
                return Properties.Resources.fullSeat;
        }
    }

    private void OnMouseUp(object sender, MouseEventArgs e)
    {
        var heightPerSeat = Height / (float)Rows;
        var widthPerSeat = Width / (float)Columns;

        var row = (int)(e.X / widthPerSeat);
        var column = (int)(e.Y / heightPerSeat);
        var seatState = _SeatStates[row][column];

        switch (seatState)
        {
            case SeatState.Empty:
                _SeatStates[row][column] = SeatState.Selected;
                break;

            case SeatState.Selected:
                _SeatStates[row][column] = SeatState.Empty;
                break;
        }

        Invalidate();
    }

    private void OnPaint(object sender, PaintEventArgs e)
    {
        var heightPerSeat = Height / (float)Rows;
        var widthPerSeat = Width / (float)Columns;

        e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

        for (int row = 0; row < Rows; row++)
        {
            for (int column = 0; column < Columns; column++)
            {
                var seatImage = GetPictureForSeat(row, column);
                e.Graphics.DrawImage(seatImage, row * widthPerSeat, column * heightPerSeat, widthPerSeat, heightPerSeat);
            }
        }
    }

    private void OnResize(object sender, System.EventArgs e)
    {
        Invalidate();
    }

    private void ReDimSeatStates()
    {
        while (_SeatStates.Count < Rows)
            _SeatStates.Add(new List<SeatState>());

        if (_SeatStates.First().Count < Columns)
            foreach (var columnList in _SeatStates)
                while (columnList.Count < Columns)
                    columnList.Add(SeatState.Empty);

        while (_SeatStates.Count > Rows)
            _SeatStates.RemoveAt(_SeatStates.Count - 1);

        if (_SeatStates.First().Count > Columns)
            foreach (var columnList in _SeatStates)
                while (columnList.Count > Columns)
                    columnList.RemoveAt(columnList.Count - 1);
    }
}