§ 18. Кампаненты для работы з табліцамі

18.2. Кампанент DrawGrid

Кампанент DrawGrid выкарыстоўваецца для стварэння табліцы, якая можа ўтрымліваць графічныя малюнкі. На панэлі кампанентаў Additional кампанент DrawGrid намаляваны ў выглядзе , імя аб'екта — DrawGrid. Кампанент DrawGrid, змешчаны на форму, атрымлівае імя DrawGridN, дзе N — нумар 1, 2, 3… (прыклад 18.5).

Гэты кампанент падобны кампаненту StringGrid, які з'яўляецца наследнікам ад DrawGrid. У DrawGrid прысутнічаюць усе ўласцівасці, метады, падзеі кампанента StringGrid, акрамя тых, што адносяцца да тэксту, г. зн. акрамя уласцівасцей Cells, Cols, Rows.

Кампанент DrawGrid (таксама StringGrid) мае канву, на якой можна размяшчаць малюнкі. Для занясення малюнкаў у ячэйкі DrawGrid выкарыстоўваюць апрацоўшчык падзей OnDrawCell. Гэта падзея надыходзіць для кожнай ячэйкі табліцы ў момант яе перамалёўкі. Размяшчаючы ў апрацоўшчыку падзеі OnDrawCell праграмны код, можна размалёўваць ячэйкі, выводзіць малюнкі і рабіць тэкставыя надпісы. Табліца сама пастаянна выклікае гэтую падзею для таго, каб адмаляваць свае ячэйкі. Прамаляваць малюнак можна, выкарыстоўваючы метады канвы StratchDraw або CopyRect.

Апрацоўшчык OnDrawCell мае параметры (прыклад 18.6).

Прыклад 18.7. Стварыць праект, у якім пры выбары ячэйкі табліцы, будзе альбо зафарбоўвацца ячэйка, альбо прамалёўвацца малюнак. Калі сума нумара радка і нумар слупка няцотныя, то адбываецца закраска ячэйкі, інакш прамалёўваецца малюнак.

Этапы выканання задання

  1. Размясціць на форме кампанент DrawGrid.
  2. Выдаліць фіксаваныя радкі і слупкі.
  3. Устанавіць для табліцы 5 радкоў і 5 слупкоў.
  4. Устанавіць шырыню і вышыню слупка роўнай 60.
  5. У падзеі OnCreate для формы загрузіць малюнак у бітавы вобраз.
  6. Напісаць апрацоўшчык падзеі OnDrawCell, у якім замалёўваць ячэйкі.

Калі ўласцівасць DefaultDrawing кампанента DrawGrid мае значэнне true (устаноўлена па змоўчанні), то замалёўвацца будуць толькі выдзеленыя ячэйкі табліцы. Як толькі вылучэнне зменіцца, ячэйка становіцца зафарбаванай тым колерам, які ўстаноўлены па змоўчанні. Калі для ўласцівасці DefaultDrawing устанавіць значэнне false, то пасля змены выдзеленай ячэйкі размалёўка папярэдніх ячэек не мяняецца.

Кампанент DrawGrid зручна выкарыстоўваць для стварэння гульняў на клеткавым полі. Для праграміравання гульні спатрэбіцца матрыца стану гульні. У такой матрыцы будзе захоўвацца абстаноўка гульні на бягучым хаду. Пасля выканання ходу абстаноўка мяняецца, адпаведныя змены запісваюцца ў матрыцу стану і адбываецца абнаўленне кампанента DrawGrid. Матрыца стану гульні можа выкарыстоўвацца для захавання гульні і наступнай яе загрузкі.

Прыклад 18.8. Падрыхтаваць поле гульні ў крыжыкі-нулікі для двух гульцоў.

Этапы выканання задання

  1. Размясціць на форме кампанент DrawGrid і кнопку.
  2. Выдаліць фіксаваныя радкі і слупкі.
  3. Колькасць радкоў і слупкоў роўна 3.
  4. Для захоўвання матрыцы стану гульні апісаць двухмерны масіў pole з 3 радкоў і 3 слупкоў. Стан клеткі будзем апісваць адным з трох значэнняў: 0 — клетка пустая, 1 — у клетцы крыжык, 2 — у клетцы нулік.
  5. Напісаць апрацоўшчык падзеі OnCreat для формы, у якім варта загрузіць два бітавых вобраза — малюнкі для крыжыка і нуліка.
  6. Напісаць апрацоўшчык падзеі OnSelectCell, у якім неабходна змяніць значэнне элемента масіва pole для абранай клеткі. Для вызначэння таго, што маляваць у клетцы на бягучым кроку будзем выкарыстоўваць знакавую пераменную znak, якая будзе мяняць сваё значэнне пасля кожнага ходу. Спачатку znak = 'X';
  7. Напісаць апрацоўшчык падзеі OnDrawCell, у якім трэба маляваць у ячэйцы малюначак, які адпавядае матрыцы стану.
  8. Напісаць апрацоўшчык падзеі OnClick для кнопкі, у якім неабходна абнуліць масіў. Пасля абнулення масіва перамаляваць табліцу на форме. Каманда DrawGrid1 -> Refresh(); выклікае апрацоўшчык падзеі OnDrawCell.

Кампанент StringGrid валодае істотна вялікімі магчымасцямі, чым DrawGrid, паколькі ён можа захоўваць у ячэйках і малюнкі, і тэксты. Калі неабходна ўнесці тэкст у нейкія ячэйкі DrawGrid, то спатрэбіцца выкарыстоўваць метады вываду тэксту на канву, што не заўсёды зручна.

Прыклад 18.5. Кампанент DrawGrid на форме:

Прыклад 18.6. Параметры апрацоўшчыка OnDrawCell:

  • ACol, ARow — індэксы слупка і радка;
  • Rect — прамавугольнік у рамках ячэйкі, зададзенай індэксамі ACol і ARow;
  • State — стан ячэйкі:

-  gdSelected — ячэйка вылучаная;
- gdFocused — ячэйка мае фокус уводу;
- gdFixed — ячэйка ставіцца да фіксаванага радка ці слупка.

Прыклад 18.7. Форма на этапе праектавання:

Апрацоўшчык падзеі OnCreate для формы.

void __fastcall TForm1::

FormCreate(TObject *Sender)

{

  ris -> LoadFromFile("fly.bmp");

}

Апрацоўшчык падзеі OnSelectCell для табліцы.

void __fastcall TForm1::
DrawGrid1DrawCell(TObject *Sender,

int ACol, int ARow, TRect &Rect, 
TGridDrawState State)

{

  if (State.Contains(gdSelected)) {

    if ((ACol + ARow) % 2) {

      DrawGrid1 -> Canvas -> Brush

       -> Color = clSkyBlue;

      DrawGrid1 -> Canvas ->

       FillRect(Rect);

    }

    else

      DrawGrid1 -> Canvas ->

      StretchDraw(Rect, ris);

  }

}

Дадатак у час працы:

Прыклад 18.8. Форма на этапе праектавання:

Апрацоўшчык падзеі OnCreate для формы.

void __fastcall TForm1::

FormCreate(TObject *Sender) 

{

  znak = 'X';

  kr -> LoadFromFile("k.bmp");

  nl -> LoadFromFile("n.bmp");

}

Апрацоўшчык падзеі OnSelectCell для табліцы.

void __fastcall TForm1::

DrawGrid1SelectCell(TObject 
*Sender, int ACol,
int ARow,  bool &CanSelect)

{

  if (pole[ACol][ARow] == 0)

    if (znak == 'X') {

      pole[ACol][ARow] = 1;

      znak = 'O';

    }

    else {

      pole[ACol][ARow] = 2;

      znak = 'X';

    }

}

Апрацоўшчык падзеі OnDrawCell для табліцы.

void __fastcall TForm1::

DrawGrid1DrawCell(TObject 

*Sender, int ACol, int ARow,

 TRect &Rect, TGridDrawState State) 

{

  switch (pole[ACol][ARow]) {

    case 1: {

      DrawGrid1 -> Canvas -> 

      StretchDraw(Rect, kr);

      break;

    }

    case 2: {

      DrawGrid1 -> Canvas -> 

      StretchDraw(Rect, nl);

      break;

    }

  }

}

Апрацоўшчык падзеі OnClick для кнопкі.

void __fastcall TForm1::

BitBtn1Click(TObject *Sender)

{

  for (int i = 0; i < 3; i++)

    for (int j = 0; j < 3; j++)

      pole[i][j] = 0;

  DrawGrid1 -> Refresh();

}

Дадатак у час працы: