I wrote a C# code that makes labels from 0 to 100 in the form. when I run the project, only 0 appears in the form at the 15,156 location. actually, others have been created but they don't move in the x line. for example, 0 is on 15,156 and 1 should be in the 35,156 location and go ahead until the end.
for(int i = 0; i < 101; i++)
{
Label lbl = new Label();
lbl.Name = "lbl" + i.ToString();
lbl.Text = i.ToString();
lbl.Location = new Point(15 + j, 156);
this.Controls.Add(lbl);
j += 20;
}
Add lbl.AutoSize = true before adding lbl to Controls collection.
This way you're telling label to be wide enough pixels to let text be visible. If you omit this, label will be 100 pixels wide (default size) which will cause the first label (the one with Text 0) to hide second label, second label to hide third, third to hide fourth etc... Each label will be wide 100 pixels and text will only occupy first 10 pixels, hidden under previous label.
Also, increase that j variable a bit more (like 50 pixels) and add border to better see what's happening.
Define the size for your controls:
for(int i = 0; i < 101; i++)
{
Label lbl = new Label();
lbl.Name = "lbl" + i.ToString();
lbl.Text = i.ToString();
lbl.Location = new Point(15 + j, 156);
lbl.Size = new Size(65, 15);
this.Controls.Add(lbl);
j += 20;
}
Rererence:
https://support.microsoft.com/en-us/help/319266/how-to-programmatically-add-controls-to-windows-forms-at-run-time-by-u
One problem you're running into is that you're not specifying the size, so all the labels are being created with a width of 100, and the blank space of each label is covering up the text of the one below it. To resolve this, just set Size = new Size(width, height) when creating the control.
Also, when dynamically placing controls next to each other that are all the same size, we can just use the loop variable as a multiplier to determine the Left value for the Location. As long as we choose a Width that is wide enough to fit our longest value, this will work. This is good if you need a fixed column width for each number, but as the numbers get larger, there is less white space between them:
var labelSize = new Size(25, 20);
var padDistance = 2;
for (int i = 0; i < 101; i++)
{
Controls.Add(new Label
{
Name = $"lbl{i}",
Text = i.ToString(),
Size = labelSize,
Location = new Point(i * (padDistance + labelSize.Width), 156)
});
}
If, however, you would rather have all the numbers the same distance apart, then we can AutoSize the controls and use the Right value of the previous control to help determine the current control's Left value. In order to most easily keep track of the previous control, we can add the controls to a List<Label> and then get the previous one using an index in the list (note that we need to special-case the first label, since there is no control before it). In this case, there is equal white space between all the numbers, regardless of the number of characters they have:
var padDistance = 2;
var labels = new List<Label>();
for (int i = 0; i < 101; i++)
{
// For all but the first control, get the 'Right' value of the previous control
int left = (i == 0) ? padDistance : labels[i - 1].Right + padDistance;
labels.Add(new Label
{
Name = $"lbl{i}",
Text = i.ToString(),
AutoSize = true,
Location = new Point(left, 156)
});
Controls.Add(labels[i]);
}
if i understood you correctly try and feedback please i can help.
Vertical
int j = 5;
for (int i = 0; i < 101; i++)
{
Label lbl = new Label
{
Name = "lbl" + i.ToString(),
Text = "lbl " + i.ToString(),
Location = new Point(10, 10 + j),
Size = new Size(50, 20)
};
this.Controls.Add(lbl);
j += 20;
}
horizontal
int x = 50; int y = 20;
for (int i = 0; i < 101; i++)
{
Point location = new Point(x, y);
Label lbl = new Label
{
Name = "lbl" + i.ToString(),
Text = "lbl" + i.ToString(),
Location = location,
Width = 30
};
this.Controls.Add(lbl);
x += 40;
}
Related
i'm newbie here and also in c#.
my project is to create a box in grid view.
then when click desired box, i'll get the box coordinate or position and box will change the colour.
when click another box, the previous box colour will change to original.
the box will resize when total size for rows x cols more than panel2 size.
i wanna extend the function of code by add new button NEXT, when click, then next picture box will be highlight and also coordinate will update. how to relate new button with existing picture box?
for (int cols = 0; cols < COLUMNS; cols++)
{
for (int rows = 0; rows < ROWS; rows++)
{
PictureBox newPic = new PictureBox();
newPic.Height = HEIGHT;
newPic.Width = WIDTH;
newPic.BackColor = Color.Maroon;
int x = cols * (HEIGHT + SPACE);
int y = rows * (WIDTH + SPACE);
newPic.Location = new Point(x + SPACE, y + SPACE);
newPic.Click += NewPic_Click;
items.Add(newPic);
this.panel2.Controls.Add(newPic);
}
}
Just for color switching, you only need the PictureBox which has been clicked on. It is stored in the sender parameter.
I you want the coordinates, you need to store some information on the PictureBox. You don't want to specify 50 handlers.
The way I would do is; to make use of the Tag property of a Control.
Your for-loop would be something like:
for (int cols = 0; cols < COLUMNS; cols++)
{
for (int rows = 0; rows < ROWS; rows++)
{
PictureBox newPic = new PictureBox();
newPic.Height = HEIGHT;
newPic.Width = WIDTH;
newPic.BackColor = Color.Maroon;
// instead of the coordinates, store the indices (for col, row)
newPic.Tag = new Point(cols, rows);
// I would use the Width on the cols, instead of the Height.
int x = cols * (WIDTH + SPACE);
int y = rows * (HEIGHT + SPACE);
newPic.Location = new Point(x + SPACE, y + SPACE);
newPic.Click += NewPic_Click;
items.Add(newPic);
this.panel2.Controls.Add(newPic);
}
}
And your handler would be something like:
// a field to store the previous selected picturebox.
private PictureBox _currentPictureBox = null;
private void NewPic_Click(object sender, EventArgs e)
{
// the picturebox which has been clicked, is stored in the sender object, but you need to cast it to a PictureBox.
PictureBox pb = (PictureBox)sender;
// just for the extra use of the Tag.
var location = (Point)pb.Tag;
// location.X Contains the Column index
// location.Y Contains the Row index
// did we have a previous picturebox?
if(_currentPictureBox != null)
{
// change the previous pictureBox back to Maroon
_currentPictureBox.BackColor = Color.Maroon;
}
// change the current to blue
pb.BackColor = Color.Blue;
// store the new one as the current. (so we can revert it)
_currentPictureBox = pb;
}
I haven't tested it, only in a notepad. So there might be some typo's. But I hope you get the idea.
try
{
int txtno = 10;
int Textbox_pointY = 15;
int label_pointY = 15;
int label_pointX = 10;
int Textbox_pointX = 75;
panel1.Controls.Clear();
for (int i = 0; i < txtno; i++)
{ //Lable creation
Label lbl = new Label();
panel1.Controls.Add(lbl);
lbl.Text = "Test_" + i;
lbl.Location = new Point(label_pointX, label_pointY);
label_pointY += 22;
//Text box creating
TextBox a = new TextBox();
panel1.Controls.Add(a);
a.Text = (i + 1).ToString();
a.Location = new Point(Textbox_pointX, Textbox_pointY);
//panel1.Show();
Textbox_pointY += 22;
//label_pointY += 5;
}
}
catch (Exception)
{
MessageBox.Show(e.ToString());
}
When dynamically generate label and enter code heretext box in winform c# Label overlaps over textbox .I need to keep text box closely to label text .I have added my code here .
Set AutoSize to false and specify labels' Width explicitly:
int txtno = 10;
int label_pointY = 15;
int label_pointX = 10;
int Textbox_pointX = 75;
// Don't do this: it just removes conrols from the panel,
// but does't free resources (and you have resource leakage)
// panel1.Controls.Clear();
// If you want to get rid of all controls on the panel1 (i.e. dispose them)
// do it like this:
for (int i = panel1.Controls.Count - 1; i >= 0; --i)
panel1.Controls[i].Dispose();
for (int i = 0; i < txtno; i++) {
Label lbl = new Label() {
Parent = panel1,
Text = "Test_" + i,
Location = new Point(label_pointX, label_pointY),
AutoSize = false,
Width = Textbox_pointX - label_pointX,
};
TextBox box = new TextBox() {
Parent = panel1,
Text = (i + 1).ToString(),
Location = new Point(Textbox_pointX, label_pointY)
};
label_pointY += Math.Max(box.Height, lbl.Height);
}
I am trying to add a picturebox control to a panel which is created at runtime.
It is for a chess game I am working on. I want to add a picture box to each panel , an assigning the image to the control later. Here is what I have so far:
//Sets the number of rows on the chess board
for (int i = 0; i < 8; i++)
{
//Set the number of columns on the board
for (int j = 0; j < 8; j++)
{
ChessSquare sq = new ChessSquare(((char)(65 + i)).ToString(), 7- j);
sq.Color = (i + (j % 2)) % 2 == 0 ? Color.Black : Color.White;
Panel p = new Panel()
{
Size = new Size(blockSize, blockSize),
BackColor = sq.Color,
Tag = sq,
Location = new Point(blockSize * i + 15, blockSize * j + 15),
BackgroundImageLayout = ImageLayout.Stretch
};
p.MouseEnter += new EventHandler(squareMouseEnter);
p.MouseLeave += new EventHandler(squareMouseLeave);
p.Click += new EventHandler(squareMouseClick);
chessBoardPanels[i, j] = p;
groupBox1.Controls.Add(p);
}
}
//SetUp Board
SetUpBoad Setup = new SetUpBoad();
SetUpBoad(chessBoardPanels);
Since you already put the Panels into the panel-array (?)
chessBoardPanels[i, j] = p;
You can add the PictureBoxes either now or later..:
PictureBox pb = new PictureBox ();
pb.Size = ..
pb.BackColor = Color.Transparent;
chessBoardPanels[i,j].Controls.Add(pb);
To access them later you can cast their first Control to PictureBox:
PictureBox pb = (PictureBox)chessBoardPanels[i,j].Controls[0];
pb.Image = aQueenImage;
If you want to add a PictureBox only where a piece is you need to do checks:
if (chessBoardPanels[i,j].Controls.Count > 0)
{
PictureBox pb = (PictureBox)chessBoardPanels[i,j].Controls[0];
pb.Image = aQueenImage;
}
To move a piece from <i1,j1> to <i2, j2> you do as expected:
chessBoardPanels[i1,j1].Controls[0].Parent = chessBoardPanels[i2,j2];
I notice that you are hooking up mouse events. If you want to use them to move the pieces, remember that transparency will not work for overlapping controls in Winforms and so while a piece-Box is crossing Panels it will not have working tranparency around the Image.
While the pBox is nested in a Panel all is well but to move it you would have to first make it a child of the parent of those panels and only add it to the target Panel upon MouseUp; the coordinate corrections can be solved but the tranparency, if you need it, will be a bigger problem..
The usual advice it to consider drawing at least those board squares and maybe even the pieces onto a base board-Panel (or board-PictureBox)
I would like to display 13 pictureBox, however, it ends up with only the last one visible.
So I was wondering if I did it in a wrong way.
The following code get image from resources folder.
var testP = new PictureBox();
for (int i = 0; i < 13; i++)
{
testP.Width = 65;
testP.Height = 80;
testP.BorderStyle = BorderStyle.None;
testP.SizeMode = PictureBoxSizeMode.StretchImage;
test[i] = getImage(testP, testPTemp[i]);
}
The following code is trying to display 13 pictureBox with shifting location.
These two codes segments should be able to perform the action.
test = new PictureBox[13];
for (var i = 0; i < 13; i++)
{
test[i].Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + testTemp[i]);
test[i].Left = 330;
test[i].Top = 500;
test[i].Location = new Point(test[i].Location.X + 0 * displayShift, test[i].Location.Y);
this.Controls.Add(test[i]);
}
Here is the getImage()
private PictureBox getImage(PictureBox pB, string i) // Get image based on the for loop number (i)
{
pB.Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + i); // Get the embedded image
pB.SizeMode = PictureBoxSizeMode.StretchImage;
return pB;
}
I'm pretty sure there are all PictureBox Controls but they have all the same location so they are lying above each other. That's why only the last one is visible to you.
I think you should replace the 0 with the i variable.
test[i].Location = new Point(test[i].Location.X + i * displayShift, test[i].Location.Y); this.Controls.Add(test[i]);
It's hard to tell the exact problem based off the code you've provided. One possible issue could be that when you are creating the PictureBoxes you only create a single instance before the for loop and then fill the array with references to that instance. Another possibility is that when you're calculating the X position of the controls, you're multiplying by 0 which will always result in 0 (meaning all the controls are at location 330).
Below is code that will achieve basically what you're trying but without all your code I can't give you a more specific example.
In Your Class
const int PICTURE_WIDTH = 65;
const int PICTURE_HEIGHT = 85;
Inside You Function
//Loop through each image
for(int i = 0; i < testTemp[i].length; i++)
{
//Create a picture box
PictureBox pictureBox = new PictureBox();
pictureBox.BorderStyle = BorderStyle.None;
pictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
//Load the image date
pictureBox.Image = (Image)Properties.Resources.ResourceManager.GetObject("_" + testTemp[i]);
//Set it's size
pictureBox.Size = new Size(PICTURE_WIDTH, PICTURE_HEIGHT);
//Position the picture at (330,500) with a left offset of how many images we've gone through so far
pictureBox.Location = new Point(330 + (i * PICTURE_WIDTH), 500);
//Add the picture box to the list of controls
this.Controls.Add(pictureBox);
}
If you need to keep a list of the picture boxes, just create a new list before the loop and add each pictureBox to the list inside the loop. If the control/window you're adding these PictureBoxes to needs to scroll left or right to see all the images set the AutoScroll property to true.
I have a problem with charts in my application. I want to use charts to display histograms of pictures. I want to add a gradient rectangle under chart with colors from black to R/G/B/White, so I draw it as Background Image of each chart. When values on AxisY ar greater then 1k everything is fine, but when those values have less then 4 digits there is a problem screen. Anyone know how to prevent extension of AxisX?
Init charts:
for(int i = 0; i < 3; i++)
{
ca = new ChartArea();
ca.AxisX.Interval = 1D;
ca.AxisX.IntervalOffsetType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
ca.AxisX.LabelAutoFitStyle = System.Windows.Forms.DataVisualization.Charting.LabelAutoFitStyles.WordWrap;
ca.AxisX.MajorGrid.Enabled = false;
ca.AxisY.MajorGrid.LineColor = System.Drawing.Color.DarkGray;
ca.BackColor = System.Drawing.Color.Transparent;
ca.BackSecondaryColor = System.Drawing.Color.Transparent;
ca.BorderWidth = 0;
ca.Name = "ChartArea" + i.ToString();
ca.AxisY.LabelAutoFitStyle = LabelAutoFitStyles.DecreaseFont;
ca.AxisX.Minimum = 0;
ca.AxisX.Interval = 256;
ca.AxisY.IntervalAutoMode = IntervalAutoMode.VariableCount;
s = new Series();
s.BorderWidth = 0;
s.ChartArea = "ChartArea" + i.ToString();
s.IsVisibleInLegend = false;
s.Name = "Series" + i.ToString(); ;
s.Color = Colors[i];
s["PointWidth"] = "1";
HistCharts[i] = new Chart();
HistCharts[i].Anchor = AnchorStyles.Top | AnchorStyles.Right;
HistCharts[i].BackColor = Color.Transparent;
HistCharts[i].BackgroundImageLayout = ImageLayout.None;
HistCharts[i].BorderlineWidth = 0;
HistCharts[i].ChartAreas.Add(ca);
HistCharts[i].Location = new System.Drawing.Point(405, (i + 3) * Form.Height / 6 - 28);
HistCharts[i].Name = "Chart" + i.ToString();
HistCharts[i].Series.Add(s);
HistCharts[i].Size = new System.Drawing.Size(297, Form.Height / 6 - 27);
HistCharts[i].TabIndex = 6;
HistCharts[i].Text = "chart" + i.ToString();
HistCharts[i].Visible = false;
HistCharts[i].SendToBack();
}
SetChartImage();
for(int i = 0; i < 3; i++)
HistCharts[i].BackgroundImage = HistImages[i];
Set new series and paint:
if(Hists == null)
{
HistCharts[0].Visible = false;
HistCharts[1].Visible = false;
HistCharts[2].Visible = false;
UpdateStatTimer(Time);
return;
}
HistCharts[0].BackgroundImage = HistImages[Hists.Length > 1 ? 1 : 0];
if(Hists[0].SequenceEqual(Hists[1]) && Hists[0].SequenceEqual(Hists[2]))
{
HistCharts[0].Series[0].Color = Color.Black;
HistCharts[0].BackgroundImage = HistImages[0];
HistCharts[0].Visible = true;
HistCharts[1].Visible = false;
HistCharts[2].Visible = false;
}
else
{
HistCharts[0].Series[0].Color = Color.Red;
HistCharts[0].BackgroundImage = HistImages[1];
HistCharts[0].Visible = true;
HistCharts[1].Visible = true;
HistCharts[2].Visible = true;
}
int Max = 0;
for(int i = 0; i < 3; i++)
{
HistCharts[i].Series[0].Points.Clear();
HistCharts[i].ChartAreas[0].AxisY.Maximum = Double.NaN;
for(int j = 0; j < Hists[i].Length; j++)
HistCharts[i].Series[0].Points.AddXY(j + 0.5, Hists[i][j]);
HistCharts[i].Update();
if(HistCharts[i].ChartAreas[0].AxisY.Maximum > Max)
Max = (int) HistCharts[i].ChartAreas[0].AxisY.Maximum;
}
if(StatisticsItemCheck.Checked == false)
{
for(int i = 0; i < 3; i++)
HistCharts[i].ChartAreas[0].AxisY.Maximum = Max;
}
if all Hists are equal Green and Blue histograms are invisible and Red Histogram becomes GrayScale Histogram
This is not really about scaling..:
The reason your images don't always align with the Y-Axis is that the Y-Axis legend takes more or less room in various cases. This make the inner plot area move to the right and your carefully aligned image doesn't fit anymore.
When the Y-Axis moves to the right the whole plotarea shrinks, at least if the default vlaues of Auto are still valid for the various elements..
The simplest workaround is to set the position from Auto to a fixed value that suits all your data:
chart1.ChartAreas[0].InnerPlotPosition.X = someValue;
Note that all element position values are in percent of the whole chart! So maybe you will want to modify it upon resizing the chart..? As you have noticed, you also have to resize you images..
To find a good value you can use the debugger to see which are the current ones in both of your cases and pick the larger one and then some extra for safety..
In the same veign you may want to get better control over the format, i.e. the number of digits on your y-axis label values, maybe like this..:
chart1.ChartAreas[0].AxisY.LabelStyle.Format = "0.00"; // some formatstring
Update:
To make use of the system's AutoScaling during(after a resize, you can use this workaround:
First set the Auto on and copy the resulting Elementposition. Then use those values to create a new one under control:
int LeftEdge = yourValue;
chart1.ChartAreas[0].InnerPlotPosition.Auto = true;
ElementPosition EP = chart1.ChartAreas[0].InnerPlotPosition;
chart1.ChartAreas[0].InnerPlotPosition =
new ElementPosition(LeftEdge, EP.Y, EP.Height, 100 - LeftEdge);