I am trying to prompt a method to start upon a button click. The problem is that they are over two different classes and it is difficult to share all the relevant values over both the form and the class. I was wondering if it was possible to change a listbox's values through pressing a button on a form. At the moment mine is just staying on the first list.
My first class is the form. This is holding the physical changing of the data.
if (teach.Alphabet == "B")
{
lbl1.Text = "What is the english word for White?";
lstNum.Items.AddRange(number1);
txtQuestion.Text = String.Join(Environment.NewLine, english1);
}
It calls the method teach.CallRandomQuestion() to get the alphabet letter (it is a way it chooses which question to put onto the system). This is done by the following code:
public void CallRandomQuestion()
{
if (score == 1)
{
Alphabet = "A";
Answer = "1";
}
if (score == 2)
{
Alphabet = "B";
Answer = "3";
}
}
Finally I have a public int score which starts at 1 and adds one every time the correct answer is given. So if the correct answer is given, the second question B should show in the listbox, but doesn't.
public void Showinlistbox()
{
// Add a listBox named listBox1
// Add Score
score++;
CallRandomQuestion();
//if you want mutual-exclusion lock add lock (listBox1)
listBox1.Items.Add(Alphabet);
}
Related
I'm currently working on a chatting program and the idea is to make it a secret one (Kind of like Facebook has the secret chat function).
My messages are sent to a listBox component and I want that every 10 or 'n' seconds the oldest message would get deleted. I
was trying to mark every message with an index but didn't quite understand how that works.
What I'm asking if maybe you guys know a function or could help me write one that does just that. I'm using Visual Studio 2015 Windows Forms, C#.
Well, when you have a ListBox, the items are all indexed since it's an object collection (an array of objects). Starting from 0 and going upwards for newer entries.
So let's say we add 3 items to our ListBox
listBox1.Items.Add("Item 1"); //Index 0
listBox1.Items.Add("Item 2"); //Index 1
listBox1.Items.Add("Item 3"); //Index 2
All you would have to do, is create a thread that runs in the background that deletes the item at index 0 (the oldest entry) each time.
new Thread(() =>
{
while(true)
{
if(listBox1.Items.Count > 0) //Can't remove any items if we don't have any.
{
Invoke(new MethodInvoker(() => listBox1.Items.RemoveAt(0))); //Remove item at index 0.
//Needs invoking since we're accessing 'listBox1' from a separate thread.
}
Thread.Sleep(10000); //Wait 10 seconds.
}
}).Start(); //Spawn our thread that runs in the background.
In C# WinForms a ListBox contains ListBoxItems which are a ObjectCollection (msdn-link)
So you can add any Object you like, the message which will be displayed comes from the DisplayMember
So for example
public class MyMessage {
public DateTime Received { get; set; }
public string Message { get; set; }
public string DisplayString
{
get { return this.ToString(); }
}
public string ToString() {
return "[" + Received.ToShortTimeString() + "] " + Message;
}
}
can be added as ListBoxItem.
Setting the DisplayMember to "DisplayString" (more here) will get you the correct output.
now you can iterate through the ListBoxItems, cast them as MyMessage and check the time when they were received.
I don't know if you thought about this but here's a way you could achieve this task.
First create an List of strings
List<string> list1 = new List<string>();
To use the List feature you will have to include collections in the form
using System.Collections;
Now comes the tricky part.
First declare a static integer variable globally i.e. outside all classes.
static int a;
Whenever you receive a message(considering your messages will be in string format) you've to add that string to list1 which you created.
list1.Add("the received message");
Now you've to declare a Timer (If you're new, check out how timers work). Windows forms already has timers, using that will be preferable.
The timer sends a Tick event after the desired time.
private void timer1_Tick(object sender, EventArgs e)
{
a = list1.Count() - 1; //Count will return the number of items in the list, you subtract 1 because the indexes start from 0
list1.RemoveAt(a);
listBox.Items.Clear();
foreach(string x in list1)
{
listBox.Items.Add(x);
}
}
What this code will do is, at every Tick event of the timer it will refresh the listbox, remove the last element from the array, and refill the listbox with the rest.
To use the timer just drag and drop it on the form. It's all GUI based and easy to figure out.
Let me know if you've doubts.
Tip: Make maximum use of try{} & catch{} blocks to avoid app crashes.
The following code is giving me a small issue.
public void ButtonShort()
{
lcd.WriteLine(" K ");
GpioPinValue Readbutton = ButtonS.Read();
if (buttonS == GpioPinValue.Low)
{
Temp = Temp + "K";
}
}
Temp is a list which is empty by default. So every button press should add ONE 'K'.
But it actually registers 'K' multiple times.
What I want is that one button press only registers one 'K'.
Thanks for the help!
I can't directly help you for C#, but had a similar problem once where I used Java with the Pi4J Lib for the GPIO Access.
In there, you have events which are triggered by a changing input pin value. I catched that event and checked in the routine wether the state was high/low, depending on what had to be the actual trigger for counting.
Code in Java was quite straigt forward:
public void handleGpioPinInputStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
if (event.getState() == PinState.HIGH) {
[...]
}
}
[Edit - got interested... :-)]
Perhaps the following code from here will help:
private void buttonPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
// toggle the state of the LED every time the button is pressed
if (e.Edge == GpioPinEdge.FallingEdge)
{
ledPinValue = (ledPinValue == GpioPinValue.Low) ?
GpioPinValue.High : GpioPinValue.Low;
ledPin.Write(ledPinValue);
}
[...]
I am having a bit of difficulty setting a variable to 0 if the user doesn't enter a value into the textbox, it is making it tricky because the variable gets passed around multiple forms, if it was in the same form it would be much easier to do. My code is attached down below.
//in one of my input forms
//runs on button click
if (!string.IsNullOrWhiteSpace(TXTCustomerGrowth.Text))
{
fm.SaveGrowth(Convert.ToDouble(TXTCustomerGrowth.Text));
//fm is instance of class where my methods to save variables are
}
//in class
public void SaveGrowth(double value)
{
customerGrowth = value;
}
public double GetGrowth()
{
return customerGrowth;
}
//in the final summary form
double growth = fm.GetGrowth();
I have tried initially saving the variable as a string and converting to a double when i need it but it complains that it cannot convert type string to double so basically what I want to know is how I can modify that first if statement so if the textbox is null then set the variable to null (my issue being I am not sure how to do it in my situation because the variable isnt created in the input form.
EDIT:
I forgot to mention it runs fine initially but I have an edit button on the summary screen which allows you to change your values and its when they delete the growth value and leave it blank it doesnt register and keeps the growth the same as what it was.
EDIT2:
My edit button just brings you back to the beginning so your values you entered aren't deleted,
when the summary button is pressed this method is called:
public void ShowSummary()
{
calculatingForm.Show();
summaryForm.UpdateForm();
calculatingForm.Hide();
summaryForm.Show();
}
and in the UpdateForm method is:
double growth = fm.GetGrowth();
String Foo = "21"
Double bar;
if(Double.TryParse(Foo, out bar))
{
}
Upon further attempts answer my own question here is the code answer:
if (!string.IsNullOrWhiteSpace(TXTCustomerGrowth.Text))
{
fm.SaveGrowth(Convert.ToDouble(TXTCustomerGrowth.Text));
}
else
{
fm.SaveGrowth(0);
}
I've been messing around with a word game in Unity C# and have come to a standstill regarding an anti-cheat mechanic I want to implement.
Once the first letter has been entered into the input field, I start running a 2 second timer. After the 2 seconds, in the player does not submit or type another letter, the input field should lock the previously typed letters in place on the input field and any letters typed after should be typed after it.
Here's the code I have so far:
currTime = 0;
hasInput = false;
lockedString = "";
void Update(){
if(hasInput){
currTime += Time.deltaTime * 1;
if(currTime >= 2){
//Stores current string value of input field
lockedString = inputField.text;
}
}
}
void OnInputValueChange(){
currTime = 0;
hasInput = true;
if(lockedString != ""){
inputField.text = lockedString + inputField.text;
}
}
Right now I'm running OnInputValueChange() whenever the input field's value is changed. I also manage to store the string that's been entered so far once the timer hits 2 seconds, but I do not know how to make it so that the input field "locks" the locked string into the front and allow changes to the letters typed behind it. The code inputField.text = lockedString + inputField.text; simply adds the lockedString variable to the input field every time the value gets changed.
The desired outcome is as such in pseudo-code:
//User types "bu"
//2 second timer starts
//During these 2 seconds, user can delete "bu" or continue typing
//User deletes "bu" and types "ah"
//Once the 2 second timer ends, whatever string is now in input is locked
//"ah" is now locked at the front of the input field
//After locking "ah", user cannot delete it anymore, but can continue typing
Any insight to how I might achieve something like this will be most helpful. Thanks for taking the time to help, I really appreciate it!
Currently, you are simply concatenating the string. You will want to check if the string starts with the same characters, and if not, completely overwrite the input:
void Update() {
if (hasInput && ((Time.time - inputTime) > 2f))
{
//Stores current string value of input field
lockedString = inputField.text;
hasInput = false;
}
}
void OnInputValueChange() {
inputTime = Time.time;
hasInput = true;
if ((lockedString.Length > 0) && (inputField.text.IndexOf(lockedString) != 0)) {
// Replace invalid string
inputField.text = lockedString;
// Update cursor position
inputField.MoveTextEnd(false);
}
}
Note: I have implemented an alternate method of measuring the time passed. Feel free to replace this with your own method.
I'm making a simple Guess-The-Number game with a GUI. I need to wait on a loop waiting for the user to input a number in a text box and press "OK". How do I wait for an event inside a loop?
Note: I don't want message boxes. This is done in the main window, hence the need to wait for input.
EDIT: I should have explained myself better. I know that there's a loop inside the GUI. What I want is another loop inside a method. Maybe there's a better way to do this. I could code stuff inside the button's event handler, now that I think about it. Although I'd need global variables. Whataver, I'll think about it, but I hope my question is clearer now.
EDIT 2: Sorry that my question wasn't clear and the edit didn't do much help. First of all, the code is too big to be posted here. I'd probably have to post a screenshot of the GUI, so it wouldn't be of much use. Basically, I have two fields, "Max number" and "Number of allowed guesses". The user enters these two and clicks "Play". A new panel becomes available, with a text box and a "Guess" button. The user enters a guess, and the program checks to see if it's correct.
The purpose of the second infinite loop is to avoid global variables. See, each time the user clicks "Play", the game has to generate a new random number as the correct guess. If everything is done inside a method, no problem. But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
I'd also have to keep track of the remaining number of guesses outside of the method. Again, it's no big deal. I just want to avoid globals if I can.
Again, I'm sorry that my question wasn't too clear. I'm kind of tired, and I didn't feel like writing too much. If this still isn't clear, then don't bother. I'll think of something.
C# automatically loops infinitely waiting for events until your form is closed. You just need to respond to the button click event.
Jason Down's suggestion is wise, create a new GuessingGame class and add it to your project. I know you're worried about "global variables" (which everyone is taught in school never to use unless you absolutely have to), but think about your design specifications for a minute.
But if the "Guess" button's event handler is called multiple times, the number has to be stored as an instance variable of the Form. Sure, it's not big deal, but I think the number should be a property of the method directing the current game, not of the Form.
As an alternative, store an instance of your GuessingGame class in the form. This is not a global variable! You said so yourself, the point of the game is keep track of the guesses and generate new numbers to guess every time "Play" is clicked. If you store an instance of the game in the form then open another form (e.g. a Help or About box), then the game's instance would not be available (thus, not global).
The GuessingGame object is going to look something like:
public class GuessingGame
{
private static Random _RNG = new Random();
private bool _GameRunning;
private bool _GameWon;
private int _Number;
private int _GuessesRemaining;
public int GuessesRemaining
{
get { return _GuessesRemaining; }
}
public bool GameEnded
{
get { return !_GameRunning; }
}
public bool GameWon
{
get { return _GameWon; }
}
public GuessingGame()
{
_GameRunning = false;
_GameWon = false;
}
public void StartNewGame(int numberOfGuesses, int max)
{
if (max <= 0)
throw new ArgumentOutOfRangeException("max", "Must be > 0");
if (max == int.MaxValue)
_Number = _RNG.Next();
else
_Number = _RNG.Next(0, max + 1);
_GuessesRemaining = numberOfGuesses;
_GameRunning = true;
}
public bool MakeGuess(int guess)
{
if (_GameRunning)
{
_GuessesRemaining--;
if (_GuessesRemaining <= 0)
{
_GameRunning = false;
_GameWon = false;
return false;
}
if (guess == _Number)
{
_GameWon = true;
return true;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call StartNewGame() before making a guess.");
}
}
}
This way, all the data related to the game is encapsulated within the class. Hooking up the events is easy in the codebehind of the form:
GuessingGame game = new GuessingGame();
private void btnPlay_Click(object sender, EventArgs e)
{
int numberOfGuesses = Convert.ToInt32(txtNumberOfGuesses.Text);
int max = Convert.ToInt32(txtMax.Text);
game.StartNewGame(numberOfGuesses, max);
}
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = Convert.ToInt32(txtGuess.Text);
bool correct = game.MakeGuess(guess);
if (correct)
lblWin.Visible = true;
if (game.GameEnded)
{
// disable guess button, show loss label
}
}
You should probably look for a book to actually learn windows programming.
The very basics:
1) There is already an infinite loop deep down in the windows code somewhere. Any windows program is constantly looping and scanning for input.
2) Once input is found, this loop fires off an Event.
3) Your mission, should you choose to accept it, is to write event handlers to handle those events.
you are most likely doing it wrong as it has already been pointed out, but you can use this
Application.DoEvents();
to process events when you are on an actual loop
to do it the right way
- don't use a loop
- use an edit box for the input, then a button
- implement the button onclick event
Yes, and What if I am waiting for Speech events, it could happen anytime event when a function is running, I need to handle that without recursively call a function