I'm newbie for C# and i have a little project. I'm stucked somewhere. I explained it here (with sample source codes) :
I have a form application. I'm asking users select an option from 2 buttons. There are 2 buttons (YES and NO) . My codes like this :
public partial class Form1 : Form
{
public int choice=0;
public Form1()
{
if(choice == 0)
{
label.Text = "Please push one of these buttons :";
// And there are buttons below this label
}
else if(choice == 1)
{
label.Text = "You just pushed YES button";
}
else if(choice == 2)
{
label.Text = "You just pushed NO button";
}
}
private void buttonYes_Click(object sender, EventArgs e)
{
choice = 1;
/*
I have to use one of these here for redraw whole form
this.Refresh();
this.Invalidate();
*/
}
private void buttonNo_Click(object sender, EventArgs e)
{
choice = 2;
/*
I have to use one of these here for redraw whole form
this.Refresh();
this.Invalidate();
*/
}
}
As you see, when user click one of YES or NO button, whole constructor function should be re-executed. And label should be "You just pushed YES / NO button".
But when i use this.Refresh() , nothing happening when i clik buttons. Still label is "Please push one of these buttons :" .
When i use this.Invalidate() , all buttons disappering, and label is still "Please push one of these buttons :" .
What should i do ?
Thanks.
PS
I've found this question BEFORE ask this one. But as you see, accepted answer not working for me.
Invalidating or refreshing doesn't call the constructor again. The constructor is called exactly once when the form is created, and invalidating doesn't create a new form. Put the logic for changing stuff in another method and call that from the constructor AND from the event handlers - but do note for posterity that calling instance methods or accessing variables from the constructor isn't really the nicest way of doing this stuff - but for your purposes here it's the simple solution.
public partial class Form1 : Form
{
public int choice=0;
public Form1()
{
UpdateForm();
}
private void UpdateForm(){
if(choice == 0)
{
label.Text = "Please push one of these buttons :";
// And there are buttons below this label
}
else if(choice == 1)
{
label.Text = "You just pushed YES button";
}
else if(choice == 2)
{
label.Text = "You just pushed NO button";
}
}
private void buttonYes_Click(object sender, EventArgs e)
{
choice = 1;
/*
I have to use one of these here for redraw whole form
this.Refresh();
this.Invalidate();
*/
UpdateForm();
}
private void buttonNo_Click(object sender, EventArgs e)
{
choice = 2;
/*
I have to use one of these here for redraw whole form
this.Refresh();
this.Invalidate();
*/
UpdateForm();
}
}
This is how you really should be doing it:
public partial class Form1 : Form
{
public Form1()
{
// Isn't there supposed to be InitializeComponent() here?
// You should assign this in the designer, rather than here.
label.Text = "Please push one of these buttons :";
}
private void buttonYes_Click(object sender, EventArgs e)
{
label.Text = "You just pushed YES button";
}
private void buttonNo_Click(object sender, EventArgs e)
{
label.Text = "You just pushed NO button";
}
}
Since all the button is doing is changing a label, that should be done directly, not though changing a variable and refreshing.
But why didn't it work my way?
All Refresh and Invalidate do is redraw what is already on your form. They don't recreate it.
A constructor is designed to initialize an object once, when you create it. It cannot be called to 'reinitialize' or 'refresh' an object.
To avoid going into too much detail, I recommend you find an article/book on object oriented programming to learn more about constructors and other OOP idioms.
This is the best option if you want to keep the same variables as in the exemple. If you want a shorter version just change the label directly in the Form1 Constructor.
public partial class Form1 : Form
{
public int choice=0;
public Form1()
{
buttonYes.Click += (s,e) => {
choice = 1;
ChangeText(choice);};
buttonNo.Click += (s,e) => {
choice = 2;
ChangeText(choice);};
}
private void ChangeText(int userChoice)
{
if(choice == 0)
label.Text = "Please push one of these buttons :";
else if(choice == 1)
label.Text = "You just pushed YES button";
else if(choice == 2)
label.Text = "You just pushed NO button";
}
}
Shorter Version
public partial class Form1 : Form
{
public Form1()
{
label.Text = "Push a button";
buttonYes.Click += (s,e) => {label.Text = "Yes is pressed";};
buttonNo.Click += (s,e) => {label.Text = "No is pressed";};
}
}
Main Constructor execute when new object created .
use an Method for do this . and i am shore this will work
public string TextSwitcher(int choice)
{
Switch(choice) // choice is an int
{
// 1,2,3 is not an serial no they will pass by parameter
case(1):
return "Please push one of these buttons :";
brake;
case(2):
return = "You just pushed YES button";
brake;
case(3)
return = "You just pushed NO button";
brake;
}
}
private void buttonYes_Click(object sender, EventArgs e)
{
label.Text = TextSwitcher(2);
}
private void buttonNo_Click(object sender, EventArgs e)
{
label.Text = TextSwitcher(3);
}
i hop this will help you . and welcome for you'r thank's .
best of luck
Related
Frist of all, I'm a beginner in C# and I want to become a game dev one day. So here I am! Asking about this simple question for you, but not for me.
The question is, I wanted my code to change text when I press the button. Imagine you're playing text-based adventure game which I'm trying to make here, and when you press the button it'll change the text each time when you press it.
But my code doesn't, here is my code enter image description here
The code is not wrong, but it doesn't work as I expected. It'll show only the last one but not from the first to last.
If you can help me develop my knowledge about this I'd be thankful so much.
You can cycle through an array or a List.
Here is a very simple exemple:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace TextLineByLine
{
public partial class Form1 : Form
{
List<string> Messages = new List<string>();
int currentLine = -1;
public Form1()
{
InitializeComponent();
// Add some messages
Messages.Add("You open your eyes");
Messages.Add("The bright blue sky is up there");
Messages.Add("And some blood covers the ground");
Messages.Add("You're not sure what happened...");
}
private void button1_Click(object sender, EventArgs e)
{
currentLine++; // increment the line index
if (currentLine < Messages.Count)
{
Title.Text = Messages[currentLine];
}
else
{
Title.Text = "-= Nothing to display =-";
}
}
}
}
Well you can create a string array for your sentences like this and do the following.
int counter = 0;
private void btnAction_Click(object sender, RoutedEventArgs e)
{
string[] messages = new string[4]
messages[0] = "Your first message";
messages[1] = "Your second message";
messages[2] = "Your third message";
messages[3] = "Your fourth message";
title.Text = messages[0];
counter++;
}
if I understand your question well you want a text change each time it is pressed.
You can do it easily by using an Integer for example.
public partial class MainWindow : Window
{
int dialogue = 0;
public MainWindow() { InitializeComponent(); }
private void btnAction_Clickl(object sender, RoutedEventArgs e)
{
switch ( dialogue )
{
case 0:
Title.Text = "Some text";
dialogue++;
break;
case 1:
Title.Text = "Another text";
dialogue++;
break;
default: //just in case you want to reset the text
Title.Text = "First text";
dialogue = 0;
break;
}
}
}
If you want to set it automatic, like just one click and then the text changes every x seconds you can use:
public partial class MainWindow : Window
{
public MainWindow() { InitializeComponent(); }
private void btnAction_Clickl(object sender, RoutedEventArgs e)
{
Dialogue();
}
private async void Dialogue()
{
Title.Text = "Some text";
await Task.Delay(2000); // Where 2000 means 2 seconds in milliseconds
Title.Text = "More text"; // And so on...
}
}
Have a nice day.
I just finished an exercise from Head First C# where I built a Typing Game. The book leaves it to the reader to figure out how to make it so the player can start a new game once they've lost. After the user loses the game, the window shows the message "Game Over". I would like to have a new window pop up and ask the user if they would like to play again once they've closed out of the game over screen. I'd like there to be two buttons; one that says "no" and one that says "yes". What I'm stuck on is how I should (or would) go about restarting the app if the user decides they want to play again. I'll copy and paste my code below:
namespace _7HeadFirstProject
{
public partial class Form1 : Form
{
Random random = new Random();
Stats stats = new Stats();
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
// Add a random key to the ListBox
listBox1.Items.Add((Keys)random.Next(65, 90));
if (listBox1.Items.Count > 7)
{
listBox1.Items.Clear();
listBox1.Items.Add("Game Over");
timer1.Stop();
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
// If the user pressed a key that's in the ListBox...
// ... remove it and then make the game a little faster
if (listBox1.Items.Contains(e.KeyCode))
{
listBox1.Items.Remove(e.KeyCode);
listBox1.Refresh();
if (timer1.Interval > 400)
timer1.Interval -= 10;
if (timer1.Interval > 250)
timer1.Interval -= 7;
if (timer1.Interval > 100)
timer1.Interval -= 2;
difficultyProgressBar.Value = 800 - timer1.Interval;
// The user pressed a correct key, so update the Stats object...
// ...by calling its Update() method with the argument true
stats.Update(true);
}
else
{
// The user pressed an incorrect key, so update the Stats object...
// ...by calling its Update() method with the argument false
stats.Update(false);
}
// Update the labels on the StatusStrip
correctLabel.Text = "Correct: " + stats.Correct;
missedLabel.Text = "Missed: " + stats.Missed;
totalLabel.Text = "Total: " + stats.Total;
accuracyLabel.Text = "Accuracy: " + stats.Accuracy + "%";
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
MessageBox.Show("Would you like to play again?");
if
}
}
}
DIFFERENT CLASS:
namespace _7HeadFirstProject
{
class Stats
{
public int Total = 0;
public int Missed = 0;
public int Correct = 0;
public int Accuracy = 0;
public void Update(bool correctKey)
{
Total++;
if (!correctKey)
{
Missed++;
}
else
{
Correct++;
}
Accuracy = 100 * Correct / Total;
}
}
}
You have the whole game working so leave that form alone. Add another form to your project and then set the new form as the startup form. You can set it as the startup form by opening Program.cs and modifying this line:
// Instead of Form1 put the name of your new form
Application.Run(new Form1());
Double click the new form and put this code in it:
// Note: Your load method may have a different name.
private void Form2_Load(object sender, EventArgs e)
{
this.StartNewGame();
}
private void GameForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (MessageBox.Show("Continue?", "Continue?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
this.StartNewGame();
}
}
private void StartNewGame()
{
// Your game form may have a different name so change this to that name
var gameForm = new Form2();
gameForm.FormClosed += GameForm_FormClosed;
gameForm.Show();
}
Every time the user presses the yes button on the dialog, you are creating a brand new instance of the form (of the game). In this new form, you can also have an array which keeps track of the total number of games and what the score of each game was so you can show it in case the user selected No. All you need is something like this:
var games = new List<Stats>();
// keep adding to it every time you call StartNewGame() method.
Try this:
if ((MessageBox.Show("Would you like to play again?", "Message", MessageBoxButtons.YesNo)) ==
DialogResult.Yes)
{
Application.Restart();
}
I am trying to pull a label text into another form inside the same solution to use in an if statement. However, it seems as though it's not pulling the data from the field. I am trying to change the color of the label background based on the label text in form 1. Any help is greatly appreciated.
IN FORM 1:
public void button1_Click(object sender, EventArgs e)
{
form1 view = new form();
view.Show();
view.label1 = label1.Text.ToString();
}
IN FORM 2:
public string label1 { get; set; }
public void Display()
{
if (label1 == "1")
{
for (int i = 0; i < nWinnings.Length; i++)
{
Label label = new Label();
label.BackColor = Color.Red;
...
}
}
else
{
for (int i = 0; i < nWinnings.Length; i++)
{
Label label = new Label();
label.BackColor = Color.Blue;
...
}
}
}
There is more to the label but the label is working fine minus the color change.
This is incorrect:
Label label = new Label();
You cannot create a new instance of your Label... it has absolutely no connection to the original Label instance in the first Form, and changing any property on it will not affect the original one either.
You'll need to pass a reference to the entire Label:
// Form 1
public void button1_Click(object sender, EventArgs e)
{
form1 view = new form();
view.label1 = label1;
view.Show();
}
// Form 2
public Label label1 { get; set; }
public void Display()
{
if (label1.Text == "1")
{
for (int i = 0; i < nWinnings.Length; i++)
{
label1.BackColor = Color.Red;
// ... etc, etc
I'd limit how much passing around of references to controls you do to other Forms. In my experience, code starts to get quite muddy when you do that too much.
If what I understood is correct, you have 2 forms. FORM1 & FORM2.
You have a label control LABEL1 in FORM1. You read this text and pass it to FORM2.
In FORM2, you have another label control LABEL2, whose background color you want to change.
You can declare a string variable in FORM2.
Add a new constructor to FORM2 to accept a string argument, and set this value to the string variable.
In FORM2 OnLoad, you can then check the value of your string variable and
then,
LABEL2.BackColor = whateverColor in the if-else loop.
something like this in FORM1
FORM2 newForm = new FORM2(LABEL1.Text);
newForm.Show();
and in FORM2
private label1String = String.Empty();
public FORM2(string arg)
{
...Default Initialization Code...
label1String = arg;
}
private void ChangeLabel2Color()
{
if(label1String == "1")
{
LABEL2.BackColor = whateverColorYouNeed;
}
else
{
...WHATEVER YOU NEED TO DO...
}
}
I wrote the code directly, so there might be syntax errors.
My form transition is slow when I click button, I am using thread to have a form effect that form opacity starts from 0.1 and increase the number. Then I have a method and start the method from Form_Load in thread.
private void RunTimer_Tick_Things()
{
if (flag)
{
while (this.Opacity <= cs.CheckMaxOpacityValue())
{
Thread.Sleep(cs.GetTimerSleepNumberToIncreaseOcacity());
if (this.Opacity == cs.CheckMaxOpacityValue())
{
thrdTimer.Abort();
break;
}
this.Opacity += cs.GetIncreasedOpacityValue();
}
}
else
{
while (this.Opacity >= cs.CheckMinOpacityValue())
{
Thread.Sleep(cs.GetTimerSleepNumberToDecreaseOpacity());
this.Opacity -= cs.GetDecreasedOpacityValue();
}
thrdTimer.Abort();
}
}
And I have button in this form to open another form. Like this
private void button2_Click(object sender, EventArgs e)
{
Form2DatabaseSetup frm2 = new Form2DatabaseSetup();
StopThread();
this.Hide();
frm2.Show();
flag = false;
}
My problem is when I click this button the second form is opening slowly.
Consider like, you click the button then the first form hides and waiting for 1,5 second then the second form opens.
Note: The second form has thread and same functions.
Does Anyone has experienced it or know , has a knowledge about this case?
at first i thought you are increasing opacity by 0.01 so 15 * 100 =1.5 exactly what you described, but after you send the values i can see the increase is 0.06, so i think you have some problems with all the function you have ( GetTimerSleepNumberToIncreaseOcacity, GetIncreasedOpacityValue ) .
try instead of the functions to work with hard coded values and work your way up,
i use this code and it works fine:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var f = new Form2();
f.Show();
new Thread(() =>
{
while (f.Opacity < 1)
{
Thread.Sleep(15);
//if (this.Opacity == cs.CheckMaxOpacityValue())
//{
// thrdTimer.Abort();
// break;
//}
f.Invoke((Action)delegate { f.Opacity += 0.06; });
}
}).Start();
}
}
I was wondering if there was a way of adding a sort of animation to text displayed on a form.
What I had in mind when I thought of this was kind of similar to what you can do with text in PowerPoint (i.e. a typewriter-like animation where the text is typed one at a time, have the whole textbox appear with a certain effect etc), I'm just looking to find out what you can do using Windows Forms.
Currently I'm using a textbox to display information on my form application, though in hindsight I realise labels would have worked just as well.
EDIT: Turns out I was using labels after all, I just gave it a name with 'textbox' inside for lack of a better description.
public partial class Form1 : Form
{
int _charIndex = 0;
string _text = "Hello World!!";
public Form1()
{
InitializeComponent();
}
private void button_TypewriteText_Click(object sender, EventArgs e)
{
_charIndex = 0;
label1.Text = string.Empty;
Thread t = new Thread(new ThreadStart(this.TypewriteText));
t.Start();
}
private void TypewriteText()
{
while (_charIndex < _text.Length)
{
Thread.Sleep(500);
label1.Invoke(new Action(() =>
{
label1.Text += _text[_charIndex];
}));
_charIndex++;
}
}
}
Now, I personally wouldn't do this because gratuitous animations tend to annoy users. I'd only use animation sparingly - when it really makes sense.
That said, you can certainly do something like:
string stuff = "This is some text that looks like it is being typed.";
int pos = 0;
Timer t;
public Form1()
{
InitializeComponent();
t = new Timer();
t.Interval = 500;
t.Tick += new EventHandler(t_Tick);
}
void t_Tick(object sender, EventArgs e)
{
if (pos < stuff.Length)
{
textBox1.AppendText(stuff.Substring(pos, 1));
++pos;
}
else
{
t.Stop();
}
}
private void button1_Click(object sender, EventArgs e)
{
pos = 0;
textBox1.Clear();
t.Start();
}
or something like that. It'll tick off ever half second and add another character to the multi-line text box. Just an example of what someone could do.