Why doesn't my TableLayoutPanel use all of its size when divided by percentages?

烈酒焚心 提交于 2019-12-13 04:52:15

问题


I am dynamically adding controls to a TableLayoutPanel.

It has 12 rows and 32 columns.

I've divided the widths of the columns so that those with labels are twice as wide as those with TextBoxes, and the percentages add up to 100:

labels = 5%
textBoxes = 2.5%

As there are 24 textboxes per row and 8 labels per row, this equals 100% (40% labels, 60% textBoxes).

HOWEVER, the last column is a spacehog, as can be seen here:

http://warbler.posterous.com/the-32-column-is-wider-than-the-rest

And I need that space for the labels to show their entire selves: they are really five characters wide ("00:00" ... "23:45") not four, as displayed.

Based on empirical evidence (previous trial-and-error) I could reduce the width of the TLP to skinny up that last column, but that doesn't solve my label-cells-too-skinny problem.

This is how I'm slapping the controls on the TLP (I've set the column width percentages at design-time, via the properties page for Columns collection)

private void AddPlatypusScheduleControlsToTableLayoutPanel()
{
    try
    {
        this.SuspendLayout();
        tableLayoutPanelPlatypusSchedule.ColumnCount = PLATYPUS_SCHEDULE_COL_COUNT;
        int ColNum = 0;
        int RowNum = 0;
        int LoopCounter = 1;
        var dt = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);

        while (LoopCounter <= QUARTER_HOUR_COUNT)
        {
            string lblName = string.Format("labelPS{0}", LoopCounter);
            var lbl = new Label
                {
                    Name = lblName,
                    Dock = DockStyle.Fill,
                    Margin = new Padding(),
                    Font = new Font("Microsoft Sans Serif", 7),
                    TextAlign = ContentAlignment.MiddleCenter,
                    Text = dt.ToString("HH:mm")
                };
            tableLayoutPanelPlatypusSchedule.Controls.Add(lbl, ColNum, RowNum);

            string txtbxName1 = string.Format("textBoxLSA{0}", LoopCounter);
            var txtbxa = new TextBox { Name = txtbxName1, Dock = DockStyle.Fill, Margin = new Padding() };
            string txtbxName2 = string.Format("textBoxLSB{0}", LoopCounter);
            var txtbxb = new TextBox { Name = txtbxName2, Dock = DockStyle.Fill, Margin = new Padding() };
            string txtbxName3 = string.Format("textBoxLSC{0}", LoopCounter);
            var txtbxc = new TextBox { Name = txtbxName3, Dock = DockStyle.Fill, Margin = new Padding() };
            tableLayoutPanelPlatypusSchedule.Controls.Add(txtbxa, ColNum + 1, RowNum);
            tableLayoutPanelPlatypusSchedule.Controls.Add(txtbxb, ColNum + 2, RowNum);
            tableLayoutPanelPlatypusSchedule.Controls.Add(txtbxc, ColNum + 3, RowNum);

            dt = dt.AddMinutes(15);
            RowNum++;
            LoopCounter++;
            if (RowNum == 12)
            {
                ColNum = ColNum + 4;
                RowNum = 0;
            }
        }
    }
    finally {
        this.ResumeLayout();
    }
}

UPDATE

I thought maybe the problem was the width of the TLP was not exactly divisible by 32 (it was 619); so I widened it to 640, yet the same problem remains.

UPDATE 2

To get it to work, I had to use absolute sizes for the columns rather than percentages*, and increase the width of the label-holding columns to 35 (which leaves only 15 for the textBox-holding columns at a TLP width of 640).

  • WPF can be a bear at times (more like a Kodiak than Winnie), but it sure fills the bill for situations like this, where I worry about absolute sizes going all to Dallas on different resolutions/screen sizes, etc.

回答1:


So maybe this is due to floating point math and integral widths.

The ClientSize.Width of a control is an integer. The table layout, regardless if you specify a floating point value, will ultimately need to convert that to something integral.

I threw together an example similar to yours. When I ran the example, I grabbed the control's ClientWidth value, which was 284 for my window's size.

The cell borders are going to be some width and as a guess I said they were 1. So, let's assume 284 minus the 33 for the borders, so that is 251 left over that needs to be split up into 32 columns.

For those narrow columns, the value was 0.025:

0.025 * 251 = 6.275, truncated to 6

So there's an extra 0.275 for each narrow column.

For those wider columns, the value was 0.05:

0.05 * 251 = 12.55, truncated to 12

So there's an extra 0.55 for each wide column.

24 * 6 = 144 width for the 24 narrow columns

8 * 12 = 96 width for the 8 wide columns

Total of 240.

11 left over, so the extra goes to the last column and it ends up being what one would think it would be (6) + the extra (11) and it ends up being, say, 3x as wide as you would expect, due to floating point math.

Anyhow, that's my guess on why it looks that way.




回答2:


The last column's width is always padded to fill the remainder of the space if the total width of the layout panel is not perfectly divisible by the number of columns in the layout panel (when using relative % widths).

Assuming each textbox only needs to contain one character, a layout panel size of 600x240 using the following column width settings displays quite nicely.

labels = 6.5%
textBoxes = 2.0%


来源:https://stackoverflow.com/questions/12011893/why-doesnt-my-tablelayoutpanel-use-all-of-its-size-when-divided-by-percentages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!