In theory the whole thing I'm trying to accomplish is stupid from object orientated point of view,but I have to do it.
Its an Online game I'm working on.The client has an inventory with items,you know - virtual items.
The server sends the items with their corresponding position in the inventory.
This is how my inventory looks like:
I have 62 panels(each panel represents the room in the inventory).
My problem:When I sort out the virtual items and the corresponding slots they should be placed in,I have to draw them on form.
In theory,If I receive item "C:\a.bmp" in position 4,how do I set panel4.image to be equal to the image?
This is what I'm trying to do:
var data = new byte[6];
... //we receive a packet,data is our buffer
var position = data[4];
Form1.panel + position + .backgroundImage = "bla bla.jpg";
How do call the panels like that?
Turn them into an array instead of having 62 individual variables. Then you can use:
Form1.panels[position].BackgroundImage = "...";
There isn't any designer support for this (that I'm aware of) though - did you create all those panels in the designer? If you can possibly do it programmatically instead, you'll make your life a lot easier (IMO).
Related
Im making a Random Generator with Windows Forms with Images and I use the random pick with resources pictureBox1.Image = Properties.Resources.heart;
Now, the "heart" should get removed from the List, to prevent getting "heart" again.
Here I thought, that I just use int firstCard = randomCard.Next(cards.Count); and I want to use the int firstCard as Properties.Resources.cards[firstCard], because behind Properties.Resources. comes the resource name. But the string doesnt work there, and I dont know how to fix that. Pls help.
Thank you
Pults
Add all your images to a List<Image> - if you have 100 images your list will end up with 100 things
Pick one at random and also remove it. Make the upper bound of random the number of things in the list
//do this once outside the loop that adds images: var r = new Random();
Then the loop that adds images
var x = r.Next(imageList.Count);
var i = inageList[x]; //get the image
imageList.RemoveAt(x); //can't get it again
Note that setting the image of a picture box cannot be done in addition; you'll need multiple picture boxes
Side note, you might find it easier to keep your images in an ImageList (easier to index numerically) - the documentation for it also has some useful/helpful example codes that iteratively draws images into a PictureBox
Also, someone else (maybe doing the same exercise as you :) ) wondered how to get images by string name..
Oh yeah, someone asked the same, didnt find it.
Yea the "ResourceManager.GetObject" is exactly what I needed.
Thanks for the quick response and instant solve!
I have implemented annotation feature which is similar to drawing in VR. Drawing is a Unity trail and its shape depends on its trajectory. This is where real problem comes. We are synchronising the drawing in realtime using PhotonTransformView which syncs world position of the trail. But here is the output. The synchronised drawing looks so different from the original one.
Here is sync configuration code:
public void SetupSync(int viewId, int controllingPlayer)
{
if (PhotonNetwork.inRoom)
{
photonView = gameObject.AddComponent<PhotonView>();
photonView.ownershipTransfer = OwnershipOption.Takeover;
photonView.synchronization = ViewSynchronization.ReliableDeltaCompressed;
photonView.viewID = viewId;
photonTransformView = gameObject.AddComponent<PhotonTransformView>();
photonTransformView.m_PositionModel.SynchronizeEnabled = true;
photonView.ObservedComponents = new List<Component>();
photonView.ObservedComponents.Add(photonTransformView);
photonView.TransferOwnership(controllingPlayer);
}
}
How can we make the drawing on two systems more similar? I have seen cases where people have been able to synchronise these perfectly. Check this. What are they doing?
Yes, PhotonTransformView is not suitable for this.
You could send a reliable rpc every x milliseconds with the list of points since the last rpc. That's when it's being drawn live, and when the drawing is finished, you cache the whole drawing definition in a database given a drawing Id. Then drawings can be retrieved later by players joining the room after the drawing was done or even loaded from a list of drawing or by any arbitrary logic.
All in all you need two different system, one when drawing is live, and one when drawing is done.
Martjin Pieters's answer is the correct way to do it.
But for those who have the same problem for a different situations, it comes from this line:
photonView.synchronization = ViewSynchronization.ReliableDeltaCompressed;
It's basically compressing data and not sending the new one if it's too close to the last data sent. Just switch it Unreliable and all the data will be directly sent.
I'm creating a card game similar to Play Your Cards Right using C# WFA.
I have 52 card faces as PNGs that I want to be able to apply to pictureboxes. I have 10 picture boxes, pbP1Card1 -> pbP1Card5 and pbP2Card1 -> pbP2Card5. When a card is drawn, I want to change the next picturebox from a cardback image to the corresponding card face for the newly drawn card.
I am trying to find a fast solution to getting this to work across all ten PBs. I am thinking of a method similar to this:
string picbox = "pbP1Card1";
string card = "ace_of_spades";
is used in
picbox.Image = Properties.Resources.card
Where the picbox being targeted and the current card can be changed accordingly.
EDIT:
Along with Joe's answer, I have achieved what I wanted by using the following:
picbox.Image = ((System.Drawing.Image)(Properties.Resources.ResourceManager.GetObject(card)));
string picbox = "pbP1Card1";
picbox.Image = Properties.Resources.card
That's not gonna work at all the way you want. Using string values as variable name references is not good practice. Instead, define your PictureBox controls with an array, like this:
PictureBox[,] cards = new PictureBox[1,4];
Now, pbP1Card1 will be cards[0,0]. pbP2Card5 would be cards[1,4], and you can use integer variables to increment through the positions. So you might have a line of code somewhere that looks like this:
cards[0,i].Image = Properties.Resources.card
The best thing here is you don't have to remove and recreate your existing PictureBoxes. Instead, your initialization code has a few lines that look like this:
cards[0,0] = pbP1Card1;
cards[0,1] = pbP1Card2;
cards[0,2] = pbP1Card3;
//...
cards[1,4] = pbP2Card4;
Since PictureBox is a reference type, you will be able to access the same PictureBox object using either reference, so anything you've already written to use the existing names will still work.
So this is a two part question. Moving question #2 to the top since #1 has been answered.
Question #2 - What would be an ideal method to use checkboxes from the initial instance of Form1 (that is sadly unnamed) to set what objects are allowed. I was thinking perhaps I could have a hidden form that holds variables, and use a set accessor called from Form1 on change to the checkboxes and updates the list or dictionary I call in my above mentioned function?
The first is, I have multiple images - two currently but more to come - and want to randomly use one of those each time the function is called. Currently I'm doing this:
System.IO.Stream file;
Random rnd = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber));
int a = rnd.Next(0, 2);
if (a == 0) {file = thisExe.GetManifestResourceStream("QATestFileGenTools.checkFront1.bmp");}
else if (a == 1) {file = thisExe.GetManifestResourceStream("QATestFileGenTools.checkFront2.bmp");}
else {file = thisExe.GetManifestResourceStream("QATestFileGenTools.checkFront2.bmp");}
The plan was the final else was to use that image as default in the future. As seen, each image will be a resource embedded in the executable. I'd like to clean this up, possibly using a dictionary or list, where I randomly get a number between 0 and list.size-1 and then set the file equal to that.
Question #1 - How can I make a list or dictionary of resource pointers and then set file to be that resource that time?
Now, currently I cannot use my checkboxes. I have two checkboxes on Form1 to reflect each of the two current images. Since there's no way to call Form1.cbImage1.Checked because the initial instance has no name/identifier, I was considering setting a global variable, which I am loathe to do. I tried setting a get accessor, but of course that runs into the same issue.
Thanks in advance!
For question #1:
var dict = new Dictionary<int, string>();
dict.Add(0, "QATestFileGenTools.checkFront1.bmp");
dict.Add(1,"QATestFileGenTools.checkFront2.bmp");
dict.Add(2, "QATestFileGenTools.checkFront2.bmp");
Random rnd = new Random(DateTime.Now.Millisecond);
int randomInt = rnd.Next(0, 2);
string resourceName = dict[randomInt];
System.IO.Stream file file = thisExe.GetManifestResourceStream(resourceName);
Edit: changed the random seed to something simpler and probably equally effective.
In the end, for question #2, I am creating a dictionary of objects (configuration data) along with calls to various worker classes. This might be clumsy, but it's allowing me to send various data in a single variable, arrays, integers, booleans and strings. So long as the code is commented well, it's easy enough to typecast them on the other side.
I am trying to write a kiosk program for my print center at a school for students to select size and media type and then have it generate a price. I am currently doing this with radio buttons which works fine but we are adding many more options and a drop down list box would be more appropriate. Also, my code for calculating the price is out of control. I would like to set this up so that calculating the price should be easy. Setup is something like this:
File1 - Paper Size (9 options) - Media Type (18 options)
File2, File 3, etc.
I was going to store this in a 3D array filename[]papersize[]media[] for processing the price.
The problem is that not all media types are available in all sizes. I see that you can not disable items in the list. If you pick one size, I can selectively populate the other drop down with or without items, but it changes my index numbers. If I could disable items, I could keep the same index and make an easy loop for processing prices. As it is now I would have to manually specify and loop for each paper size since the media types are different indexes.
I hope this makes sense, I am not really a programmer, I am just trying to make something simple to improve our workflow and accuracy at the print center. I can provide a screen shot of the old program and a mockup of my new program if it would help. Can anyone think of a more elegant solution for this?
Thanks!!
EDIT
Yikes.. Ok, this is ending up to be more difficult than I was expecting: Thanks everyone for your input, it is much appreciated. I did not really expect any responses and there were a lot. Thank You. I attempted the table idea mentioned below but I am not exactly sure how to implement it. I will comment on that post for what I tried. Let me provide more detail in the event that someone else has another idea.
For example of what I am trying to do:
Size = 8.5x11 has media = matte, double sided matte, luster, gloss, acetate, resume
Size = 11x17 has media = same minus acetate and resume
and so on, up to a 60" roll with backlit media and all sorts of stuff.
Price for 8.5x11 is 1.50 regardless of paper and then each paper has its own price
Price for 11x17 is 3.00 and each paper has its own price which is more than their 8.5x11 counterparts
8.5x11 matte = .25
11x17 matte = .50
8.5x11 matte total = 1.75
11x17 matte total = 3.50
I am trying to do this in as little steps as possible. Currently I have radio buttons which take up a bunch a screen real-estate and do things like: When 11x17_1.Checked acetate_1.Disable, etc. Also for calculating price I have hundreds of lines of code doing things like:
If(8.5x11_1.Checked)
{
If(matte_1.Checked)
price = 8.5x11matte_1;
if(luster_1.Checked)
price = 8.5x11luster_1;
...etc.
}
Rolls require more data (height) to be processed as we charge by linear inch for these. Currently for each file I just have a height box that they are required to fill out. I could just put a height field next to each file for my new version. Then if they select a roll, the height box bust be filled out, which requires more IF's... which I currently have hundreds of. Any thoughts on a more elegant way to do this?
I just don’t have the programming background to simplify this, but I know this can probably be done in 10 lines of code using an array and drop down lists:
It has been a long time since I used arrays but I was thinking of something like:
Selection[file_1][combobox_size.Index][combobox_media.Index]
I think I would have to manually define each array value since the prices are arbitrary?
[0][0][0] = 1.75
[0][0][1] = 1.75
[0][0][2] = 2.00
And so on.
My winform would have let’s say 12 rows for them to enter a file name and then pick the drop down lists. If filename != null then I will process a price for the file and selections.
So if file 1 was 11x17 gloss my array would be something like:
[0][1][3] which I would have pre-defined with a value of $4.00 for example
If it is a roll then I would just multiply by the required height box.
Is this logic sound or grossly inefficient?
EDIT #3
Ok, almost there I think. Sadly, I was unable to figure out the other solutions offered by the community, but I wrote a "get_index" function that looks like this:
public static int get_index(string index)
{
if (index == "Matte")
return (1);
....
if (index == "Luster")
return (3);
....
else
return (0);
}
in my main program I define prices like this:
for (int x = 0; x < filenum; x++)
{
pricegrid[x, 0, 0] = 1.75; // 8.5x11 Resume
pricegrid[x, 0, 1] = 1.75; // 8.5x11 Matte
pricegrid[x, 0, 2] = 1.75; // 8.5x11 Double Sided Matte
pricegrid[x, 0, 3] = 2.35; // 8.5x11 Luster
.....
}
Then to calculate the price I am doing something like this calling that get_index function:
private void calculate_price()
{
getindex[0] = get_index(media1.SelectedItem.ToString());
....
}
You should populate your ComboBox dynamically as you do.
Instead of using SelectedIndex you can use SelectedValue which does not depend on number of elements.
See for example: Using ValueMember in ComboBox
You shouldn't use one three-dimensional array. You will need 3 tables to that. Store all your types in a database.
3 tables are:
1. paper
2. media
3. papermedia
so. you populate first dropdown with papersizes.
then when item is selected in papersizes you run a query to populate dropdown media (you join through intersection table). this way you will only show media that is only available for this papersize. or you can do the other way around.
Does this answer your question?
There are several ways of doing it.
You could create a class FileWithDetail that'd store
[class File / class paper size / class Mediatype ]
Initialize your list at the start of your app
List<FileWithDetail> LstFileWithDetail = new FileWithDetail(){...}
Then with Linq to Object you would easily be able to query the object and bind it to your comboboxes according to your selected value
var LstPaperSize = from p in FileWithDetail
where p.FileName == SelectedFileName
Select ...