I am drawing set of Labels dynamically and i want to remove them. I am using the same button to remove and add new Labels. The labels are drawn randomly with random coordinates. But, when i am pressing the button the old Labels should me removed and the new Labels appeared. But, what I am having is that the new labels appears and old Labels appears but empty labels. I want them to be remove at all. See the picture:
//Global Intialization
int xCoor;
int yCoor;
//send the random method
Random coor = new Random();
private void btnRun_Click(object sender, EventArgs e)
{
//Removing the Labels after drawing them in the picBox
this.RemoveOldLabels();
//to draw the Labels rendomely.
for (int x = 1; x <= 25; x++)
{
for (int i = 0; i < 1; i++)
{
//Get the Coordinates for X,Y
xCoor = coor.Next(0, 750);
yCoor = coor.Next(0, 500);
//Start Greating the Labels
Label nodeLabel1 = new Label();
nodeLabel1.Text = x + " : " + xCoor + "," + yCoor;
nodeLabel1.AutoSize = true;
nodeLabel1.Location = new Point(xCoor + 10, yCoor + 5);
nodeLabel1.ForeColor = System.Drawing.Color.Red;
nodeLabel1.BackColor = Color.LightBlue;
//Draw the Labels in the PicBox
this.picNodes.Controls.Add(nodeLabel1);
}
}
}
//this to remove the Labels
private void RemoveOldLabels()
{
List<Label> LabelsToRemove = new List<Label>();
foreach (var x in this.picNodes.Controls)
{
if (x.GetType() == typeof(System.Windows.Forms.Label))
{
LabelsToRemove.Add((Label)x);
}
}
It looks like RemoveOldLabels() is finding the labels, but not actually removing them.
Try getting all "Label" controls, then disposing of them (which should also remove them from the collection and make them disappear off the form).
foreach (var label in picNodes.Controls.OfType<Label>().ToList())
label.Dispose();
Your remove old labels logic does not do anything. It simply adds the labels to a list and that's it.
You need to remove those controls from picNodes as below:
private void RemoveOldLabels()
{
List<Label> LabelsToRemove = new List<Label>();
foreach (var x in this.picNodes.Controls)
{
if (x.GetType() == typeof(System.Windows.Forms.Label))
{
LabelsToRemove.Add((Label)x);
}
}
foreach (var label in LabelsToRemove)
{
this.picNodes.Controls.Remove(label);
label.Dispose();
}
}
Related
I have the code that creates a grid of buttons from an array. I need to get their possitions in array on mouse clicked event. Any ideas or links to some other post/articles would be very helpful.
The code for creating the grid:
// Creating buttons array for 5x5 grid
Button[] tiles25 = new Button[25];
// Generating 5x5 button grid
void Spawn5x5Grid()
{
// position of the firts tile
int x = 35, y = 55;
// current tile index
int count = 0;
for (int i = 1; i < 6; i++)
{
for (int j = 1; j < 6; j++)
{
// Adding button to the array
tiles25[count] = new Button()
{
Size = new Size(24, 24),
Location = new Point(x, y)
};
// Adding buttons from array to the form
Controls.Add(tiles25[count]);
count++;
x = x + 24;
}
x = 35;
y = y + 24;
}
lblSize.Text = "5 x 5";
currentGrid = Grids.grid5x5;
}
I suggest scanning tiles25 array in the Click event handler
...
Controls.Add(tiles25[count]);
tiles25[count].Click += (o, ee) => {
Button button = o as Button;
int index = Array.IndexOf(tiles25, button);
//TODO: Put relevant code here: "button" clicked which is at "index" position
};
count++;
x = x + 24;
...
Register an event handler for each of your button click events and then extract the Location property from the sender object:
// Generating 5x5 button grid
void Spawn5x5Grid()
{
// position of the firts tile
int x = 35, y = 55;
// current tile index
int count = 0;
for (int i = 1; i < 6; i++)
{
for (int j = 1; j < 6; j++)
{
// Adding button to the array
tiles25[count] = new Button()
{
Size = new Size(24, 24),
Location = new Point(x, y)
};
// Adding buttons from array to the form
Controls.Add(tiles25[count]);
tiles25[count].Click += Tiles25_Click;
count++;
x = x + 24;
}
x = 35;
y = y + 24;
}
lblSize.Text = "5 x 5";
currentGrid = Grids.grid5x5;
}
private void Tiles25_Click(object sender, EventArgs e)
{
var bt = sender as Button;
MessageBox.Show("X = " + bt.Location.X + "; Y = " + bt.Location.Y);
}
You need to set up an event handler for when the button is clicked. Right now, all you're doing is creating the buttons and adding them to the list of controls at a given position. Now, all you have to add is the event handler for the click event!
//...
// Adding button to the array
tiles25[count] = new Button()
{
Size = new Size(24, 24),
Location = new Point(x, y),
};
tiles25[count] += new EventHandler(this.Tile_Click);
//...
void Tile_Click(Object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
//...
}
Then inside of the Tile_Click() event handler, you can use whatever code necessary to get the position with the clickedButton object.
If I'm not wrong VoidWalker, you are trying to get the position(index) of the item in the source array and not the actual position of the button on screen. If the former case is true read on, for the latter we have some good answers above.
What you need to do is to mark each button with an identifier that would be used to infer the position. A simple yet damn efficient approach.
At the time of creating the button:
// Adding button to the array
tiles25[count] = new Button()
{
Size = new Size(24, 24),
Location = new Point(x, y)
};
// Add the current index to the name field of the Button
tiles25[count].Name = "Grid5-Btn" + count.ToString();
// Adding buttons from array to the form
Controls.Add(tiles25[count]);
Then on button click you can simply do
void Tile_Click(Object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
var index = int(clickedButton.Name.Split("Grid5-Btn")[0]);
//...
}
This way you can add multiple pieces of informatio such as the hierarchy of grids on the page. You can exactly pinpoint which element to access without running any loops, which would be the case with Array.IndexOf
I want to be able to do something like this so that i can just add label then label1 label 2 label3 etc and i cant create an array of new labels or anything since my labels have an image attached to them and have to keep a certain position as well. So making a new label that has some text as a label that wont show up anywhere in particular on my form isn't much use.
List<Label> labels = new List<Label>();
for (int i = 0; i < 10; i++)
{
labels.Add(label + (i.ToString()));
}
You can add Labels to list from Form by name like this :
List<Label> labels = new List<Label>();
for (int i = 0; i < 10; i++)
{
var label =
this.Controls.OfType<Label>().Where(lb => lb.Name == "label" + i).FirstOrDefault();
if (label != null)
labels.Add(label);
}
Here is a Code Sample:
You need to add the labels to the Controls collection of the tab page:
Page2.Controls.Add(CustomLabel[CustomLabel.Count - 1] as Control);
List<Label> customLabels = new List<Label>();
foreach (string ValutaCustomScelta in Properties.Settings.Default.ValuteCustom)
{
Label label = new Label();
label.Location = new System.Drawing.Point(317, 119 + customLabels.Count*26);
label.Parent = Page2;
label.Name = "label" + ValutaCustomScelta;
label.Text = ValutaCustomScelta;
label.Size = new System.Drawing.Size(77, 21);
customLabels.Add(label);
Page2.Controls.Add(label);
}
Have you added the labels by code or by design?
If you added them by code just add them then to the list.
If you added them by design there are two options. They are all on the same container (panel, form, groupbox...) or they are not.
If they are you can:
for each(control ctr in $yourcontainer.controls)
{
if(ctr is Label)
{
labels.add(ctr);
}
}
If they are not in the same container you can add them by hardcode
labels.add(%label1name);
labels.add(%label2name);
labels.add(%label3name);
labels.add(%label4name);
But if they are too much, you can run the code before for each one of the panels
I'm supposed to create a magic square in 2D using Windows Forms Application. It should look like this:
However, the user should be able to decide the size of the square (3x3, 5x5, 7x7, etc). I already wrote the code in a Console Application, but I don't know how to add the 2D graphics.
Somebody already asked this question (How do I put my result into a GUI?), and one of the answers was to use DataGridView, but I'm not sure if that's what I'm looking for, since I can't make it look like the picture.
Any ideas or advice?
You can use a TableLayoutPanel and add buttons to panel dynamically.
If you don't need interaction with buttons, you can add Label instead.
Create square dynamically:
public void CreateSquare(int size)
{
//Remove previously created controls and free resources
foreach (Control item in this.Controls)
{
this.Controls.Remove(item);
item.Dispose();
}
//Create TableLayoutPanel
var panel = new TableLayoutPanel();
panel.RowCount = size;
panel.ColumnCount = size;
panel.BackColor = Color.Black;
//Set the equal size for columns and rows
for (int i = 0; i < size; i++)
{
var percent = 100f / (float)size;
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, percent));
panel.RowStyles.Add(new RowStyle(SizeType.Percent, percent));
}
//Add buttons, if you have your desired output in an array
//you can set the text of buttons from your array
for (var i = 0; i < size; i++)
{
for (var j = 0; j < size; j++)
{
var button = new Button();
button.BackColor = Color.Lime;
button.Font = new Font(button.Font.FontFamily, 20, FontStyle.Bold);
button.FlatStyle = FlatStyle.Flat;
//you can set the text of buttons from your array
//For example button.Text = array[i,j].ToString();
button.Text = string.Format("{0}", (i) * size + j + 1);
button.Name = string.Format("Button{0}", button.Text);
button.Dock = DockStyle.Fill;
//If you need interaction with buttons
button.Click += b_Click;
panel.Controls.Add(button, j, i);
}
}
panel.Dock = DockStyle.Fill;
this.Controls.Add(panel);
}
If you need interaction with buttons
void button_Click(object sender, EventArgs e)
{
var button = (Button)sender;
//Instead put your logic here
MessageBox.Show(string.Format("You clicked {0}", button.Text));
}
As an example, you can call
CreateSquare(3);
Screenshot:
You can create a Form and add a TableLayoutPanel with this property
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.BackColor = Color.Gold;
and this is the result
When you create Row and Column, to fit correctly set the percentage in this way:
After this you can add a Button or Label in each square.
I am trying to make a simple five in a row (gomoku) game for two players using windows forms and c#. I put a picturebox with a picture and stretched it out on the form. Now I want to put labels at all the intersections on the picture board so a user can click them and change their background color to black or white.
How can I make the labels created clickable on the form?
public partial class Form1 : Form
{
int labelCount = 0;
int iteration = 0;
public Form1()
{
InitializeComponent();
Label[] board = new Label[361];
for (int i = 0; i < 361; i++)
{
board[i] = new Label
{
Name = "label" + i,
Height = 55,
Width = 55,
MinimumSize = new Size(55, 55),
Text = "label " + i
};
}
int x = 0;
int y = 0;
foreach (var Label in board)
{
if (x >= 580)
{
x = 0;
y = y + Label.Height + 55;
}
Label.Location = new Point(x, y);
this.Controls.Add(Label);
x += Label.Width;
}
}
}
Should I make a one-dimensional [361] or two-dimensional array[{A,1}, {A,2}....{D,1}] to easily check for a winner? How can I connect it to the created labels so the array data corresponds to the objects on the board?
Well Sorry If don`t understand your question. For the Q.1 to add 361 labels you can try the code below. I hope it will help you.
public int x = 0;
public int y = 0;
private Label[] moku = new Label[361];
private void Form1_Load(object sender, EventArgs e)
{
try
{
for (int i = 0; i < 361; i++)
{
moku[i] = new Label();
moku[i].Parent = pictureBox1;//make the picturebox parent
moku[i].Location = new Point(x, y);
moku[i].Text = "O";
moku[i].Name = "moku" + i;
moku[i].BackColor = Color.Transparent;
pictureBox1.Controls.Add(moku[i]);
y += 55;
if (y >= 361) { x += 55; y = 0; x+=55; }
}
}catch(Exception er)
{
MessageBox.Show(er.ToString());
}
}
I prefer using a 2D array because it's easier if you want to check the surrounding boxes.
Form design:
Full source:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication6
{
public enum Player
{
Empty = 0,
White,
Black
}
public partial class Form1 : Form
{
// initialize board of 5x5
private Player[,] board = new Player[5, 5];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DrawBoard();
}
private void DrawBoard()
{
for (var i = 0; i <= board.GetUpperBound(0); i++)
{
for (var j = 0; j <= board.GetUpperBound(1); j++)
{
// for name and text
var name = string.Format("{0}, {1}", i, j);
var label = new Label()
{
Name = name, // name of label
Size = new Size(55, 55),
BorderStyle = BorderStyle.FixedSingle,
Location = new Point(i * 55, j * 55), // location depends on iteration
Text = name
};
label.Click += ClickLabel; // subscribe the Click event handler
pictureBox1.Controls.Add(label); // add label to a container
}
}
}
// this event handler will handle all the labels click event
private void ClickLabel(object sender, EventArgs e)
{
var label = (Label)sender; // this is the label that you click
var x = Convert.ToInt32(label.Name.Split(',')[0]);
var y = Convert.ToInt32(label.Name.Split(',')[1]);
// change the color
if (radPlayerBlack.Checked)
{
// Player Black
label.ForeColor = Color.White;
label.BackColor = Color.Black;
board[x, y] = Player.Black;
}
else
{
// Player White
label.ForeColor = Color.Black;
label.BackColor = Color.White;
board[x, y] = Player.White;
}
}
}
}
You can check the value of the 2D array for black or white. Here's the value when I QuickWatch it in Visual Studio.
I have a feeling that Im am missing something obvious but:
I have a single row of pictures in a form, in theory the pictures could go on forever. I need a scroll bar so that the user can look at all of the pictures in the row. I know I need to enable auto scroll but I have no idea how to enable it. Can someone tell me how to enable it or something that I am missing?
If it helps this is the code i am using to generate the pictures:
private void imagePalletToolStripMenuItem_Click(object sender, EventArgs e)
{
MyPalletGui.Show();
Dictionary<string,Bitmap> MyPallet = MyImageCollection.ToDictionary();
int xcor = -50;
int ycor = 0;
foreach (Bitmap curtImage in MyPallet.Values){
PictureBox myPicBox = new PictureBox();
xcor += 50;
myPicBox.Location = new Point(xcor, ycor);
myPicBox.Width = 50;
myPicBox.Height = 50;
myPicBox.Visible = true;
myPicBox.Image = new Bitmap(curtImage);
this.MyPalletGui.Controls.Add(myPicBox);
This code will do exactly what you want, it uses the Form as the ViewPort with AutoScroll:
public Form1()
{
InitializeComponent();
PopulatePictures();
}
private void PopulatePictures()
{
this.AutoScroll = true;
string[] list = Directory.GetFiles(#"C:\\Users\\Public\\Pictures\\Sample Pictures", "*.jpg");
PictureBox[] picturebox= new PictureBox[list.Length];
int y = 100;
for (int index = 0; index < picturebox.Length; index++)
{
picturebox[index] = new PictureBox();
this.Controls.Add(picturebox[index]);
picturebox[index].Location=new Point(index * 120, y);
if(x%12 == 0)
y = y + 150;
picturebox[index].Size = new Size(100,120);
picturebox[index].Image = Image.FromFile(list[index]);
}
}