2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Помогите разобраться с таймером...
Сообщение02.12.2008, 20:02 
Здраствуйте. Ситуация такова - имеется программа, автоматически отрисовываящая рандомный график. Все это делается в Timer...
Но проблема в том, что выбор 1 милисекунды в качестве интервала таймера и 1000 милисекунд никакой видимой разницы не дает.
Скажите пожалуйста, что не так в этом коде:

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windef.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
Timer1->Enabled = false;
Form1->DoubleBuffered = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Graphics::TBitmap *btm1=new Graphics::TBitmap;
float ypos=0;
    float  st, x, y, z, min;
    float shirina;
    shirina = 150;
    y=250;
    z=250;
    st = 4;
    min = 10;

    btm1->Canvas->Pen->Style = psSolid;
    btm1->Canvas->Pen->Width = st;

      btm1->Canvas->Brush->Color = clBlack;
      btm1->Canvas->FillRect(Rect(0, 0, btm1->Width,
      btm1->Height));
                        btm1->Width = (shirina*(st+1));
btm1->Height = z;
ypos = btm1->Height;
ypos+=min;
x=-(st/2);
btm1->Canvas->Pen->Color = clLime;
randomize();
for (int k=0; k<150; k++)
{
x+=(st+1);
btm1->Canvas->MoveTo(x, ypos);
btm1->Canvas->LineTo(x, ypos-(random(y)));
}
PaintBox1->Canvas->CopyMode = cmSrcCopy;
PaintBox1->Canvas->Draw(0,0, btm1);
delete btm1;
}
//---------------------------------------------------------------------------

 
 
 
 
Сообщение02.12.2008, 20:39 
Аватара пользователя
В таймере лучше поставить refresh или repaint. А отрисовку делать в обработчике OnPaint

 
 
 
 
Сообщение03.12.2008, 18:14 
Возможно 1 мсек - слишком маленький интервал времени.
Попробуйте сравнить 1000 мсек и, скажем, 5000 мсек.

Хотя это и не имеет прямого отношения к вопросу, к совету Pavia присоединяюсь.

 
 
 
 
Сообщение04.12.2008, 08:46 
Практика показывает, что меньше 10 мс ставить бесполезно, а будет ли заметна разница между 10 мс и 1000 мс - зависит от сложности кода (сколько он займет проц. времени) в функции таймера.

 
 
 
 
Сообщение04.12.2008, 11:36 
Всем спасибо! буду пробовать...

Добавлено спустя 23 минуты 23 секунды:

Pavia писал(а):
В таймере лучше поставить refresh или repaint. А отрисовку делать в обработчике OnPaint

Вы такой код имели ввиду? :
Код:
.......
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
Graphics::TBitmap *btm1=new Graphics::TBitmap;
float ypos=0;
    float  st, x, y, z, min;
    float shirina;
    shirina = 150;
    y=250;
    z=250;
    st = 4;
    min = 10;

    btm1->Canvas->Pen->Style = psSolid;
    btm1->Canvas->Pen->Width = st;

      btm1->Canvas->Brush->Color = clBlack;
      btm1->Canvas->FillRect(Rect(0, 0, btm1->Width,
      btm1->Height));
                        btm1->Width = (shirina*(st+1));
btm1->Height = z;

PaintBox1->Width = btm1->Width;
PaintBox1->Height = btm1->Height;

ypos = btm1->Height;
ypos+=min;
x=-(st/2);
btm1->Canvas->Pen->Color = clLime;
randomize();
for (int k=0; k<150; k++)
{
x+=(st+1);
btm1->Canvas->MoveTo(x, ypos);
btm1->Canvas->LineTo(x, ypos-(random(y)));
}
PaintBox1->Canvas->CopyMode = cmSrcCopy;
PaintBox1->Canvas->Draw(0,0, btm1);
delete btm1;
}
//---------------------------------------------------------------------------


Странно, но лишь при первом нажатии кнопки график обновляется с нужной частотой=( далее идет по-старому. Что 15 мс, что 1000. Да и код тут вроде не такой сложный, чтобы занимать много процессорного времени.

 
 
 
 
Сообщение04.12.2008, 13:39 
Аватара пользователя
Скорее всего, всё дело в randomize().

Дело в том, что randomize, скорее всего, реализована примерно так, как у меня в BDS 2006:
Код:
inline void _RTLENTRY randomize(void)
{
    srand((unsigned) time(NULL));
}

Т.е. последовательность "случайных" значений, возвращаемых функцией random(), будет полностью определяться тем, что вернёт функция time() в момент вызова randomize(), а time() возвращает разные значения не чаще, чем раз в секунду :D
Соответственно, Ваши графики исправно рисуются 100 или там 1000 раз в секунду (зависит от того, насколько шустра видеокарта), но в течение секунды выводят одно и то же. Если убрать из конструктора
Код:
Form1->DoubleBuffered = true;
, то это должно стать хорошо заметно.

Мораль: нет никакой необходимости вызывать функцию randomize() чаще, чем один раз за всё время работы приложения (т.е. в самом начале программы).
Уберите randomize() из рисующей функции и поставьте её в конструктор формы (например). Всё должно заработать на ура.

 
 
 
 
Сообщение04.12.2008, 18:48 
worm2 писал(а):
Скорее всего, всё дело в randomize().

Дело в том, что randomize, скорее всего, реализована примерно так, как у меня в BDS 2006:
Код:
inline void _RTLENTRY randomize(void)
{
    srand((unsigned) time(NULL));
}


Мораль: нет никакой необходимости вызывать функцию randomize() чаще, чем один раз за всё время работы приложения (т.е. в самом начале программы).
Уберите randomize() из рисующей функции и поставьте её в конструктор формы (например). Всё должно заработать на ура.

worm2, СПАСИБО ВАМ ГРОМАДНОЕ! Вы даже не представляете, сколько времени я бился над этой ерундой! Спасибо!
PS а что дает doublebuffered? я когда разбирался с мерцанием экрана, просто мне посоветовали его включить, и все, не обьясняя сути свойства.

 
 
 
 
Сообщение04.12.2008, 19:31 
Аватара пользователя
Насколько я помню (смотреть сейчас лень, можно поискать в справке по билдеру), при включении этого свойства всё рисование на PaintBox1->Canvas выполняется в памяти, и лишь по его окончании выводится на форму, чем снижает мерцание.
Но у Вас, вроде бы, рисование на холсте элемента PaintBox1 выполняется только один раз:
Код:
PaintBox1->Canvas->Draw(0,0, btm1);

поэтому, возможно, в предыдущем сообщении я не прав и, вроде как, DoubleBuffered не играет роли, только лишнюю память использует...

Добавлено спустя 4 минуты 51 секунду:

А может быть, DoubleBuffer всё-таки помогает, потому что перед вызовом обработчика события OnPaint Windows очищает элементы на форме, заливая их цветом фона... В общем, точно не знаю...

 
 
 
 
Сообщение05.12.2008, 21:57 
worm2 писал(а):
Насколько я помню (смотреть сейчас лень, можно поискать в справке по билдеру), при включении этого свойства всё рисование на PaintBox1->Canvas выполняется в памяти, и лишь по его окончании выводится на форму, чем снижает мерцание.
Но у Вас, вроде бы, рисование на холсте элемента PaintBox1 выполняется только один раз:
Код:
PaintBox1->Canvas->Draw(0,0, btm1);

поэтому, возможно, в предыдущем сообщении я не прав и, вроде как, DoubleBuffered не играет роли, только лишнюю память использует...

Добавлено спустя 4 минуты 51 секунду:

А может быть, DoubleBuffer всё-таки помогает, потому что перед вызовом обработчика события OnPaint Windows очищает элементы на форме, заливая их цветом фона... В общем, точно не знаю...

Все-таки он помогает! Я когда создавал компонент на основе пэйнтбокса, специально включил его в код для проверки. Даже с использованием канвы битмапа с последующим копированием ее на канву самого компонента непосредственно происходит некоторое мерцание(разумеется, при малых значениях интервала таймера). При включении буферизации мерцание практически сводится на нет.

 
 
 [ Сообщений: 9 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group