Reputation: 63
I want my program to constantly change the font background color, but I want it to go smoothly so I tried to modify a Color variable Color custom;
and use it to for the background color of the form this.BackColor = custom;
but it doesn't work and I don't know how to make it work, here is the complete code:
private void Principal_Load(object sender, EventArgs e)
{
Color custom;
int contr = 0, contg = 0, contb = 0;
do
{
while (contr < 255 && contg == 0)
{
if (contb != 0)
{
contb--;
}
contr++;
while (contg < 255 && contb == 0)
{
if (contr != 0)
{
contr--;
}
contg++;
while (contb < 255 && contr == 0)
{
if (contg != 0)
{
contg--;
}
contb++;
}
}
}
custom = Color.FromArgb(contr, contg, contb);
this.BackColor = custom;
} while (true);
}
Upvotes: 6
Views: 1269
Reputation: 117019
To start with, your current code doesn't work, but not because of any threading issue (although that does need to be solved).
The issue is that these lines never get hit:
custom = Color.FromArgb(contr, contg, contb);
this.BackColor = custom;
The logic in your while
loops just don't work.
The values that you produce are the set of:
(0, 0, 1), (0, 0, 2) ... (0, 0, 255), (0, 254, 1), (0, 253, 2) ... (0, 1, 254)
It then just repeated tries to produce those values, but can never break out of the while (contr < 255 && contg == 0)
loop.
Now, assuming that's actually what you wanted then I suggest the best approach to do this is using Microsoft's Reactive Framework. Just NugGet "Rx-WinForms" and you can then write this code:
var ranges = new[]
{
Observable.Range(1, 255).Select(x => Color.FromArgb(0, 0, x)),
Observable.Range(1, 254).Select(x => Color.FromArgb(0, 255 - x, x)),
};
var query =
ranges
.Concat()
.Zip(Observable.Interval(TimeSpan.FromMilliseconds(100.0)), (x, i) => x)
.Repeat()
.ObserveOn(this);
var subscription = query.Subscribe(c => this.BackColor = c);
So ranges
is an array of IObservable<Color>
. Calling .Concat()
on ranges
turns it from IObservable<Color>[]
to IObservable<Color>
. The .Zip
ties each value to a timer counting off in 10ms increments (you can change the value if you wish). Calling .Repeat()
just repeats the loop continuously - sort of like while (true)
. Then .ObserveOn(this)
forces the observable subscription to be run on the UI thread.
Finally, the .Subscribe(...)
actually runs the observable and updates the BackColor
of the form.
The nice thing about this is that you can stop the subscription at any time by calling .Dispose()
on the subscription:
subscription.Dispose();
That cleans up all of the threads and the timer. It's a very neat solution.
Upvotes: 1