I was trying to have my Form's background change when I press a button with a transition.
I figured the most simple and fast way to do this would be to put a white panel over my Form, with a blank backcolor, and to change its alpha component from 0 to 250 then from 250 to 0 when I click the button.
When alpha reaches its maximum value, I want to change the background image.
This technique worked like an hour ago, but now the color does not change at all, and my code is not entirely executed.
Here's the function that is called by the Timer :
private void ChangeIndex(object sender, EventArgs e)
{
if (progressBar.Value == progressBar.Maximum-progressBar.Step)
{
t.Stop();
btnDébut.Enabled = true;
btnFin.Enabled = true;
btnPrécédent.Enabled = true;
btnSuivant.Enabled = true;
if (indiceCourant >= dt.Rows.Count)
{
this.indiceCourant = 0;
}
lblChargement.Visible = false;
progressBar.Visible = false;
RemplitChamps(indiceCourant);
}
progressBar.Step = 10;
progressBar.Maximum = 200;
progressBar.PerformStep();
MessageBox.Show(progressBar.Value.ToString() + " " + pnlFondEcran.BackColor.A.ToString() + " " + progressBar.Maximum.ToString());
if(progressBar.Value <100)
{
this.pnlFondEcran.BackColor = System.Drawing.Color.FromArgb(pnlFondEcran.BackColor.A + progressBar.Maximum/progressBar.Step,255, 255,255);
// i wanna add 24 each time, until alpha=240
}
else
{
MessageBox.Show("error");
this.pnlFondEcran.BackColor = System.Drawing.Color.FromArgb(pnlFondEcran.BackColor.A -progressBar.Maximum / progressBar.Step, 255, 255, 255);
//then substract 24 each time
}
}
The Panel's name is pnlFondEcran.
The progressbar works fine.
The MessageBox.Show(some stuff )'s ouptpur is 0,20,40... to 200, 0, 200.
The progressBar.Value<100 statement is never evaluated until the first last time the function is called, I have no idea why.
Here's the method calling ChangeIndex() :
private void DebutTimer()//lance le timer pour la progressbar
{
lblChargement.Visible = true;
progressBar.Visible = true;
progressBar.Value = 0;
//gestion du timer
t = new System.Windows.Forms.Timer();
t.Interval = 150;
t.Enabled = true;
t.Tick += new EventHandler(ChangeIndex);
t.Start();
//gestion des boutons
btnDébut.Enabled = false;
btnFin.Enabled = false;
btnPrécédent.Enabled = false;
btnSuivant.Enabled = false;
}
Related
I'm trying to code a Simon Says game and I ran into a problem. I cannot figure out how to make my Randomizer timer (that randomizes which boxes are lit up) to run by waves. I want it to run once, then when it's referred to again - run twice and so on.
This is RandomPlace():
private PictureBox RandomPlace()
{
PictureBox p = new PictureBox();
Random rnd = new Random();
switch (rnd.Next(1, 5))
{
case 1:
p = TopRight;
break;
case 2:
p = TopLeft;
break;
case 3:
p = BottomRight;
break;
case 4:
p = BottomLeft;
break;
}
return p;
} //Gets a random PictureBox
This is RandomImage():
private void RandomImage()
{
TopLeft.Enabled = false;
TopRight.Enabled = false;
BottomLeft.Enabled = false;
BottomRight.Enabled = false;
PictureBox a = RandomPlace();
if (a == TopLeft)
{
TopLeft.Image = Resources.TopLeftLit;
label1.Text = "TopLeft";
Thread.Sleep(500);
TopLeft.Image = Resources.TopLeft;
label2.Text = "TopLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 1;
patternRightNow++;
}
if (a == TopRight)
{
TopRight.Image = Resources.TopRightLit;
label1.Text = "TopRight";
Thread.Sleep(500);
TopRight.Image = Resources.TopRight;
label2.Text = "TopRightAFTERSLEEP"; //FIGURE OUT HOW TO RESET PICTURE
Thread.Sleep(500);
pattern[patternRightNow] = 2;
patternRightNow++;
}
if (a == BottomLeft)
{
this.BottomLeft.Image = Resources.BottomLeftLit;
label1.Text = "BottomLeft";
Thread.Sleep(500);
this.BottomLeft.Image = Resources.BottomLeft;
label2.Text = "BottomLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 3;
patternRightNow++;
}
if (a == BottomRight)
{
this.BottomRight.Image = Resources.BottomRightLit;
label1.Text = "BottomRight";
Thread.Sleep(500);
this.BottomRight.Image = Resources.BottomRight;
label2.Text = "BottomRightAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 4;
patternRightNow++;
}
} //Lits up the random PictureBoxes and sets them back to normal
This is Randomizer_Tick():
rivate void Randomizer_Tick(object sender, EventArgs e)
{
RandomImage();
patternRightNow = 0;
tickCount++;
Randomizer.Stop();
ClickCheck();
} //Use RandomImage() to lit up random PictureBoxes on 5 waves, wave 1 - 1 PictureBox, wave 2 - 2 PictureBoxes and so on.
This is ClickCheck():
private void ClickCheck()
{
TopLeft.Enabled = true;
TopRight.Enabled = true;
BottomLeft.Enabled = true;
BottomRight.Enabled = true;
if (tickCount == clickCount)
{
CheckIfWin();
Randomizer.Start();
}
} //Enables the PictureBoxes to be pressed, after the user input reaches the current wave's amount of PictureBoxes lit up, disable PictureBoxes again and start the randomizer
Instead of using timers, I advise you to look at Tasks. It's much easier to create such statemachines.
Fill a list with colors and play it. Wait until the user pressed enough buttons and check the results.
For example: (haven't tested it, it's just for example/pseudo code)
It might contain some typo's.
private List<int> _sequence = new List<int>();
private List<int> _userInput = new List<int>();
private Random _rnd = new Random(DataTime.UtcNow.Milliseconds);
private bool _running = true;
private bool _inputEnabled = false;
private TaskCompletionSource<object> _userInputReady;
public async void ButtonStart_Click(object sender, EventArgs e)
{
if(_running)
return;
while(_running)
{
// add a color/button
_sequence.Add(_rnd.Next(4));
// play the sequence
for(int color in _sequence)
{
// light-up your image, whatever
Console.WriteLine(color);
// wait here...
await Task.Delay(300);
// turn-off your image, whatever
}
// clear userinput
_userInput.Clear();
_userInputReady = new TaskCompletionSource<object>();
_inputEnabled = true;
// wait for user input.
await _userInputReady.Task;
// compare the user input to the sequence.
for(int i=0;i<_sequence.Count;i++)
{
if(_sequence[i] != _userInput[i])
{
_running = false;
break;
}
}
}
Console.WriteLine("Not correct");
}
// one handler for all buttons. Use the .Tag property to store 0, 1, 2, 3
public void ButtonClick(object sender, EventArgs e)
{
if(!_inputEnabled)
return;
var button = (Button)sender;
// add user input to the queue
_userInput.Add((int)button.Tag);
if(_userInput.Count >= _sequence.Count)
_userInputReady.SetResult(null);
}
So want to be able to pause and resume my chart and text box from updating when I click a button. Currently, now it just updates in real-time time. I have attached my code below, I've tried ResumeUpdates() and PauseUpdates() for chart but it does not work for the textboxes I have no idea. The data im getting is stored in an ArrayList with originally comes from a serial port
Edit: if I have initraph() within mmy button function and call it from there it calls it once and gets updated once.
first button click =chart and textboxes updates in realtime
second button click = chart and textboxes pause
third button click = chart and textboxes resume updating
private void InitChart()
{
if (!b)
{
speedRecordChart.ChartAreas[0].AxisX.Maximum = 200;
speedRecordChart.ChartAreas[0].AxisX.Minimum = 0;
if (position.lat1 > 90)
{
textBox_analLat.Text = position.latComp1 + position.lat1 / 100;
}
else
{
textBox_analLat.Text = position.latComp1 + position.lat1;
}
if (position.lng1 > 180)
{
textBox_analLong.Text = position.lngComp1 + position.lng1 / 100;
}
else
{
textBox_analLong.Text = position.lngComp1 + position.lng1;
}
speedRecordChart.Series["Speed"].Points.Clear();
for (int i = 0; i < totalSpeedList.Count() - 1; ++i)
{
speedRecordChart.Series["Speed"].Points.AddY(totalSpeedList[i]);
}
Console.WriteLine("speedChart : " + totalSpeedList);
}
return;
}
/*****************************************for button**********/
Boolean b = true;
private void button_Resume_Click(object sender, EventArgs e)
{
if (b == true)
{
button_Resume.Text = "resume";
//speedRecordChart.Series.ResumeUpdates();
// serialPort1.Close();
InitChart();
}
else
{
button_Resume.Text = "pause";
// speedRecordChart.Series.SuspendUpdates();
// serialPort1.Open();
}
b = !b;
}
What I'm trying to do is this:
I want the 4 pictureBoxes I got in the form to get the faces of card - turn them over I mean. a random card from the 4 will be chosen, turned over and show the face of the card being chosen also randomley.
Once a card is turned over, it cant be turend over again in the next timer interval, and once all cards had been turned over, a messageBox appears and once the user presses ok, it all restarts.
Problem is: the messageBox keeps appearing over and over again, because of the flag positive value. I don't know which variable should I use to prevent that from happening.
Relevant code:
//This function is the timer's function, it starts every time interval:
private void cardsChangingTimer_Tick(object sender, EventArgs e)
{
int chosenImage = rnd.Next(1, 17);
int chosenCard = rnd.Next(0, 4);
if (bucketArr[chosenCard] == 0)
{
bucketArr[chosenCard]++;
switch (chosenCard)
{
case 0:
card1Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
break;
case 1:
card2Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
break;
case 2:
card3Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
break;
case 3:
card4Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
break;
}
}
gameEnded = true;
for (int i = 0; i < bucketArr.Length; i++)
{
if (bucketArr[i] == 0)
{
gameEnded = false;
break;
}
}
if (gameEnded)
{
DialogResult dialog = MessageBox.Show("All 4 cards were turned over...");
if (dialog == DialogResult.OK)
{
card1Pic.Image = Image.FromFile("..\\..\\17.png");
card2Pic.Image = Image.FromFile("..\\..\\17.png");
card3Pic.Image = Image.FromFile("..\\..\\17.png");
card4Pic.Image = Image.FromFile("..\\..\\17.png");
}
gameEnded = false;
for(int i = 0; i < bucketArr.Length; i++)
bucketArr[i] = 0;
}
}
Thanks alot for any help...
The problem you are having is the timer is continuing to run while the dialog box is shown. Simply stop the timer before the MessageBox is shown then restart the timer after the box returns.
private void cardsChangingTimer_Tick(object sender, EventArgs e)
{
int chosenImage = rnd.Next(1, 17);
int chosenCard = rnd.Next(0, 4);
/// ... Rest of the code goes here
break;
}
}
if (gameEnded)
{
//Get a reference to the timer and stop it.
var timer = (Timer)sender;
timer.Stop();
DialogResult dialog = MessageBox.Show("All 4 cards were turned over...");
if (dialog == DialogResult.OK)
{
card1Pic.Image = Image.FromFile("..\\..\\17.png");
card2Pic.Image = Image.FromFile("..\\..\\17.png");
card3Pic.Image = Image.FromFile("..\\..\\17.png");
card4Pic.Image = Image.FromFile("..\\..\\17.png");
}
gameEnded = false;
for(int i = 0; i < bucketArr.Length; i++)
bucketArr[i] = 0;
//start the timer here after everything has been re-initialized.
timer.Start();
}
}
I am using chart control in my c# application.Using timer updating values in chart at every 1 seconds.Also i enabled scroll bar for the chart , so the scroll bar is keep on adjusting while the values are adding. Actually my requirement is if i drag the scroll bar and hold at any point it has to freeze at that particular point only.It should not adjust when ever i drag and hold the scroll bar at the particular point.How to do that ? Please refer the code below,
int x1=10, x2=10, y1=10, y2=10; //globally declared
private void button1_Click(object sender, EventArgs e) //chart preparation in button click
{
chart1.Series.Clear();
series1.MarkerStyle = MarkerStyle.Circle;
series1.MarkerColor = Color.BlueViolet;
series1.MarkerSize = 7;
series1.Color = System.Drawing.Color.Green;
series1.IsXValueIndexed = true;
series1.YAxisType = AxisType.Primary;
series1.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series1);
series2.MarkerStyle = MarkerStyle.Circle;
series2.MarkerColor = Color.Orange;
series2.MarkerSize = 7;
series2.Color = System.Drawing.Color.Purple;
series2.IsXValueIndexed = true;
series2.YAxisType = AxisType.Secondary;
series2.ChartType = SeriesChartType.Line;
this.chart1.Series.Add(series2);
chart1.ChartAreas[0].CursorX.AutoScroll = true;
chart1.ChartAreas[0].CursorY.AutoScroll = true;
chart1.ChartAreas[0].AxisX.ScrollBar.Size = 15;
chart1.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All;
chart1.ChartAreas[0].AxisX.ScrollBar.IsPositionedInside = false;
chart1.ChartAreas[0].AxisX.ScrollBar.Enabled = true;
chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.Series[0].Points.AddXY(x1, y1);
chart1.Series[1].Points.AddXY(x2, y2);
chart1.ChartAreas[0].AxisX.ScaleView.Position = chart1.ChartAreas[0].AxisX.Minimum;// scrollPosition;
chart1.ChartAreas[0].AxisX.ScaleView.Zoom(chart1.ChartAreas[0].AxisX.Maximum - nCheck, chart1.ChartAreas[0].AxisX.Maximum);
x1 += 1;
x2 += 1;
nlength++;
if (nlength == 25)
{
nCheck = 30;
chart1.Update();
}
else if (nlength == 50)
nCheck = 50;
timer1.Start();
}
public void createGraph() //called in timer
{
chart1.Series[0].Points.AddXY(x1, y1);
chart1.Series[1].Points.AddXY(x2, y2);
chart1.ChartAreas[0].AxisX.ScaleView.Position = chart1.ChartAreas[0].AxisX.Minimum;// scrollPosition;
chart1.ChartAreas[0].AxisX.ScaleView.Zoom(chart1.ChartAreas[0].AxisX.Maximum - nCheck, chart1.ChartAreas[0].AxisX.Maximum);
x1 += 1;
x2 += 1;
nlength++;
if (nlength == 25)
{
nCheck = 30;
chart1.Update();
}
else if(nlength == 50)
nCheck = 50;
}
private void chart1_AxisScrollBarClicked(object sender, ScrollBarEventArgs e)
{
chart1.ChartAreas[0].CursorX.AutoScroll = false;
chart1.ChartAreas[0].CursorY.AutoScroll = false; //here i need to update some code i think so ...
}
As long as the minimum and maximum of an axis is not set, it will auto-adjust to data. Here is an example where a start of user selection fixes the range of x-axis to current view and applies the selection as zoom and frees the axis range again when selection is completed.
double SelectionStartX=0, SelectionEndX=0;
Chart.SelectionRangeChanging += (object sender, CursorEventArgs e) =>
{
//Record selection to be applied as zoom in SelectionRangeChanged event
SelectionStartX = e.ChartArea.CursorX.SelectionStart;
SelectionEndX = e.ChartArea.CursorX.SelectionEnd;
//Stop motion - Fix x-axis range to width of view
e.Axis.Maximum = e.Axis.ScaleView.ViewMaximum;
e.Axis.Minimum = e.Axis.ScaleView.ViewMinimum;
};
Chart.SelectionRangeChanged += (object sender, CursorEventArgs e) =>
{
//Reset previous zooming and apply only last user selected range
if (e.Axis.ScaleView.IsZoomed)
{
e.Axis.ScaleView.ZoomReset();
e.Axis.ScaleView.Zoom(SelectionStartX, SelectionEndX);
}
//Continue motion - Make chart adaptive to data range
e.Axis.Minimum = double.NaN;
e.Axis.Maximum = double.NaN;
};
I have 16 graphs[maximum ] with 4 fastlines in each graph. In each graph 3 fastlines represent min , max and ideal value. 4th fastline is actual values from the hardware. I have to run the test for 18,000 samples. So , first 3 fastlines are already drawn and when the switch is on and data comes in , 4th fastline is drawn. In order to draw the 4th line, I use the method Series4.Add(actualvalue, "" , color.red) .
here is the problem. each time the sample is drawn on 4th line. chart has to be refreshed in order to view the plotting of that sample. that also redraws the other 3 fastlines with 18,000 samples in each . so it redraws that many samples without use again and again. I need to draw only 4th fastline.
I can not use an array to fill the values up and then assign it as a source of fastline because I dont have any values beforehand. I tried series4.repaint() method and series4.refreshseries() method, but that doesnt repaint 4th series actually. we have to refresh the whole chart.
and therefore, it slows down the performance because of high number of samples in each fastline [18,000] and one graph with 4 fastlines and total 16 graphs like this.
I ve already done
Series4.AutoRepaint = false, Series4.DrawAllPoints = false;
Series4.XValues.Order = ValueListOrder.None , Series4.YValues.Order = ValueListOrder.None
Is there any way I can increase the performance ?
Thank you.
I have made a simple code, where I have added 4 charts with 4 FastLines with 18000 points for each fastline using a table to add a initialize values and after I update only the values of Series4. The performance is good for the number of values I am drawing:
public Form1()
{
InitializeComponent();
InitializeChart();
}
// Steema.TeeChart.Styles.FastLine Series1;
Timer timer1, timer2,timer3, timer4;
Random r;
DateTime dt;
DateTime[] Xvalues1;
double[] Yvalues1;
Steema.TeeChart.TChart tChart1, tChart2, tChart3,tChart4;
private void InitializeChart()
{
tChart1 = new TChart();
tChart2 = new TChart();
tChart3 = new TChart();
tChart4 = new TChart();
this.Controls.Add(tChart1);
this.Controls.Add(tChart2);
this.Controls.Add(tChart3);
this.Controls.Add(tChart4);
//Initialize Locations and size
this.Width = 908;
this.Height = 600;
//Location
tChart1.Left = 12;
tChart1.Top = 53;
tChart2.Left = 468;
tChart2.Top = 53;
tChart3.Left = 12;
tChart3.Top = 318;
tChart4.Left = 468;
tChart4.Top = 318;
//Size
tChart1.Width = 373;
tChart1.Height = 236;
tChart2.Width = 373;
tChart2.Height = 236;
tChart3.Width = 373;
tChart3.Height = 236;
tChart4.Width = 373;
tChart4.Height = 236;
tChart1.Aspect.View3D = false;
tChart2.Aspect.View3D = false;
tChart3.Aspect.View3D = false;
tChart4.Aspect.View3D = false;
tChart1.Legend.Visible = false;
tChart2.Legend.Visible = false;
tChart3.Legend.Visible = false;
tChart4.Legend.Visible = false;
tChart1.Panel.Gradient.Visible = false;
tChart2.Panel.Gradient.Visible = false;
tChart3.Panel.Gradient.Visible = false;
tChart4.Panel.Gradient.Visible = false;
tChart1.Axes.Bottom.AxisPen.Visible = false;
tChart2.Axes.Bottom.AxisPen.Visible = false;
tChart3.Axes.Bottom.AxisPen.Visible = false;
tChart4.Axes.Bottom.AxisPen.Visible = false;
tChart1.Axes.Left.AxisPen.Visible = false;
tChart2.Axes.Left.AxisPen.Visible = false;
tChart3.Axes.Left.AxisPen.Visible = false;
tChart4.Axes.Left.AxisPen.Visible = false;
//Series
tChart1.AutoRepaint = false;
tChart2.AutoRepaint = false;
tChart3.AutoRepaint = false;
tChart4.AutoRepaint = false;
for (int i = 0; i < 4; i++)
{
new Steema.TeeChart.Styles.FastLine(tChart1.Chart);
new Steema.TeeChart.Styles.FastLine(tChart2.Chart);
new Steema.TeeChart.Styles.FastLine(tChart3.Chart);
new Steema.TeeChart.Styles.FastLine(tChart4.Chart);
tChart1[i].XValues.DateTime=true;
tChart2[i].XValues.DateTime = true;
tChart3[i].XValues.DateTime = true;
tChart4[i].XValues.DateTime = true;
InitialDataSeries(tChart1[i]);
InitialDataSeries(tChart2[i]);
InitialDataSeries(tChart3[i]);
InitialDataSeries(tChart4[i]);
}
//Axes labels
tChart1.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart1.Axes.Bottom.Labels.Angle = 90;
tChart2.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart2.Axes.Bottom.Labels.Angle = 90;
tChart3.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart3.Axes.Bottom.Labels.Angle = 90;
tChart4.Axes.Bottom.Labels.DateTimeFormat = "dd/MM";
tChart4.Axes.Bottom.Labels.Angle = 90;
tChart1.AutoRepaint = true;
tChart2.AutoRepaint = true;
tChart3.AutoRepaint = true;
tChart4.AutoRepaint = true;
tChart1.Refresh();
tChart2.Refresh();
tChart3.Refresh();
tChart4.Refresh();
//Timer
timer1 = new Timer();
timer1.Start();
timer1.Interval = 100;
timer1.Tick += new EventHandler(timer1_Tick);
}
void timer1_Tick(object sender, EventArgs e)
{
//See the chart data updated.
tChart1[0].Visible = false;
tChart1[1].Visible = false;
tChart1[2].Visible = false;
PopulateSeries(tChart1[3]);
PopulateSeries(tChart2[3]);
PopulateSeries(tChart3[3]);
PopulateSeries(tChart4[3]);
}
private void PopulateSeries(Steema.TeeChart.Styles.Series Series1)
{
r = new Random();
dt = DateTime.Now;
tChart1.AutoRepaint = false;
tChart2.AutoRepaint = false;
tChart3.AutoRepaint = false;
tChart4.AutoRepaint = false;
// show only 50 points - delete the rest
while (Series1.Count > 10000)
{
Series1.Delete(0);
}
if (Series1.Count > 10000)
{
Series1.Delete(0);
}
else
{
for (int t = 0; t < 100; t++)
{
Series1.Add(dt, r.Next(1000));
dt = dt.AddSeconds(15);
}
}
tChart1.AutoRepaint = true;
tChart2.AutoRepaint = true;
tChart3.AutoRepaint = true;
tChart4.AutoRepaint = true;
tChart1.Refresh();
tChart2.Refresh();
tChart3.Refresh();
tChart4.Refresh();
}
private void InitialDataSeries(Steema.TeeChart.Styles.Series Series1)
{
//Arrays
dt = DateTime.Now;
r = new Random();
Xvalues1 = new DateTime[18000];
Yvalues1 = new double[18000];
(Series1 as Steema.TeeChart.Styles.FastLine).DrawAllPoints = false;
for (int j = 0; j < 18000; j++)
{
Xvalues1[j] = dt;
dt = dt.AddSeconds(15);
Yvalues1[j] = r.Next(1000);
}
Series1.Add(Xvalues1, Yvalues1);
}
Could you tell us if it help you? On the other hand, if my code doesn't help you I recommend you use TeeChartDirect2D, this is ideal for the high speed data throughput required by DSP realtime applications. See the White paper, Boosting graphics-rendering performance in Windows Forms, for a closer look.
Thanks,