My program is quite straightforward in concept - it allows the user to take points during bowling tournaments, as well as show players the results through the scoreboard.
There is the form of the account in which they enter the points, and the form of the scoreboard, which shows the ratings of the players, by dividing. The board runs in a different thread than the main program.
The scoreboard consists of a TableLayoutPanel, which I manipulate programmatically to present a table of the results that need to be shown. My problem is that it takes a lot of time to render a table (especially for a long list of players). The user experience of viewing a table rendering is poor.
I tested the rendering speed of text fields, labels and boxes to reduce the load; text fields won, so I changed the label labels to text fields ... but this is still not enough.
There is a lot to watch, but if anyone knows how I could further accelerate the rendering of the scoreboard, I would be all ears / eyes.
Here my process is broken.
The calling method (called every 15 seconds by a timer):
private void switchBoard()
{
night = nights.GetNight(nightID);
NightDay = night.Night_Date.ToString("ddd");
dtDivisions = scoreBoard.roll_display(dtDivisions);
DataRow[] drs = dtDivisions.Select("showing = 1");
DataRow dr = drs[0];
lbl_title.Top = 30;
lbl_title.Text = (string)dr["title"] + " Qualifying - " + NightDay;
lbl_title.Width = this.Width;
lbl_title.TextAlign = ContentAlignment.MiddleCenter;
int Cols = games.GetCountGamesForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision) + 3;
int Rows = players.GetCountPlayersForTourNightByDivision(TourID, nightID, scoreBoard.ShowDivision) + 1;
GenerateTable(Cols, Rows);
GenerateHeaders(tourID, nightID);
GenerateScoreLabels(tourID, nightID, scoreBoard.ShowDivision);
}
Creating a table:
private void GenerateTable(int columnCount, int rowCount)
{
this.tblPnlScoreboard.Controls.Clear();
this.tblPnlScoreboard.ColumnStyles.Clear();
this.tblPnlScoreboard.RowStyles.Clear();
this.tblPnlScoreboard.ColumnCount = columnCount;
this.tblPnlScoreboard.RowCount = rowCount;
for (int x = 0; x < columnCount; x++)
{
if(x==0)
{
this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute,30));
}
else if(x==1)
{
this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
}
else if(x==columnCount-1)
{
this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
}
else
{
this.tblPnlScoreboard.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, (this.tblPnlScoreboard.Width - 130) / columnCount));
}
for (int y = 0; y < rowCount; y++)
{
if (x == 0)
{
if(y==0)
{
this.tblPnlScoreboard.RowStyles.Add(new RowStyle(SizeType.Absolute, 50));
}
else
{
this.tblPnlScoreboard.RowStyles.Add(new RowStyle(SizeType.AutoSize));
}
}
}
}
}
Create Headers:
private void GenerateHeaders(int TourID, int NightID)
{
DataTable dtPlayers = players.GetPlayersForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision);
int Row = 1;
foreach (DataRow dr in dtPlayers.Rows)
{
Label lblPlayer = new Label();
lblPlayer.Name = dr["ID"].ToString();
lblPlayer.Text = dr["player_name"].ToString();
lblPlayer.BackColor = Color.Transparent;
lblPlayer.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
lblPlayer.TextAlign = ContentAlignment.MiddleLeft;
lblPlayer.AutoSize = true;
lblPlayer.Height = tblPnlScoreboard.GetRowHeights()[Row];
this.tblPnlScoreboard.Controls.Add(lblPlayer, 1, Row);
Label lblTotal = new Label();
lblTotal.Name = "lbl_total";
lblTotal.Text = dr["Total"].ToString();
lblTotal.BackColor = Color.Transparent;
lblTotal.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
lblTotal.TextAlign = ContentAlignment.MiddleLeft;
lblTotal.AutoSize = true;
lblTotal.Height = tblPnlScoreboard.GetRowHeights()[Row];
this.tblPnlScoreboard.Controls.Add(lblTotal, tblPnlScoreboard.ColumnCount, Row);
Row++;
}
Label lblTotals = new Label();
lblTotals.Height = tblPnlScoreboard.GetRowHeights()[0];
lblTotals.Name = "lbl_total";
lblTotals.Text = "Totals";
lblTotals.BackColor = Color.Transparent;
lblTotals.ForeColor = Color.White;
lblTotals.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
lblTotals.TextAlign = ContentAlignment.MiddleCenter;
lblTotals.AutoSize = true;
lblTotals.Anchor = (AnchorStyles.None);
this.tblPnlScoreboard.Controls.Add(lblTotals, this.tblPnlScoreboard.ColumnCount-1, 0);
DataTable dtGames = games.GetGamesForTourNightByDivision(tourID, nightID, scoreBoard.ShowDivision);
int Col = 2;
foreach (DataRow dr in dtGames.Rows)
{
Label lblGame = new Label();
lblGame.Width = this.tblPnlScoreboard.GetColumnWidths()[Col];
lblGame.Height = tblPnlScoreboard.GetRowHeights()[0];
lblGame.Name = dr["ID"].ToString();
lblGame.Text = dr["disp_name"].ToString().Replace("Game ", "");
lblGame.BackColor = Color.Transparent;
lblGame.ForeColor = Color.White;
lblGame.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
lblGame.TextAlign = ContentAlignment.MiddleCenter;
lblGame.Anchor = (AnchorStyles.None);
this.tblPnlScoreboard.Controls.Add(lblGame, Col, 0);
Col++;
}
}
Finally, creating ratings:
private void GenerateScoreLabels(int TourID, int NightID, int DivID)
{
Players players = new Players();
DataTable dtScores = players.GetPlayerGamesIDsForTourNightByDivision(TourID, NightID, scoreBoard.ShowDivision);
Divisions Divs = new Divisions();
DataTable dtColors = Divs.GetDivisionScoreboardColors(DivID);
foreach (DataRow dr in dtScores.Rows)
{
int col = FindX((int)dr["fk_game_id"]);
int row = FindY((int)dr["fk_player_id"]);
if (col > 0 && row > 0)
{
TextBox txt_score = new TextBox();
txt_score.Name = dr["ID"].ToString();
txt_score.Text = dr["score"].ToString();
txt_score.ForeColor = Color.Black;
txt_score.Font = new Font("Microsoft Sans Serif", 25, FontStyle.Bold);
txt_score.Width = this.tblPnlScoreboard.GetColumnWidths()[col];
txt_score.Height = tblPnlScoreboard.GetRowHeights()[0];
if(row % 2 == 0)
{
txt_score.BackColor = Color.FromArgb((int)dtColors.Rows[0]["sb_even_row_color"]);
}
else
{
txt_score.BackColor = Color.FromArgb((int)dtColors.Rows[0]["sb_odd_row_color"]);
}
txt_score.BorderStyle = BorderStyle.None;
txt_score.TextAlign = HorizontalAlignment.Center;
txt_score.Anchor = (AnchorStyles.Top);
this.tblPnlScoreboard.Controls.Add(txt_score, col, row);
ttmr_switch.Enabled = true;
}
}
}
In the CellPaint event for TableLayoutPanel, I have the following processes:
private void tblPnlScoreboard_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = e.CellBounds;
SolidBrush sb = GetBrushFor(e.Row, e.Column, scoreBoard.ShowDivision);
g.FillRectangle(sb, r);
sb.Dispose();
}
Choice of colors:
private SolidBrush GetBrushFor(int row, int column, int DivID)
{
DataTable dt_colors = divisions.GetDivisionScoreboardColors(DivID);
if (row == 0)
{
SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_column_header_color"]));
return brush;
}
else
{
if(row % 2 == 0)
{
SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_even_row_color"]));
return brush;
}
else
{
SolidBrush brush = new SolidBrush(Color.FromArgb((int)dt_colors.Rows[0]["sb_odd_row_color"]));
return brush;
}
}
}