How does timer work ? (it only works when i resize the window in my case)

İ created a class that loads images according to a timercallback. It is a really wierd thing that timercallback works when i try to debug my code but when i run it as a standalone to test it i cannot see those picture unless i resize my plugin window.

in my lamp class

  Lamp::Lamp()
{
counter = 0;
setBounds(getBounds());

 }

 Lamp::~Lamp()
{
}

 void Lamp::paint (Graphics& g)
  {

   Rectangle<int> lampCropArea(0, 0, 70, 70);
   lampImage = lampImage.getClippedImage(lampCropArea);
   lampImage = lampImage.rescaled(getWidth(), getHeight(), 
   Graphics::highResamplingQuality);
   Rectangle<float> lampArea(getX(), getY(), getWidth(), getHeight());
   g.drawImage(lampImage, lampArea);
   }

  void Lamp::blink(Graphics& g, int clockRate)// BPM
   {
    	if (!isTimerRunning())
             {
         startTimer(1 / ((clockRate / 60) * 1000 * 24)); /*BPM to period in 
             milliseconds+ devided 24 for calling 24  images each time*/
              }
            paint(g);

    }


   void Lamp::timerCallback()
      {

         ++counter;
         int value = getTimerInterval();
         DBG(getTimerInterval());
     lampImage  = ImageCache::getFromMemory(returnImageName(counter), returnImageSize(counter));
       stopTimer();
       if (counter == 26) { counter = 0; }
 }

and i just create an instance in my plugin editor to call lamp like this

      lamp.blink(g, 5000); /*5000 for testing */

I thought when i create a timer and start it with an interval it is supposed to wait will that interval value (in milliseconds) than brach to timercallback(). After doing what i want in it i call stoptimer to stop it. Am I wrong ? what would you suggest me ?

Why are you starting and stopping the timer and don’t just let it run continuously? Why doesn’t your timerCallback repaint() the component? If you don’t do that, the component graphics are updated only on resize and some other spurious events from the OS. You shouldn’t call paint() yourself. It’s not going to update what you see on the screen. Only calling repaint() causes the components to update from your code.

You are attempting to resize the image at each paint() call, with a high quality. That is going to be expensive to do.

Also this in your constructor doesn’t really make sense : setBounds(getBounds());? What do you think that is going to do…?

Your timer is NaN for clockRates less than 60. You are doing integer divisions.

1 Like

You don’t call paint() directly. Painting is done asynchronously. I don’t know where are you calling blink() from, but you shouldn’t pass Graphics contexts from one component to another. The idea is that you change your data, and when you need a repaint you call repaint() to get paint() called later by the message loop. Also, integer divisions will give you integer results, and I think you intended to divide by 24, not multiply. Assuming returnImageName and returnImageSize are ok and take 0…23, I guess it would be something like

void Lamp::blink(int clockRate)
{
    if (counter == 0) startTimer(int(60000.f / 24.f / clockRate));
}

void Lamp::timerCallback()
{
    lampImage = ImageCache::getFromMemory(returnImageName(counter), returnImageSize(counter));
    repaint();
    if (++counter == 24)
    {
        stopTimer();
        counter = 0;
    }
}

And of course, setBounds(getBounds()) won’t do anything at all.

Here’s a simple component that can start and run an animation cycle :

class ColorSwitchingComponent : public Component, public Timer
{
public:
	ColorSwitchingComponent()
	{}
	void timerCallback() override
	{
		++m_state;
		if (m_state == 4)
			m_state = 0;
		if (Time::getMillisecondCounterHiRes() - m_start_time >= m_duration_to_switch)
		{
			stopTimer();
			m_state = 0;
		}
		repaint();
	}
	void paint(Graphics& g) override
	{
		static const Colour colors[4] = { Colours::black,Colours::yellow,Colours::green,Colours::red };
		g.fillAll(colors[m_state]);
	}
	void startSwitching(double durationSeconds, double updateInterval=0.25)
	{
		m_start_time = Time::getMillisecondCounterHiRes();
		m_duration_to_switch = durationSeconds*1000.0;
		startTimer(updateInterval*1000.0); 
	}
private:
	int m_state = 0;
	double m_start_time = 0.0;
	double m_duration_to_switch = 1.0;
};

It could be done in a different way too, with say, MultiTimer, but the approach above has worked for me…

thank you for answering :pray: i was planin to starting point and stopping points to calculata time duration. i know i could do it by calling gettimerInterval and saving these two times but i thought it could be better to do it that way. Looks like im terriblly wrong :slight_smile: how would you suggest me to use repaint() ? just a little bit of example code would be great because it says that repaint is not going to repaint it immidiately.

:smiley: now it is in resized :smiley:

Actually, as Xenakios pointed, what should be in resized() (or even somewhere else if you know all possible sizes beforehand) is the rescaling of the images. Also, lampArea is basically getBounds(), but that will give you the bounds with respect to the parent component -I think you want getLocalBounds().

Also have a look at the demos:

and

thank you everyone. :pray: it will try to learn from these examples :slight_smile: