Here is my question:
Im making a booking cinema system in c#, windows form
Let's say i have 5 columns of 5 rows of pictureboxes that on form load get their value, avaliable or not from the database.
The user then click on the seat he wants (and the image of the pictuebox change) and press a submit button.
How i can check the image of every picturebox (to determine if he want this seat or not) together?
I can do something like this
if (picturebox11.image=="seatchecked"){seats[]+=11;}
if (picturebox12...
But im wondering if there is another faster way to do it. (the position of the pictureboxes is fixed if that helps)
I have done this so far:
private void button1_Click(object sender, EventArgs e)
{
List<PictureBox> pb = new List<PictureBox>();
pb.Add(seat11);
pb.Add(seat12);
pb.Add(seat13);
pb.Add(seat14);
pb.Add(seat15);
pb.Add(seat21);
pb.Add(seat22);
pb.Add(seat23);
pb.Add(seat24);
pb.Add(seat25);
pb.Add(seat31);
pb.Add(seat32);
pb.Add(seat33);
pb.Add(seat34);
pb.Add(seat35);
for (int i = 0; i < 20; i++) {
pb[i].Click += pictureBox_Click;
}
}
void pictureBox_Click(object sender, EventArgs e)
{
this.pictureBox.Image = ArgyroCinema.Properties.Resources.seatred;
}
Store each PictureBox in a list and iterate through them. Also, when the user selects/deselects a seat, change the Tag property of the PictureBox as, at the moment, you're trying to compare a string to an Image (picturebox11.Image returns an Image object).
List<PictureBox> pb = new List<PictureBox>();
pb.Add(pictureBox1);
pb.Add(pictureBox2);
//etc..
Alternatively, you can use the methods suggested here to get all PictureBox objects in your form to save you having to type it out above.
Then just iterate through them and read their Tag property. In this case I've used true to represent that they want the seat but Tag is an object type, so you can use whatever type you like.
foreach(PictureBox p in allPictureBoxes)
{
if((bool)p.Tag == true)
{
//seat wanted
}
else
{
//seat not wanted
}
}
Update from comments
void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = sender as PictureBox;
if(pb != null)
pb.Image = ArgyroCinema.Properties.Resources.seatred;
}
Related
I'm creating a simple game where a melody is played, and buttons that corresponds to notes are supposed to be highlighted.
Then the user is to push the button, and during each click the buttons are to highlighted again. I would like to place all the buttons in the GUI graphically.
Can I add a highLight method to the buttons in the GUI? I know I probably could create a new class that ineherits from some button class and create the buttons in the code but I would prefer to do it graphically.
What is the neatest way to handle the button outputs? I know I could paste in code for each button like
private void button_withIndexA(object sender, EventArgs e)
{
checkIfThisNoteWasCorrect();
highLightThisButton();
setHighLightOffForAllOtherButtons();
}
However, I think it would be neater to collect all buttons in some sort of container class and make a function like
class buttonArrayHandler
{
/*constructors etc*/
private void someButtonWasClicked(object sender)
{
/*Check which button was clicked, and do stuff accordingly*/
}
}
However I don't know how to do that. Suggestions?
You could change the button colors to create a highlight effect, but if it's a game you can use images / graphics for buttons, and swap them to another graphic when clicked.
When you double click on a button / graphic / control, by default it creates a method and links it to the click action for you. Instead click on each control, then the little lightning icon, and under the click action, pick the same method for all of them.
Then in your method cast the object sender to get the original control, for example:
var clickedButton = (Button)sender;
Where (Button) may be (Graphics) or whatever type of control you used as a button.
EDIT:
If you need to access a group of controls, you can either keep a global list of names at the top of the form and loop through them:
public List<string> buttonList = new List<string>() { "button1", "button2" };
void SomeMethod()
{
foreach (var controlName in buttonList)
{
this.Controls[controlName].Text = "TEST";
}
}
Or use a fixed name and number range:
void SomeMethod()
{
for (int i = 1; i <= 2; i++)
{
this.Controls["button" + i].Text = "TEST";
}
}
I would recommend adding the buttons programatically just like Carlos487 mentioned, here is the code segment that I made and could work to your advantage:
public Form1()
{
InitializeComponent();
int topMod = 0;
for (int i = 0; i < 5; i++)
{
MakeButton(i,topMod);
topMod += 20;
}
}
public void MakeButton(int index, int margin)
{
Button currentButton = new Button();
currentButton.Text = "Note" + index;
currentButton.Top += margin;
currentButton.Click += OnButtonClick;
panel1.Controls.Add(currentButton);
}
public void OnButtonClick(object sender, EventArgs e)
{
//checkIfThisNoteWasCorrect();
//highLightThisButton();
//setHighLightOffForAllOtherButtons();
MessageBox.Show("My Action was activated!");
}
As you can see you can place the common functions within the OnButtonClick method like I did here, giving all of the buttons the same event sequence. If you do not want to go through the whole process of programming buttons then you could also just do this:
currentButton.Click += OnButtonClick;
I am trying to do the following action with pictureboxes:
Search for a picturebox that has a special image, my method for this returns a number of the box that has this image.
Example:
if (picturebox1.Tag == "special") {
return 1; //returns value 1 as in picturebox1 contains it.
}
Now when I click on pictureBox2 I want it to switch with the picturebox that contains the special picture (I have a total of 10 pictureboxes with pictures, only one box contains a special one)
Click event on picturebox2:
private void pictureBox2_Click(object sender, EventArgs e)
{
performSwitch(2); //2 meaning picturebox "2"
}
Method it calls:
public void performSwitch(int pictureBoxWaarde)
{
switch (pictureBoxWaarde)
{
case 2:
pictureBox10.Image = pictureBox2.Image; //else picture overwrites
pictureBox2.Image = pictureBox1.Image;
pictureBox1.Image = pictureBox10.Image;
break;
}
}
This code works however I dont want to make TONS of if-else statements for every combination there is.. So to make it 'smart' I will need something like this:
public void performSwitch(int pictureBoxWaarde)
{
switch (pictureBoxWaarde)
{
pictureBox10.Image = pictureBox2.Image; //else picture overwrites
pictureBox2.Image = pictureBox"+findBlackBox+".Image;
pictureBox"+findBlackBox()+".Image = pictureBox10.Image;
break;
}
}
If this would work it would get the special box number and work without the need of lots of if-else. How would I do this?
I'm not sure whether I fully understand what you're trying to achieve, but you can always find a control by its name.
Let's say that you have a variable string m_specialPictureBoxName; that always contains the name of the current special picture box, you could do the following:
public void performSwitch(int pictureBoxWaarde)
{
// Get current special picture box
PictureBox currentSpecial = this.Controls.Find(m_specialPictureBoxName, true) as PictureBox;
// Get new special picture box
m_currentPictureBoxName = String.Format("pictureBox{0}", pictureBoxWaarde);
PictureBox clicked = this.Control.Find(m_currentPictureBoxName, true) as PictureBox;
// Swap images
Image temp = currentSpecial.Image;
currentSpecial.Image = clicked.Image;
clicked.Image = temp;
}
Also I'm swapping the image without using the temporary pictureBox10 assignment - I'm not sure whether you want pictureBox10 to get the image. If you do, you can replace it with your previous code instead of the Image temp = ...line.
Assign all the PictureBox event handlers to a single method.
Write the method like this
private void ApictureBox_Click(object sender, EventArgs e)
{
var clickedPicture = sender as PictureBox;
// iterate through all picture controls of the current form
for (var pic in this.Controls.OfType<PictureBox>())
if (pic.Tag=="special")
{
var temp = clickedPicture.Image;
clickedPicture.Image = pic.Image;
pic.Image = temp;
}
}
For the first step, you can either do it manually, or use a similar loop to assign the event handlers in the form constructor.
For a school project, I have to make a table reservation system,
I made the following (just a small part).
PictureBox[] pb = new PictureBox[70] { pictureBox1, pictureBox2, pictureBox3,etc.. };
foreach (PictureBox p in pb)
{
p.BorderStyle = BorderStyle.Fixed3D;
p.BackColor = Color.White;
p.MouseEnter += new EventHandler(mouseOn);
p.MouseClick += new MouseEventHandler(mouseClick);
}
private void mouseOn(object sender, EventArgs e)
{
((PictureBox)sender).BackColor = Color.Green;
}
private void mouseClick(object sender, EventArgs e)
{
reservationForm rf = new reservationForm();
rf.ShowDialog();
}
I chose for pictureboxes to represent the tables, the default BackColor is white, and when the mouse enters the BackColor turns green.
When you click on 1 of those PictureBoxes my reservationForm will open, this is where you can further fill in the details to book the table.
but the part where I get stuck now is that I don't know on my reservation form which PictureBox I clicked, so I need to get something like the index of the PictureBox array.
How do I fix this?
You know how to do it! :)
You're already doing it correctly on the mouseOn event handler. Just do the same cast of the sender parameter.
private void mouseClick(object sender, EventArgs e)
{
PictureBox clickedBox = (PictureBox)sender;
reservationForm rf = new reservationForm();
rf.ShowDialog();
}
If you need the index, you can use Array.IndexOf, assuming your pb array is a class level variable and not a method local.
int index = Array.IndexOf(pb, clickedBox);
Check sender
private void mouseClick(object sender, EventArgs e)
{
PicterBox pb = (PicterBox)sender;
...
}
In your "MouseOn" you already use (PictureBox)sender to get a reference to the picturebox.
Then you can walk through the array to compare the picturebox at a specific index to the clicked one. When you have a match, you found the index.
var clicked = (PictureBox)sender;
int index = 0;
while (index < pb.Length && pb[index] != clicked) index = index+1;
// now index is either 70 (if not found) or the position you want (0..69)
Maybe you can set in for cycle a name at each picturebox equals at the corrispondent index. So in the listener u can use
PicterBox pb = (PicterBox)sender;
and get the name that is the index.
You have many options. I will suggest some of them:
Create a public class variable or property and store the current selected Picturebox on the click event, so you can access it from the form;
Pass in the Picturebox for the constructor of the form (creating a constructor that accepts this info and stores it in an internal variable).
I want to use a wheel to change (for example) 30 buttons' background image each time a form loads.
I cannot use this:
for(int i=1;i<=30;i++)
{
button i .backgroundimage=image.fromfile("URL");
}
What should I do?
There are many possible interpretations of your problem. Why can't you use your code? There are also different solutions for your problem.
As example:
public Form1() // Constructor
{
InitializeComponent(); // Ensure all controls are created.
List<Button> buttons = new List<Button>(30);
buttons.Add(mybutton1)
buttons.Add(mybutton2)
// Go futher with all your buttons.
}
private void Form1_Load(object sender, System.EventArgs e) // Create a load event
{
foreach(Button button in buttons)
{
button.BackgroundImage = Image.FromFile(path);
// Note: The file remains locked until the Image is disposed!
}
}
Well you could use something like this assuming this code executes in a Form_Load and the buttons Parent control is your form. Have in mind that you should supply the real path to your image that you want to set as a background image
string path = "rootNameOfTheImage";
int counter = 0;
foreach(Control ctrl in this.Controls)
{
if(ctrl is Button)
{
Button btn = (Button)ctrl;
if(/* test if this button should be used */)
{
btn.BackgroundImage=Image.FromFile(path + counter++.ToString() + ".jpg");
}
}
}
I'm trying to make something of a Tile-Map editor in C# using picture-boxes (the simplest way i could think to throw tiles into a form)
The code that Generates the picture boxes is:
public void Generate_Tiles(int width, int height)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
System.Windows.Forms.PictureBox picturebox = new PictureBox();
picturebox.BackColor = SystemColors.ActiveCaption;
picturebox.Cursor = Cursors.Cross;
picturebox.Location = new System.Drawing.Point((x*32) + 4, (y*32) + 4);
picturebox.Name = x+y+"tile";
picturebox.Size = new System.Drawing.Size(32, 32);
picturebox.TabIndex = 0;
picturebox.TabStop = false;
picturebox.Click += new System.EventHandler(TileBox_Clicked));
map.Controls.Add(picturebox);
}
}
MessageBox.Show("Done");
}
That part works, as long as i use a small number of picture boxes at a time (8 by 8 seems to be the maximum that it wants to display in a decent amount of time)
I want to perform some action when the user clicks on a specified picture-box, which is why i have a onclick method, that's where i run into problems, all the picture-boxes are called... picture-box. As far as i can tell, there's no way for me to tell which picture-box the user clicked.
I will probably need to remake the way the dynamic form works anyway, since i cant get very many picture boxes, but I think the main problem will still be there, as long as i want it to be dynamic (which i do), not all of the tile-maps will be the same size.
Ive never done anything like this, and I've looked for ways to override the onclick event... which i couldn't find, and i couldn't find a good tile-engine that's up to date to use (except for XNA, but that's a little over the top for a simple tile-editor, i think)
Im likely going in the opposite direction then what i need to be doing.
The sender in your event handler will be the PictureBox which was clicked.
void TileBox_Clicked(object sender, EventArgs e)
{
PictureBox pictureBox = sender as PictureBox;
if(pictureBox != null)
{
//do stuff with your pictureBox
}
}
Can't you just cast the sender object to a PictureBox in your event handler, and work with that?
The first parameter in your event handler is the clicked control (which will be the PictureBox.
private void pictureBox1_Click(object sender, System.EventArgs e)
{
PictureBox pb = (PictureBox)sender;
// ...
}
I've taken this approach with a map tile editor as well. As others have said, you can use the sender parameter and cast it to a PictureBox to get the PictureBox object that was clicked. But I think you'll find (you probably already have) that a decent map size will really slow things down.
You might reconsider XNA. It seems complicated, and it's not as easy to get something working as just generating a bunch of PictureBox objects. But it's fast, and it's you can get a 2D map being displayed fairly quickly. You can also extend it easier, for example if you want your map to have different editable layers (terrain, etc.).
There are actually lots of ways to do this. I think the easiest is to use the sender of your event handler, which will point you back to the clicked button:
private void PictureBox_Click(object sender, EventArgs e)
{
var box = sender as PictureBox;
if (box != null)
{
//...
You can also create and add event handlers dynamically, which is an interesting option:
//...
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
System.Windows.Forms.PictureBox picturebox = new PictureBox();
pictureBox.Click += new Action<object, EventArgs>(
(sender, e) => { doStuff(pictureBox); }
);
In the above code, doStuff gets pictureBox as a parameter, so it knows which object it's supposed to work on.