Sorry for the strange title, I just don't know how to name this question.
So I have such a function say().
void say(string printedText) {
gameText.text = printedText;
}
And I need to use it several times. Something like this:
say("test text 1");
say("test text 2");
say("test text 3");
...
I need to change text by clicking Space button. Of course I need to use something like this:
if(Input.GetKeyDown(KeyCode.Space)) {
...
}
But I can't understand how to show text step by step. So for example if I click Space button once I should see "test text 1". Next click should show me "test text 2" etc.
How can I realise it? Thanks in advance.
Depending on your needs you could store different texts in a List<string> or maybe even Queue<string> and do
List example
// Add your texts in the editor or by calling texts.Add(someNewString)
public List<string> texts = new List<string>();
private int index = 0;
if(Input.GetKeyDown(KeyCode.Space))
{
// have a safety check if the counter is still within
// valid index values
if(texts.Count > index) say(texts[index]);
// increase index by 1
index++;
}
Array example
Basically the same as the List<string> but you can't add or remove elements "on the fly" (at least not that simple)
public string[] texts;
private int index = 0;
if(Input.GetKeyDown(KeyCode.Space))
{
// have a safety check if the counter is still within
// valid index values
if(texts.Length > index) say(texts[index]);
// increase index by 1
index++;
}
Queue example
public Queue<string> texts = new Queue<string>();
for adding a new text to the end of the queue do
texts.Enqueue(someNewString);
and then
if(Input.GetKeyDown(KeyCode.Space))
{
// retrieves the first entry in the queue and at the same time
// removes it from the queue
if(texts.Count > 0) say(texts.Dequeue());
}
Simple counter
If it is really just about having a different int value then yes simply use a field
private int index;
if(Input.GetKeyDown(KeyCode.Space))
{
// uses string interpolation to replace {0} by the value of index
say($"test text {0}", index);
// increase index by one
index++;
}
define a class field like this:
int count = 0;
and now everytime space is hit:
if(Input.GetKeyDown(KeyCode.Space)) {
say("test text " + count);
count = count + 1;
}
This Code:
if(Input.GetKeyDown(KeyCode.Space)) {
...
}
only works for Unity, In Visual Studio you'll have to create an Event to whatever object you want to do this, for example, if you want to call a void each time you press spacebar youll have to do this, it is easy: (Image below)
In the propieties window press the bolt icon and after double click on the event you want to create (samples): TextChanged, LocationChnaged, MouseMove, etc...
I will use KeyDown on the TextBox object
image
Now in your code this void should be generated
image
Inside this void i writed the code and this is how it looks:
(put int n = 1 before voids)
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Space)
{
//int n = 1; must be defined
textBox1.Text = "test text " + n;
n++;
}
}
Now each time you'll press or stay pressed spacebar the textbox will be filled with "test text " and the value will be 1 more each time.
Related
I am creating a system that includes a ListBox of integers inserted by the user. I have contained a search button and a search TextBox for the user to input the integer they want to search for within the ListBox. Once the user has inputted the integer, I want a message box to be displayed either informing the user that there is e.g. 1 integer of value '3' in the list box, or an error message box informing the user that the integer does not exist within the list box.
private void buttonSearch_Click(object sender, EventArgs e)
{
listBoxAddedIntegers.SelectedItems.Clear();
for (int i = listBoxAddedIntegers.Items.Count - 1;i>=0; i--) ;
{
if (listBoxAddedIntegers.Items[i].ToString().ToLower().Contains(textBoxSearch.Text.ToLower())) ;
{
listBoxAddedIntegers.SetSelected(i, true);
}
}
// ...
}
I am not really sure on the code that I am meant to include here, and the code that I have already inserted suggests that 'i' does not exist in the current content.
Can anyone help please?
the code that I have already inserted suggests that 'i' does not exist in the current content
As #FrankM already mentioned in the comments. You have a trailing ; after your for-loop.
for (int i = listBoxAddedIntegers.Items.Count - 1;i>=0; i--) ;
This will prevent the for-loop to execute your code within the { ... }. This can be transcribed to
for (int i = listBoxAddedIntegers.Items.Count - 1;i>=0; i--)
{
// Do nothing.
}
{
// now your code
}
This means also that your code within the last curly braces will be in its own scope and so that all your defined variables will be unavailable to the following code.
Answering your actual question:
As you already do for selecting the matching items. You can extent this looping by counting up a counter. And later on show the results with a MessageBox.
With the following snippet of your code
listBoxAddedIntegers.Items[i].ToString().ToLower().Contains(textBoxSearch.Text.ToLower()))
you are currently checking if an item of your list contains the entered TextBox.Text.
So if the user has entered 3, 4, 5, ..., 13, 23 in the ListBox and searches for 3. He will get 3 matches. If you want only 1 match you should use String.Equals(). I used StringComparison.InvariantCultureIgnoreCase to avoid calling ToLower().
private void buttonSearch_Click(object sender, EventArgs e)
{
var counter = 0;
for (int i = 0; i < this.listBoxAddedIntegers.Items.Count; i++)
{
var item = this.listBoxAddedIntegers.Items[i];
if (string.Equals(item.ToString(), this.textBoxSearch.Text, StringComparison.InvariantCultureIgnoreCase))
{
this.listBoxAddedIntegers.SelectedItems.Add(item);
counter++;
}
}
if (counter == 0)
{
MessageBox.Show($"No matches for \"{this.textBoxSearch.Text}\" found!", "Search Results",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show($"{counter} items found for \"{this.textBoxSearch.Text}\"!", "Search Results",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
Hint:
Since C#6 you can use string interpolation instead of String.Format() or string concatenation (+).
private void buttonSearch_Click(object sender, EventArgs e)
{
listBoxAddedIntegers.SelectedItems.Clear();
var itemsFound = listBoxAddedIntegers.Items.Where(i=>i.ToString().ToLower().Contains(textBoxSearch.Text.ToLower())).ToList();
if(itemsFound == null)
{
MessageBox.Show("No matches found.");
}
else
{
MessageBox.Show("Found " + itemsFound.Count + " matches.");
}
}
You have to do this:
int count=0;
for(int i=0;i<listBoxAddedIntegers.Items.Count;i++)
{
if(listBoxAddedIntegers.Items[i].Items[i].ToString().ToLower().Contains(textBoxSearch.Text.ToLower())
{
count+=1;
}
}
if(count>0)
{
//display your message here after the loop with the count
}
else
{
//display your message with error
}
So one of the forms I have to create is where you enter a first and last name and then it splits the two names and puts them next to the appropriate labels, form design: https://gyazo.com/9b34dca0c1cd464fd865830390fcb743 but when the word stop is entered in any way e.g. Stop, StOp, sToP etc. it needs to end.
private void btnSeparate_Click(object sender, EventArgs e)
{
string strfullname, strgivenname, strfamilyname, strfirstname;
int int_space_location_one, int_space_location_two;
strfullname = txtFullName.Text;
int_space_location_one = strfullname.IndexOf(" ");
strgivenname = strfullname.Substring(0, int_space_location_one);
lblGivenEntered.Text = strgivenname;
strfirstname = strfullname.Remove(0, int_space_location_one + 1);
int_space_location_two = strfirstname.IndexOf(" ");
strfamilyname = strfirstname.Substring(int_space_location_two + 1);
lblFamilyEntered.Text = strfamilyname;
}
This is my current code, I have tried many different ways to get the word stop to end it but it wont work so that's why there is currently no code trying to stop the program, the main problem I get is because it is searching for a space between the first and last name and it obviously doesn't have one for one word it just crashes.
Any help with this would be amazing, thanks in advance.
Just hook up the TextChanged event and go like this:
private void TextChanged(Object sender, EventArgs e)
{
// If text, converted to lower-characters contains "stop" -> Exit
if(txtFullName.Text.ToLower().Contains("stop"))
{
// What I understand as "stopping it".
Application.Exit();
}
}
IF with "stop it" you mean to cancle the operation:
private void btnSeparate_Click(object sender, EventArgs e)
{
// If text, converted to lower-characters contains "stop" -> Exit
if (txtFullName.Text.ToLower().Contains("stop"))
{
// What I understand as "stopping it".
Application.Exit();
}
else
{
// Your code inside the else block
}
}
Short version of everything: Also covering no spaces problem
private void btnSeparate_Click(object sender, EventArgs e)
{
// Save how many words are inside
int wordsInText = txtFullName.Text.Split(' ').Length;
// Save if "stop" was typed into the textbox
bool stopExisting = !txtFullName.Text.ToLower().Contains("stop");
// If text has exactly 3 words and "stop" is NOT existing
if (wordsInText == 3 && !stopExisting)
{
// Save array of splitted parts
string[] nameParts = txtFullName.Text.Split(' ');
// This is never used??
string strfirstname = nameParts[1];
// Set name-parts to labels
lblGivenEntered.Text = nameParts[0];
lblFamilyEntered.Text = nameParts[2];
}
// If text has NOT exactly 3 words and "stop" is NOT existing
else if(wordsInText != 3 && !stopExisting)
{
// If there are no 3 words, handle it here - MessageBox?
}
// If "stop" IS existing
else if(stopExisting)
{
// If text contains "stop" handle it here
// Application.Exit(); <-- if you really want to exit
}
}
You could just check, if one of the entered words is equal to the word "stop". There you need a StringComparions which ignores the case. Or you could parse the entered word into lower/upper-cases.
So if the check is true, you could just end the program with
Environment.Exit(0);
You could just check, if one of the entered words is equal to the word "stop". There you need a StringComparions which ignores the case. Or you could parse the entered word into lower/upper-cases.
So if the check is true, you could just end the program with
Environment.Exit(0);
Code:
if (strfullname.ToLowerInvariant().Contains("stop"))
{
Environment.Exit(0);
}
I am creating a windows form that is a random number guessing game. I've made these before in C++ and never had an issue, however I have a big one here- I have no idea how to get the user back to input a number after the loop has began running. Here is my code:
private void btnGuess_Click(object sender, EventArgs e)
{
int guess = 0;
int count = 0;
int accumulator = 0; // accumulator
Random rand = new Random();
int number = rand.Next(1, 100);
txtAnswer.Focus();
while (guess != number)
{
guess = int.Parse(txtAnswer.Text);
if (guess < number)
{
MessageBox.Show("Too Low! Guess again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else if (guess > number)
{
MessageBox.Show("Too High! Try again!");
txtAnswer.Text = "";
txtAnswer.Focus();
count++;
accumulator++;
}
else
{
MessageBox.Show("Correct! you guessed the number in " + accumulator + " tries!");
break;
}
}
}
}
}
I just filled the while loop arguments with something for you guys, even though i know it won't work. Basically, I need to run the loop, get feedback (if the users guess was too high or low) then get the user to be able to input another number BEFORE the loop runs again. I don't know how to get that to happen with a text box control which is where the input will be. Any ideas?
You should not loop inside in the btnGuess_Click. Instead you need to store the state (the number, count, and the accumulator variables) in the scope of the form itself.
Initialize the random number when the form loads, or using some kind of start button.
Then inside the guess button handler, read the text box value and compare it to the number variable, such as what you are doing currently.
What you are building is more a console style application. So there is 1 main loop that is executing all the code.
In forms applications it is an event driven environment. So the user gets a form, presses a button, the form is evaluated and then the method handling ends.
So you have on a class level some variables for counts, in the constructor you add the initialization and the method for submit will be something like
private void btnGuess_Click(object sender, EventArgs e)
{
//Increment counters
//Check
//Show feedback
//Leave the button click code
}
For some more info, check this out:
https://msdn.microsoft.com/en-us/library/dd492132.aspx
I have a simple while loop that allows me to find text within a textbox, but when I am searching for a word that appears several times in the textbox, it locks up the interface for a while. I'd like to move it into a background worker, but I don't think this can be done because the interface elements (i.e. textbox3.text) are on the main thread. How can I make a background worker when the main interface elements are involved?
I found decent information on the web, but I am having trouble implementing other solutions I have read into my particular situation.
public void button2_Click(object sender, EventArgs e)
{
//Highlight text when search button is clicked
int index = 0;
while (index < dragDropRichTextBox1.Text.LastIndexOf(textBox3.Text))
{
dragDropRichTextBox1.Find(textBox3.Text, index, dragDropRichTextBox1.TextLength, RichTextBoxFinds.None);
dragDropRichTextBox1.SelectionBackColor = Color.Orange;
index = dragDropRichTextBox1.Text.IndexOf(textBox3.Text, index) + 1;
}
}
Thanks for the help.
I guess what you want to do is create sub thread doing the job not to block the UI thread ( pseudo-code, aka not tested ) :
public void button2_Click(object sender, EventArgs e)
{
// Copy text in a non-thread protected string, to be used within the thread sub-routine.
string searchText = textBox3.Text;
string contentText = dragDropRichTextBox1.Text;
// Create thread routine
ThreadPool.QueueUserWorkItem(o => {
// Iterate through all instances of the string.
int index = 0;
while (index < contentText.LastIndexOf(searchText))
{
dragDropRichTextBox1.Invoke((MethodInvoker) delegate {
// Update control within UI thread
//Highlight text when search button is clicked
dragDropRichTextBox1.Find(searchText, index, contentText.Length, RichTextBoxFinds.None);
dragDropRichTextBox1.SelectionBackColor = Color.Orange;
}
// Go to next instance
index = contentText.IndexOf(searchText, index) + 1;
}
});
}
Again, this is untested, but that would give you the idea.
-- EDIT --
You don't need threading at all, doing all the work between a dragDropRichTextBox1.SuspendLayout() and dragDropRichTextBox1.ResumeLayout() is enough.
private void button1_Click(object sender, EventArgs e)
{
// Copy text in a non-thread protected string, to be used within the thread sub-routine.
string searchText = textBox1.Text;
string contentText = richTextBox1.Text;
// Suspend all UI refresh, so time won't be lost after each Find
richTextBox1.SuspendLayout();
// Iterate through all instances of the string.
int index = 0;
while (index < contentText.LastIndexOf(searchText))
{
//Highlight text when search button is clicked
richTextBox1.Find(searchText, index, contentText.Length, RichTextBoxFinds.None);
richTextBox1.SelectionBackColor = Color.Orange;
// Go to next instance
index = contentText.IndexOf(searchText, index) + 1;
}
// Finally, resume UI layout and at once get all selections.
richTextBox1.ResumeLayout();
}
You just need to use invoke when you're manipulating the UI elements in your background thread
https://msdn.microsoft.com/en-us/library/vstudio/ms171728(v=vs.100).aspx
You can call the Invoke Method on the control.
dragDropRichTextBox1.Invoke((MethodInvoker) delegate {
//Your code goes here for whatever you want to do.
}
);
This should fix your problem.
I'm trying to loop through the text in a textbox by word in order to spellcheck it. I've split the contents of the textbox into an array, and loop through each word in the array and run it through the spellchecker. When a misspelling is found, I have a popup with a listbox inside it display so that you can choose the correction.
The issue that I'm having, is that it just loops through the whole array and only ends up showing the last correction that needs to be done.
How do I pause the loop so that it waits for a selection to be made and then resume?
Here's the code for the loop:
foreach(string checkedWord in articleWords)
{
bool success = _spellChecker.CheckWord(checkedWord);
List<string> suggest;
if (!success)
{
suggest = _spellChecker.GetSuggestions(checkedWord);
SpellChecklistBox.Items.Clear();
foreach (string s in suggest)
{
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = s });
}
SpellCheckerPopup.IsOpen = true;
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = " ----------------------" });
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = "Ignore" });
}
}
When the SpellCheckerPopup displays, I have an event trigger in the listbox on SelectionChange.
Basically, I need to pause the loop somehow, and then when the SelectionChange event does it's thing, have the loop resume.
Thanks in advance!
-Sootah
If I'm not misunderstanding, currently you are going to:
(1) Check each word in the loop
(2) Pause the loop when an error is found and pop up a suggestion window
(3) User select a suggestion word and resume the loop
I think it's better and easier if the solution is:
(1) Check the word from the first one
(2) Quit the check method with an error flag, and store the position in a variable, pop up a suggestion window
(3) User selects a suggestion word and when User has confirmed the suggestion(e.g. pressing OK on the suggestion window), start the CheckWordMethod again from the stored position
(4) Until step (2) quits with no error flag, which means all words are correct now (but make sure in the whole progress, users can only modify the words by your suggestion window)
#The Smartest: Your answer lead me in the correct direction; actually ended up learning a new datatype out of it! Never used a Queue before. (Which made it a HELL of a lot simpler than having to track where in the array I was at, as I first figured I thought I'd have to.. :)
Anyway, I'll accept your answer, but here's the code I ended up doing: (The actual replacing of the word in the textbox I've not implemented yet.)
private void btnSpelling_Click(object sender, RoutedEventArgs e)
{
SpellChecklistBox.Items.Clear();
string[] articleWordsArray = txtArticle.Text.Split(' ');
foreach (string word in articleWordsArray)
{
articleWords.Enqueue(word);
}
CorrectWord();
}
private void SpellChecklistBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SpellCheckerPopup.IsOpen = false;
}
private void SpellCheckerPopup_Closed(object sender, EventArgs e)
{
CorrectWord();
SpellChecklistBox.Items.Clear();
}
Queue<string> articleWords = new Queue<string>();
private void CorrectWord()
{
if (articleWords.Count() > 0)
{
string checkedWord = articleWords.Dequeue();
bool success = _spellChecker.CheckWord(checkedWord);
List<string> suggest;
if (!success)
{
suggest = _spellChecker.GetSuggestions(checkedWord);
foreach (string s in suggest)
{
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = s });
}
SpellCheckerPopup.IsOpen = true;
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = " ----------------------" });
SpellChecklistBox.Items.Add(new ListBoxItem() { Content = "Ignore" });
SpellCheckerPopup.IsOpen = true;
}
}
}
It's all pretty straight forward courtesy of the Queue datatype. When the spelling button gets clicked it loads the TextBox into an array, and then I loop through the array to enqueue the items into the articleWords queue, after which it calls CorrectWord(). CorrectWord() then loads the relevant list after dequeueing from articleWords, and on the PopUp. Closed event it clears the ListBox and calls CorrectWord() which will keep bringing back the PopUp until there are no more words to be corrected. :)