So, I'm trying to code simple memory game in Windows Forms but I've met a simple problem that somehow I can't pass.
This is a single button code(they all look very similar):
Match CheckForMatches = new Match();
private void Pathfinder_Click(object sender, EventArgs e)
{
CheckForMatches.AddButton(Pathfinder);
CheckForMatches.Matched();
}
(where CheckForMatches object is shared between all buttons in given form)
And here are called methods codes:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
firstButtonPressed.ImageIndex = 0; //uncovering card
}
else
{
secondButtonPressed = newButton;
secondButtonPressed.ImageIndex = 0;
Thread.Sleep(1000);
}
}
public bool Matched()
{
if (firstButtonPressed != null && secondButtonPressed != null )
{
if (firstButtonPressed.Name != secondButtonPressed.Name)
{
if (firstButtonPressed.Text == secondButtonPressed.Text)
{
DisposeButtons();
return true;
}
else
{
NullButtons();
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
Now this method call one of two others, depending if last 2 clicked buttons are a pair or not(basing on their name and text):
This in case of succes disposes buttons and null Match class variables:
public void DisposeButtons()
{
firstButtonPressed.Dispose();
secondButtonPressed.Dispose();
firstButtonPressed = null;
secondButtonPressed = null;
}
This is case of failure covers cards and also nulls Match class variables:
public void NullButtons()
{
firstButtonPressed.ImageIndex = 1; //covering cards
secondButtonPressed.ImageIndex = 1;
firstButtonPressed = null;
secondButtonPressed = null;
}
The point is, no matter where I place Thread.Sleep(1000), user can never see second card he choses. He always see the first one and then, when he choses second one, either both cards are disposed(app is freezing due to that delay) or the first one becomes covered, without uncovering the second one.
EDIT:
I added output to debugger window, so now method AddButton looks like this:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
Debug.WriteLine("Before index chaning: " + firstButtonPressed.ImageIndex);
firstButtonPressed.ImageIndex = 0; //uncovering card
Debug.WriteLine("After index chaning: " + firstButtonPressed.ImageIndex);
}
else
{
secondButtonPressed = newButton;
Debug.WriteLine("Before index chaning: " + secondButtonPressed.ImageIndex);
secondButtonPressed.ImageIndex = 0;
Debug.WriteLine("After index chaning: " + secondButtonPressed.ImageIndex);
Thread.Sleep(1000);
}
}
I can see there, that ImageIndex buttons' property actually changes between 1 and 0. However, in practice, it's only visible when first if block of this method is called. I would be grateful for answering why and how to change that.
Okay, I found out maybe not best solution, but it works. I simply forced button to refresh.
Correct form of AddButton method is:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
Debug.WriteLine("Before index changing: " + firstButtonPressed.ImageIndex);
firstButtonPressed.ImageIndex = 0; //uncovering card
Debug.WriteLine("After index changing: " + firstButtonPressed.ImageIndex);
}
else
{
secondButtonPressed = newButton;
Debug.WriteLine("Before index changing: " + secondButtonPressed.ImageIndex);
secondButtonPressed.ImageIndex = 0;
secondButtonPressed.Refresh();
Debug.WriteLine("After index changing: " + secondButtonPressed.ImageIndex);
Thread.Sleep(500);
}
}
I hope it will be useful for someone one day.
Related
this code is called upon a button click in a windows form and the values are stored after button click and disappear after the event ends and go back to default values but I want the values to remain as i have to use them somewhere else....any suggestions?Also I want to retain the current state of the form and not use a new instance each time
showval function called and the value of variable bitwise is changed there
class Profile{
public bool GetProfileFilter()
{
frmInactiveView frmInactive = new frmInactiveView();
if (frmInactive.btnApplyWasClicked == true || frmInactive.btnCancelWasClicked == false)
{
frmInactive.ShowVal();
MessageBox.Show("bit:" + IBitWise);
MessageBox.Show("ST:" + BegDate);
MessageBox.Show("ET:" + EndDate);
return true;
}
else
{
return false;
}
}
}
enter code here
public partial class FilterView : Form{
Profile profile = new Profile();
private void btnApply_Click(object sender, EventArgs e)
{
btnApplyWasClicked = true;
ShowVal();
status = profile.GetProfileFilter();
profile.ShowMe();
Btn_Enable();
this.Close();
}
public void ShowVal()
{
if (btnApplyWasClicked == true || btnCancelWasClicked == false)
{
if (chkCancel.Checked == true)
{
profile.IBitWise += 2;
}
if (chkDiscon.Checked == true)
{
profile.IBitWise += 1;
}
if (chkVoidwoRes.Checked == true)
{
profile.IBitWise += 4;
}
if (chkVoidwRes.Checked == true)
{
profile.IBitWise += 8;
}
}
}
}
The problem is your form getting instantiated every time when GetProfileFileter is called.
To avoid it, put instance of frmInactiveView under your Profile class. Then value of frmInactiveView would only be renewed when a new Profile is instantiated.
class Profile{
// Keep your form instance here
frmInactiveView frmInactive = new frmInactiveView();
public bool GetProfileFilter()
{
// Don't new it again!
//frmInactiveView frmInactive = new frmInactiveView();
DialogResult result = frmInactive.ShowDialog();
// You may need to take care of dialog result if someone clicked cancel.
if (frmInactive.btnApplyWasClicked == true || frmInactive.btnCancelWasClicked == false)
{
frmInactive.ShowVal();
MessageBox.Show("bit:" + IBitWise);
MessageBox.Show("ST:" + BegDate);
MessageBox.Show("ET:" + EndDate);
return true;
}
else
{
return false;
}
}
}
So I've just been making a basic little calculator made up of buttons and a textbox(tbxSum).
The problem I'm having is that if an invalid sum is input I want my catch block to pick it up(which it does) and replace what's in the textbox with the most recent result in the calculator(which it doesn't).
So say I say:
3+3=6
My calculator will now put 6 in the textbox for the next sum.
So then say I did:
6//3
It's invalid which the calculator picks up, but I want the textbox value to return to 6 from the previous sum.
This is what I've tried:
var myButton = (Button)sender;
if (myButton.Content.ToString() == "=")
{
DataTable dt = new DataTable();
string s = tbxSum.Text;
string result = "";
if (s.Contains("("))
{
s = s.Replace("(", "*(");
}
try
{
var v = dt.Compute(s, "");
tbkSum.Text = s + "=" + v.ToString();
tbxSum.Text = v.ToString();
}
catch
{
MessageBox.Show("Invalid Sum");
tbxSum.Text = result;
}
}
I also have a textblock(tbkSum) which shows the previous sum so I thought maybe I could take everything in there to the right of the equals sign but I have no idea how to do that.
class Calculate(){
private boolean lastGoodValueSet = false;
private int lastGoodValue = 0;
void buttonFunction(){
if (myButton.Content.ToString() == "=")
{
//Your code
try
{
var v = dt.Compute(s, "");
tbkSum.Text = s + "=" + v.ToString();
lastGoodValue = v;
lastGoodValueSet = true;
}
catch
{
MessageBox.Show("Invalid Sum");
tbxSum.Text = result;
if (lastGoodValueSet)
tbxSum.Text = lastGoodValue;
}
}
}
}
This is an example set of code you could use, it's a simple value that you have to store to say if a good computation has been done and if so, at the point of error we want to go back to the computation. Hope that helps! You'll want to put some kind of message to the user, so they know there was an error though.
We have to do this, as at the point of the user pressing the equals button, the value has already changed inside tbkSum, we need it before the user has changed the value, so the best time to grab it is at the point when we update the tbkSum text value at a successful calculation
This is also assuming you do not create a new instance of the Calculate class each time you do your computation. Otherwise you'd need to store the number somewhere else
EDIT
The other way to fix this issue is to instead prevent the duplicate in the first place, I read from your other comments that you control what goes into the text box by buttons on the application. Assuming all buttons go through the same method of buttonFunction() then you could do:
private char[] buttonChars = {'/','*', '+'/*e.t.c*/}
void buttonFunction(){
string buttonPressedStr = myButton.Content.ToString();
char buttonPressed = buttonPressedStr[0];
int pos = Array.IndexOf(buttonChars , buttonPressed);
if (pos > -1)
{
if (tbxSum.Text.Length > 0){
char last = tbxSum.Text[tbxSum.Text.Length - 1];
pos = Array.IndexOf(buttonChars , last);
}
else
pos = 0;
if (pos > -1){
tbkSum.Text += buttonPressedStr;
}
}
There are cleaner ways to do this, but it's an example of how you could have prevented your issue in the first place. Some explanation:
buttonChars is an array of your different button types that would be appended to your text in the box, an example is +, -, and so on
First it checks if the button pressed was in your collection of specified buttonChars
If so, we have to check what the last thing added to the tbxSum was
If the last thing added to tbxSum was again found in the buttonChars array, we don't want to append a string
Otherwise, if the tbxSum was empty or had another character at the end, we can append our character
You can store the old value in a variable declard outside the try block and use this variable in your catch block again:
string oldSumValue = tbxSum.Text;
try
{
// your code
}
catch
{
tbxSum.Text = oldSumValue ;
MessageBox.Show("Invalid Sum");
}
Alternatively I've come up with this to prevent there being:
A)Duplicate of '*' or '/'
B)Sum starting with '*' or '/'
public MainWindow()
{
InitializeComponent();
if (tbxSum.Text == "")
{
btnDiv.IsEnabled = false;
btnMult.IsEnabled = false;
}
}
protected void btnSumClick(object sender, EventArgs e)
{
btnDiv.IsEnabled = true;
btnMult.IsEnabled = true;
var myButton = (Button)sender;
int pos = tbxSum.Text.Length;
if (pos > 0)
{
if ((tbxSum.Text[pos - 1] == '/' || tbxSum.Text[pos - 1] == '*') &&
(myButton.Content.ToString() == "/" || myButton.Content.ToString() == "*"))
{
int location = tbxSum.Text.Length - 1;
tbxSum.Text = tbxSum.Text.Remove(location, 1);
}
}
}
When I select an item from my list, the whole selection-process goes on twice.
private void serving_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
Debug.WriteLine("Serving added to diary");
login(null, null);
}
catch (WebException)
{
Debug.WriteLine(e.Error);
}
ServingList.SelectedIndex = -1;
}
When I leave out ServingList.SelectedIndex = -1; the process goes on once. But I need the selected index back to -1.
What am I missing?
Handler on SelectionChanged:
private void ServingList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("\n[#] ServingList_SelectionChanged");
Debug.WriteLine("Selected item:" + ServingList.SelectedIndex);
Debug.WriteLine("ID of latest TP: " + tp.id);
String itemid = tp.id;
Produkt temp = (Produkt)ServingList.SelectedItem;
if (servingid.Length < 1)
{
servingid = temp.servingid;
}
WebClient addserving = new WebClient();
addserving.Credentials = new NetworkCredential(username.Text, passwort.Password);
addserving.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
addserving.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
addserving.UploadStringAsync(new Uri("http://fddb.info/api/v8/diary/add_item.xml?apikey=ICPOKUI83555PU43"), "&item_id=" + itemid + "&serving_id=" + servingid);
addserving.UploadStringCompleted += new UploadStringCompletedEventHandler(serving_UploadStringCompleted);
Pivot.SelectedIndex = 0;
}
You are causing an infinate loop.
You have your list box and changing it causes an action
Change X > Action X > Handle X > Change X (-1) > Action X
Etc.
You need to have some form of break to the loop for a condition
private void serving_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
//Break condition
if (ServingList.SelectedIndex != -1)
{
try
{
Debug.WriteLine("Serving added to diary");
login(null, null);
}
catch (WebException)
{
Debug.WriteLine(e.Error);
}
ServingList.SelectedIndex = -1;
}
}
By doing this, you only set it to -1 when you need to, otherwise it will continuously keep setting the selected index to -1 even though it is already in fact set.
Im making a chat program that saves the messages in files like pub0.zzc, all computers that are using it will be connected to the hard drive that these files are in, so its fine. The method data.Chat.Read(MessageTypes type, string Channel) infinite loops through a try catch statement till it returns the messages. I used this before and works perfectly. But, my code was hard to manage so instead of just putting text boxes into the window and using the code each time, i created a user control (MessageViewer). It works fine, once again when I run it, BUT it freezes VS whenever I try to use the designer on the window housing the control. the probelm isnt the window because when i delete the control its fine. I think the possible errors are at RefreshMessages() and the Refresher_Tick(...)
Refresher.Stop() and .Start() is also not it, worked fine before
so here is the code:
private void Refresher_Tick(object sender, EventArgs e)
{
Refresher.Stop();
int RefreshRate = 4;
bool Live = true;
if (RefreshRateChoice == "Manual")
{
Live = false;
RefreshRate = 1;
}
else if (RefreshRateChoice == "4 ( Default )")
{
Live = true;
RefreshRate = 4;
}
else
{
Live = true;
RefreshRate = Convert.ToInt32(RefreshRateChoice);
}
if (data.Chat.Read(MessageType, ChannelChoice) != ContentPresenter.Text && Live)
{
RefreshMessages();
}
Refresher.Interval = RefreshRate;
Refresher.Start();
}
public void RefreshMessages() {
if (data.Chat.Read(MessageType, ChannelChoice) != ContentPresenter.Text)
{
ContentPresenter.Text = data.Chat.Read(MessageType, ChannelChoice);
}
}
and if you need it:
public static string Read(MessageTypes Type, string Channel)
{
string Loc;
if (Type == MessageTypes.Public && (Channel == "1" || Channel == "2"))
{
return "Can not view this channel, only post to it.";
}
if (Type == MessageTypes.Public)
{
Loc = data.AssetsFolder + "\\pub" + Channel + ".zzc";
}
else if (Type == MessageTypes.Private)
{
Loc = data.AssetsFolder + "\\" + Channel + ".zzpc";
}
else if (Type == MessageTypes.Game)
{
Loc = data.AssetsFolder;
}
else
{
Loc = data.AssetsFolder;
}
while (true)
{
try
{
String MessageList = "";
StreamReader MessageReader = new StreamReader(Loc);
string EncMessages = MessageReader.ReadToEnd();
MessageReader.Dispose();
List<string> EncMsgList = EncMessages.Split(';').ToList();
for (int i = 1; i < EncMsgList.Count; i++)
{
MessageList += data.Encodings.Decrypt(EncMsgList[i], Palettes.Message) + "\n";
}
return MessageList;
}
catch
{
// Do nothing
}
}
}
You say that it "freezes."
In your Read method you have a while(true) loop with an embedded try...catch block, but the catch never returns you from that method. If you keep throwing the same exception, you'll continue to loop over and over which could be where you are freezing.
At least to prove that is the case, put a return in you catch or some diagnostic code to indicate if that is the case.
if (t != null) is always null why help..
when ever i try to get value in the variable name t it always gets in the else part but i am sure that there is valuse in tat variable.
private void button3_Click(object sender, EventArgs e)
{
try
{
if (search=="")
{
}
else
{
if (textBox1.Text=="")
{
MessageBox.Show("Select A Task Or Find One");
}
else
{
search = textBox1.Text;
}
}
if (search != null)
{
t = tasks.OpenTask(search);
if (textBox2.Text!="")
{
short hour = short.Parse(textBox2.Text.Substring(0, 2));
short minute = short.Parse(textBox2.Text.Substring(3, 2));
if (t != null) // this is null dont know why
{
foreach (Trigger tr in t.Triggers)
{
if (tr is StartableTrigger)
{
(tr as StartableTrigger).StartHour = hour;
(tr as StartableTrigger).StartMinute = minute;
}
}
t.Save();
t.Close();
}
tasks.Dispose();
button2.Visible = true;
textBox3.Visible = true;
search = "";
}
else
{
MessageBox.Show("Enter Time ");
}
}
}
catch (Exception b)
{
MessageBox.Show(b.ToString());
// MessageBox.Show("Select A Task From The List ");
}
}
help guys .. well i tried it to debug but didnt get a break through..
t is null because tasks.OpenTask(search) returns null.
Probably there is no task matching your search criteria.
Why are you disposing of tasks in the first place?
Any place in your source ,where you have written something like this MyClass t = new MyClass().. where t is your class object. If you have not declared,It will always come null.
Or might be you have declared something like this
private Task t; but forgot to add new keyword. Checkout!!!