мигающие метки backColor в C#

У меня есть эта форма, содержащая 4 ярлыка. Я хочу, чтобы эти метки мигали с определенной частотой, например 12,5, 10, 8 и 4 Гц. Я использовал таймер, но он не будет работать правильно, они мигают с гораздо меньшей частотой, я знаю, что это из-за вложенных ifs в freqMethod ниже. Как мне решить эту проблему?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Timers;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        System.Timers.Timer mainTimer; 
        private int counter = 0;
        Color lColor = Color.FromArgb(255, 192, 128);
        bool buttonPressed = false;

        public Form1()
        {

            InitializeComponent();
            label1.BackColor = lColor;
            label2.BackColor = lColor;
            label3.BackColor = lColor;
            label4.BackColor = lColor;
            mainTimer = new System.Timers.Timer(1);
            mainTimer.Elapsed += new ElapsedEventHandler(timerElapsed);
        }


        private void button2_Click(object sender, EventArgs e)
        {   
            if (buttonPressed)
            {
                mainTimer.Enabled = false;
                buttonPressed = !buttonPressed;
                counter = 0;
            }
            else
            {

                mainTimer.Enabled = true;
                buttonPressed = !buttonPressed;
                counter = 0;
            }
        }

        //Frequency Method

        public void freqMethod()
        {
           if (counter % 80 == 0)
               if (label4.backColor == lColor)
                   label4.backColor = Color.black;
               else
                   label4.backColor = lColor;
           if (counter % 100 == 0)
               if (label3.backColor == lColor)
                   label3.backColor = Color.black;
               else
                   label3.backColor = lColor;
           if (counter % 125 == 0)
               if (label2.backColor == lColor)
                   label2.backColor = Color.black;
               else
                   label2.backColor = lColor;
           if (counter % 250 == 0)
               if (label1.backColor == lColor)
                   label1.backColor = Color.black;
               else
                   label1.backColor = lColor;



        }
        private void timerElapsed(object source, ElapsedEventArgs e) {
            counter++;
            freqMethod();
        }

    }
}

person Ako    schedule 17.07.2015    source источник


Ответы (3)


Вам не нужен таймер для повторения каждую секунду, поскольку вы пропускаете каждые n итераций, поскольку они занимают слишком много ресурсов. Вы можете просто манипулировать значением Timer Interval, чтобы получить требуемую частоту с адекватной производительностью.

Например, для частоты 8 Гц вам нужен только таймер для запуска события каждые 125 мс (8 раз в секунду).
Я приведу пример с частотой double, чтобы он работал с интервалами ‹ 1. Например. , если вы установите частоту 0.5, цвет будет меняться каждые 2 секунды.

Пример:

public Form1()
{
    double frequencyInHz = 8.0; // here goes your frequency
    int interval = (int)Math.Round(1000.0 / frequencyInHz); // 125ms in this case
    mainTimer = new Timer(interval);
    mainTimer.Elapsed += new ElapsedEventHandler(timerElapsed);
}   

private void timerElapsed(object source, ElapsedEventArgs e) {
    if (label2.BackColor == lColor)
        label2.BackColor = Color.Black;
    else
        label2.BackColor = lColor;
}

Если вам нужно, чтобы несколько меток меняли свой цвет на разные, вам нужно будет сделать несколько таймеров, чтобы получить хорошую производительность.

person Yeldar Kurmangaliyev    schedule 17.07.2015
comment
Просто имейте в виду, что минимальный интервал этого таймера составляет 15 мс, если я не ошибаюсь. - person Jens; 17.07.2015
comment
Таким образом, я думаю, мне следует использовать несколько таймеров, или есть лучший способ сделать это? - person Ako; 17.07.2015
comment
@ user4949420 Да. На мой взгляд, это наиболее эффективный подход. Конечно, если у вас есть соответствующее количество меток и таймеров — например, 4 или 5. - person Yeldar Kurmangaliyev; 17.07.2015

Учитывая следующие значения (и если вы хотите синхронизировать их с помощью одного таймера), общий интервал, который они могут иметь, составляет 5 мс. Итак, вам нужно поставить таймер на 5 мс и проверить частоту. Но обратите внимание на использование таймера, как описано ниже:

12.5hz = 80ms
10hz   = 100ms
8hz    = 125ms
4hz    = 250ms

Примечания из MSDN с использованием System.Timers.Timer (https://msdn.microsoft.com/en-us/library/system.timers.timer.interval(v=vs.110).aspx) См. раздел примечаний.

Свойство Interval используется для определения частоты, с которой запускается событие Elapsed. Поскольку класс Timer зависит от системных часов, он имеет то же разрешение, что и системные часы. Это означает, что событие Elapsed будет срабатывать с интервалом, определяемым разрешением системных часов, если свойство Interval меньше разрешения системных часов. В следующем примере для свойства Interval задается значение 5 миллисекунд. При запуске в системе Windows 7, системные часы которой имеют разрешение примерно 15 миллисекунд, событие срабатывает примерно каждые 15 миллисекунд, а не каждые 5 миллисекунд.

Но если вы можете использовать несколько таймеров для каждого, то вы можете установить каждый интервал таймера, как упомянул Йелдар.

person Joel Legaspi Enriquez    schedule 17.07.2015

Попробуйте это (в дополнение к модификации интервала таймера, предложенной Джоэлом или Йелдаром):

if (counter % 80 == 0)
{
  label4.backColor = label4.backColor == lColor ? Color.black : lColor;
  label4.Refresh() ;
}
person Graffito    schedule 17.07.2015
comment
я видел что-то подобное в другом месте, что именно означает эта строка? label4.backColor = label4.backColor == lColor ? Цвет.черный : lЦвет; - person Ako; 17.07.2015
comment
х = логическое условие? a : b — это компактный способ кодирования if (BoolCondition) x=a ; иначе х=b; - person Graffito; 17.07.2015