C# Change a created objects value from another class - c#

I have a Main.class which runs a timer at 5 seconds (when it resets i want to do a bunch of methods and then repeat the timer). I have a Water.class with a currentReserve-property and a pop.class with a CurrentThirst and MaximumThirst-propertys. In the Pop class i have a method thats get called when the timer reset. Basically i want the popclass to consume the currentReserve-int in the object which i have created in the Mainclass. I provide the essential code and mark with comments where the debugger thinks iam wrong:
public AITest()
{
public Water _water;
public Pop _pop;
Timer dayTimer = new Timer();
int timeLeft = 5;
public AITest()
{
InitializeComponent();
_water = new Water(8000);
lblWater.Text = _water.CurrentReserve.ToString();
_pop = new Pop(100, 100);
dayTimer.Interval = 1000;
dayTimer.Enabled = true;
dayTimer.Tick += dayTimer_Tick;
dayTimer.Start();
lblCountDown.Text = timeLeft.ToString();
}
private void dayTimer_Tick(object sender, EventArgs e)
{
lblCountDown.Text = timeLeft.ToString();
timeLeft -= 1;
if (timeLeft < 0)
{
timeLeft = 5;
_water.CurrentReserve += 100;
_pop.HaveToDrink();
lblWater.Text = _water.CurrentReserve.ToString();
}
}
}
}
public class Pop
{
public int CurrentThirst { get; set; }
public int MaximumThirst { get; set; }
public Water _water;
public Pop(int currentThirst, int maximumThirst)
{
CurrentThirst = currentThirst;
MaximumThirst = maximumThirst;
}
public void HaveToDrink()
{
CurrentThirst -= 30;
_water.CurrentReserve -= 30; //Here i get an error
}
}
public class Water
{
public int CurrentReserve { get; set; }
public Water(int currentReserve)
{
CurrentReserve = currentReserve;
}
}

You've got a _water member twice: once in AITest and once in the Pop class. Use only one, and pass it around. The exception you get will be a NullReferenceException, because nothing is ever assigned to the Pop._water member.

Related

MultiThread stopWatch timer in WinForms

I want to run timer every 10 miliseconds and update GUI label string. I have create Class TimerController, were i can set up System.Threading.Timer properties.
class TimerControl
{
private Timer _timer;
public DateTime StartTime { get; private set; }
public TimeSpan CurrentElapsedTime { get; private set; }
public TimeSpan TotalElapsedTime { get; private set; }
public event EventHandler Tick;
public bool IsTimerRunning { get; private set; }
public string CurrentElapsedTimeString { get; private set; } = "";
public TimerCallback TimerAction { get; private set; }
public object TimerParametr { get; private set; }
public int DueTime { get; private set; }
public int Period { get; private set; }
public TimerControl(TimerCallback timerAction, object state, int dueTime, int period)
{
StartTime = DateTime.Now;
CurrentElapsedTime = TimeSpan.Zero;
TotalElapsedTime = TimeSpan.Zero;
TimerAction = timerAction;
TimerParametr = state;
DueTime = dueTime;
Period = period;
}
public void StartTimer()
{
StartTime = DateTime.Now;
TotalElapsedTime = CurrentElapsedTime;
IsTimerRunning = true;
if (_timer == null)
_timer = new Timer(TimerAction, TimerParametr, DueTime, Period);
else
_timer.Change(DueTime, Period);
}
public void StopTimer()
{
_timer.Change(0, -1);
}
I create TimerControl object in MainForm.cs and I need to create function, that will be triggered by a timer. This function should update GUI time label. But in this function i dont habe access to GUI. How to fix it?
TimerControl timerControl = new TimerControl(StopWatchTimer,null, 0, 10);
public MainForm()
{
InitializeComponent();
}
private void btn_timerStart_Click(object sender, EventArgs e)
{
if(btn_timerStart.Text == "Старт")
{
timerControl.StartTimer();
btn_timerStart.Text = "Стоп";
}
else
{
timerControl.StopTimer();
btn_timerStart.Text = "Старт";
}
}
// Callback timer funnction
private static void StopWatchTimer(object label)
{
//labelTime = // labelTime doesnt exist in current context
}
}
}
I did it like that, everything works fine.
public partial class MainForm : Form
{
TimerControl timerControl;
public MainForm()
{
InitializeComponent();
timerControl = new TimerControl(StopWatchTimer, l_timer, 0, 10);
}
private void btn_timerStart_Click(object sender, EventArgs e)
{
if(btn_timerStart.Text == "Старт")
{
timerControl.StartTimer();
btn_timerStart.Text = "Стоп";
}
else
{
timerControl.StopTimer();
btn_timerStart.Text = "Старт";
}
}
private void StopWatchTimer(object label)
{
Label timeLabel = (Label)label;
TimeSpan elapsed = DateTime.Now - timerControl.StartTime;
this.Invoke(new MethodInvoker(delegate ()
{
timeLabel.Text = elapsed.ToString(#"ss\.ff");
}));
}
}
enter image description here

C# Blazor WebAssembly: Argument 2: cannot convert from 'void' to 'Microsoft.AspNetCore.Components.EventCallback'

I'm new to blazor C# and trying to make a simple countdown timer website. My website consist of:
Text to display the timer
Start and stop button
Buttons to set the timer
I'm having a problem in the buttons to set the timer. When i click on it, it won't set the timer display and i got an error Argument 2: cannot convert from 'void' to 'Microsoft.AspNetCore.Components.EventCallback'. I search on Youtube for the EventCallback topic but the problem is, my component is not seperated while in the video the example code got seperated components linked together. Here's the code.
Index.razor
#page "/"
#inherits FrontEnd.Components.Timer
<h1>Timer</h1>
<p class="timer">#Hours.ToString("00"):#Minutes.ToString("00"):#Seconds.ToString("00")</p>
#foreach (var timer in timerCollections)
{
// Here's the problem
<button #onclick="SetTimer(timer.Id)">#timer.Hours.ToString("00"):#timer.Minutes.ToString("00"):#timer.Seconds.ToString("00")</button>
}
<br/>
<button #onclick="StartTimer" disabled=#StartButtonIsDisabled>Start</button>
<button #onclick="StopTimer" disabled=#StopButtonIsDisabled>Stop</button>
Timer.cs
using System;
using System.Timers;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components;
namespace FrontEnd.Components
{
public class TimerStructure
{
public int Id { get; set; }
public int Hours { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
}
public class Timer : ComponentBase
{
public List<TimerStructure> timerCollections = new List<TimerStructure>(){
new TimerStructure(){ Id = 1, Hours = 0, Minutes = 30, Seconds = 0 },
new TimerStructure(){ Id = 2, Hours = 1, Minutes = 0, Seconds = 0 }
};
public int Index { get; private set; }
public int Hours { get; set; } = 0;
public int Minutes { get; set; } = 0;
public int Seconds { get; set; } = 0;
public bool StopButtonIsDisabled { get; set; } = true;
public bool StartButtonIsDisabled { get; set; } = false;
private static System.Timers.Timer aTimer;
// and this is the function related to the problem
public void SetTimer(int value)
{
this.Index = value - 1;
Hours = timerCollections[Index].Hours;
Minutes = timerCollections[Index].Minutes;
Seconds = timerCollections[Index].Seconds;
}
public void StopTimer()
{
aTimer.Stop();
aTimer.Dispose();
StopButtonIsDisabled = true;
StartButtonIsDisabled = false;
Console.WriteLine($"{Hours}:{Minutes}:{Seconds}");
}
public void StartTimer()
{
aTimer = new System.Timers.Timer(1000);
aTimer.Elapsed += CountDownTimer;
aTimer.Start();
StopButtonIsDisabled = false;
StartButtonIsDisabled = true;
}
public void CountDownTimer(Object source, ElapsedEventArgs e)
{
if(Seconds == 0 && Minutes > 0)
{
Minutes -= 1;
Seconds = 59;
} else if (Minutes == 0 && Seconds == 0 && Hours > 0)
{
Hours -= 1;
Minutes = 59;
Seconds = 59;
} else if (Hours == 0 && Minutes == 0 && Seconds == 0)
{
aTimer.Stop();
aTimer.Dispose();
StopButtonIsDisabled = true;
StartButtonIsDisabled = false;
} else
{
Seconds -= 1;
}
InvokeAsync(StateHasChanged);
}
}
}
Try: <button #onclick="() => SetTimer(timer.Id)">

Round Counter using Get and Set C#

Im using Get; and Set; im trying to make a round counter when user inputs Rounds, Minutes, and seconds. Ive managed to create the buttons and input using Get; Set; ... the problem is when the time reaches 0 for minutes and seconds it doesnt reset the minutes and seconds to the original value the user entered the first time, it just keeps it at 0.... Please help.. I didnt add the button or timer start code that all works just the get set problem
class User
{
public static int Rounds { get; set; }
public static int InputRounds { get; set; }
public static int Sec { get; set; }
public static int Min { get; set; }
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e){
User.sec--;
if(User.sec <= 0)
{
User.Min--;
}
if(User.Min <= 0)
{
User.Rounds++;
}
if(User.Rounds >= User.InputRounds) // User.Input is the first value the user input
{
User.Min = ????; // This is my problem with the question marks
User.Sec = ????; // Im trying to set the value back to the users value entered
User.Rounds++; // then add 1 round
}
}
Maybe you just need to refactor your User class, and please don't use static properties unless necessary.
public class User
{
private int oMin;
private int oSec;
public User(int min, int sec, int maxRounds)
{
Min = min;
oMin = min; // Saving Original Values
Sec = sec;
oSec = sec; // Saving Original Values
MaxRounds = maxRounds;
}
public int Rounds { get; private set; }
public int MaxRounds { get; }
public int Sec { get; private set; }
public int Min { get; private set; }
public void ReduceSec()
{
Sec--;
if (Sec <= 0)
{
Min--;
}
if (Min <= 0)
{
Rounds++;
}
if (Rounds >= MaxRounds)
{
Min = oMin;
Sec = oSec;
Rounds++;
}
}
}

Take the sum of a list as variable and edit it at runtime

I'm trying to calculate the end value of a specific variable that depends whether a checkbox is checked. This is however dynamically done.
What I'm trying to achieve:
The example above works fine but it starts going wrong when I start to uncheck the check boxes. It subtracts by the double amount of the time and I have no idea why:
My Code (TimeSpent is the variable that I want to have at the end):
Class
public class Activity
{
public int ID { get; set; }
public int IncidentID { get; set; }
public string Description { get; set; }
public int TimeSpent { get; set; }
public static int StartX { get; set; } = 10;
public static int StartY { get; set; } = 10;
private TextBox textBox = null;
private CheckBox checkBox = null;
public Activity(int iD, int incidentID, string description, int timeSpent)
{
this.ID = iD;
this.IncidentID = incidentID;
this.Description = description;
this.TimeSpent = timeSpent;
}
public Activity()
{ }
public bool isChecked() {
return checkBox.Checked;
}
public void setTimeSpent(int timeSpent) {
this.TimeSpent = timeSpent;
textBox.Text = timeSpent.ToString();
}
public int getTimeSpent()
{
return Int32.Parse(textBox.Text);
}
public void DrawToForm(Panel p)
{
var label = new Label();
textBox = new TextBox();
checkBox = new CheckBox();
checkBox.Checked = true;
textBox.Size = new System.Drawing.Size(40, 20);
label.Text = Description.ToString();
label.AutoSize = true;
textBox.Text = TimeSpent.ToString();
label.Left = StartX;
label.Top = StartY;
StartX += 430;// Move position to right
textBox.Left = StartX;
textBox.Top = StartY;
StartX += 160;// Move position to right
checkBox.Left = StartX;
checkBox.Top = StartY;
StartX = 10;// Reset to start
StartY += 50;// Move position to down
p.Controls.Add(label);
p.Controls.Add(textBox);
p.Controls.Add(checkBox);
}
}
GUI:
private void Btn_Validate_Click(object sender, EventArgs e)
{
tb_TotalTime.Text = calculateTotalTime().ToString();
}
public int calculateTotalTime()
{
int total = 0;
foreach (Activity a in activities)
{
if(a.isChecked())
{
total += a.getTimeSpent();
}else
{
total -= a.getTimeSpent();
}
}
return total;
}
Why is subtracting not done correctly?
You subtract when the checkbox is not checked:
if(a.isChecked())
{
total += a.getTimeSpent();
}
else
{
total -= a.getTimeSpent();// << THIS
}
So with the setup of your 2nd image (top 2 unchecked bottom one checked) you do this:
0 - 5 - 5 + 5 = -5
The 0 comes from the default value of Total (int)
To fix this you could just remove the else clause as you don't need to subtract billable time ever.
You should remove subtracting at all.
So change it to :
if(a.isChecked())
{
total += a.getTimeSpent();
}
You have total=0, you have not added all values before calculating. So you don't need subtracting.
Your logic is add if Check subtract if unchecked. Your logic should be add if Checked only.
private void Btn_Validate_Click(object sender, EventArgs e)
{
tb_TotalTime.Text = calculateTotalTime().ToString();
}
public int calculateTotalTime()
{
int total = 0;
foreach (Activity a in activities)
{
if (a.isChecked())
{
total += a.getTimeSpent();
}
}
return total;
}

returning actual Height and Width to wpf rectangle after dynamic change

I have an app with the main window which contains a rectangle and a button that leads to another window in which the user enters information. After entering info, user clicks on a button and it returns him to the main window and changes the size accordingly. What I am trying to achieve is to return the ActualHeight and ActualWidth to the rectangle if a user presses the button in the main window again, kind of a refresh of rectangle.
All the code is in the Main Window Button click event. If you need any specific information about the code, i will gladly give it to you.
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Questionnaire q = new Questionnaire();
q.ShowDialog();
var size = q.textBoxNumberOfEmployees.Text;
if (int.Parse(size) > 5 && int.Parse(size) < 15)
{
Rect1.Height = Rect1.ActualHeight - 10;
Rect1.Width = Rect1.ActualWidth - 5;
}
else if (int.Parse(size) > 15 && int.Parse(size) < 30)
{
Rect1.Height = Rect1.ActualHeight - 15;
Rect1.Width = Rect1.ActualWidth - 10;
}
else if (int.Parse(size) > 30 && int.Parse(size) < 100)
{
Rect1.Height = Rect1.ActualHeight - 30;
Rect1.Width = Rect1.ActualWidth - 15;
}
else
{
Rect1.Height = Rect1.ActualHeight;
Rect1.Width = Rect1.ActualWidth;
}
You can store the original height and width of rectangle in variables in form load. Use those variables to make rectangle to original size bebore opening new window in button click.
Following code goes at the top inside your form.
private int rect1width;
private int rect1height;
In your form__load you write this at the end.
rect1width = Rect1.ActualWidth;
rect1height = Rect1.ActualHeight;
In your button click code following code goes at top.
Rect1.Width = rect1width;
Rect1.Height = rect1height;
Here is some seemingly long code, but it uses an MVC type design pattern and compounds with the state pattern. The only thing really missing to make it true MVC is Observers and observable interfaces that would subscribe to the Questionnaire.
public interface RectangleState
{
int myHeight { get; set; }
int myWidth { get; set; }
}
public class RectangleModel
{
private static Rectangle Rect1;
public RectangleModel(Rectangle rect1 )
{
Rect1 = rect1;
}
private RectangleState state;
public RectangleState State
{
get
{
return state;
}
set
{
state = value;
ModifyState(value.myHeight, value.myWidth);
}
}
private void ModifyState(int Height, int Width)
{
Rect1.Height = Height;
Rect1.Width = Width;
}
}
public class SmallState : RectangleState
{
public int myHeight { get; set; } = 20;
public int myWidth { get; set; } = 80;
}
public class MediumState : RectangleState
{
public int myHeight { get; set; } = 25;
public int myWidth { get; set; } = 90;
}
public class LargeState : RectangleState
{
public int myHeight { get; set; } = 35;
public int myWidth { get; set; } = 120;
}
public class NormalState : RectangleState
{
public int myHeight { get; set; } = 30;
public int myWidth { get; set; } = 100;
}
Now all you need to do is plug in the conditions:
RectangleModel RM = new RectangleModel(myRectangle); // store this in your class as property;
int size = 0;
int.TryParse(q.textBoxNumberOfEmployees.Text, out size);
if (size > 5 && size < 15)
{
RM.State = new SmallState();
}
else if (size > 15 && size < 30)
{
RM.State = new MediumState();
}
else if (size > 30 && size < 100)
{
RM.State = new LargeState();
}
else
{
RM.State = new NormalState();
}
If later you decide you want to change the default values on any of these you can change them. If you wish to add a new Rectangle shape or size you can add it. If you wish to create an adapter to further modify the rectangle, you can do so. This is a nice pattern. I know the answer looks overdone, but I think you will find it works solidly and is quite flexible when plugged into the code that accesses your questionaire.

Categories

Resources