Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder: Базы данных
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.81/16: Рейтинг темы: голосов - 16, средняя оценка - 4.81
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
1

Закрасить строку DBGrid при нажатии на Button

02.05.2013, 02:49. Просмотров 2957. Ответов 20
Метки нет (Все метки)

В общем есть две кнопки ("Пометить", "Снять пометку"), и есть DBGrid. Требуется при нажатии на кнопку "Пометить" закрасить выбранную строку (если строка не выбрана, вывести showmessage). Что делает кнопка "Снять пометку", думаю всем ясно)

Я и этого реализовать не могу, так есть еще и задача посложнее, как мне кажется.

Нужно как то запомнить какие поля были помечены, и при перезапуске программы, они должны быть все так же закрашены.
Буду очень благодарен за помощь.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.05.2013, 02:49
Ответы с готовыми решениями:

Переход на другую форму при нажатии на строку в DBGrid
Как сделать так чтоби при нажатии на рядок в DBGrid совершалса переход на Form 2

DBgrid закрасить нужную строку
Всем привет, не совладал я с DBgrid-ом, чет не идет. Подскажите кодом:help: К...

Закрасить цветом выделенную строку в DBGrid
Здравствуйте! Необходимо закрасить выделенную строку в DBGrid, при этом...

Ошибка при нажатии на button
при нажатии на кнопку выходит ошибка Project Project1.exe raised exception...

При нажатии button добавлять ListBox в tabSheet
Как делать так, чтоб при нажатии button добавлялась tabSheet и ListBox???

20
_Dimon_
1396 / 559 / 127
Регистрация: 31.10.2011
Сообщений: 1,954
03.05.2013, 04:06 2
Cоздать отдельное поле в БД, например "MARK" тип int

Закрашиваем строки:
В событии OnDrawColumnCell грида
C++
1
2
3
4
5
6
7
8
void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender, const TRect &Rect,
          int DataCol, TColumn *Column, TGridDrawState State)
{
 TDBGrid* Grid = static_cast<TDBGrid*>(Sender);
 if (Grid->DataSource->DataSet->FieldByName("MARK")->Value==1)
  Grid->Canvas->Brush->Color = clRed;
 Grid->DefaultDrawColumnCell(Rect,DataCol,Column,State);
}
2
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
03.05.2013, 04:58 3
Лучший ответ Сообщение было отмечено как решение

Решение

Kasiman,
Цитата Сообщение от Kasiman Посмотреть сообщение
В общем есть две кнопки ("Пометить", "Снять пометку"), и есть DBGrid
Предлагаю сделать по уму и повесить, к примеру, на сам DBGrid чекбоксы. Т.е. клацнули по чекбоксу - строка выделилась, еще раз клацнули - выделение снялось.

Вот накидал по этому поводу:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
bool IsChecked = false;
 
// ---------------------------------------------------------------------------
__fastcall TForm1::TForm1( TComponent * Owner ) : TForm( Owner )
{
    list = new TStringList;
    list->LoadFromFile( "settings.txt" );
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm1::DBGrid1DrawColumnCell(
    TObject *      Sender,
    const TRect &  Rect,
    int            DataCol,
    TColumn *      Column,
    TGridDrawState State )
{
    int Style;
    IsChecked = list->IndexOf( DBGrid1->DataSource->DataSet->FieldByName( "ID" )
        ->AsString ) >= 0;
    if ( IsChecked )
    {
        DBGrid1->Canvas->Brush->Color = cl3DLight;
        DBGrid1->Canvas->Font->Color = clHotLight;
    }
    DBGrid1->DefaultDrawColumnCell( Rect, DataCol, Column, State );
 
    if ( !Column->Field->Index )
    {
        if ( !IsChecked )
        {
            Style = DFCS_BUTTONCHECK;
        }
        else
        {
            Style = DFCS_CHECKED;
        }
        DrawFrameControl( DBGrid1->Canvas->Handle, & Rect, DFC_BUTTON, Style );
    }
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm1::DBGrid1CellClick( TColumn * Column )
{
    if ( !Column->Field->Index )
    {
 
        if ( list->IndexOf( DBGrid1->DataSource->DataSet->FieldByName( "ID" )
            ->AsString ) >= 0 )
        {
            list->Delete
                ( list->IndexOf( DBGrid1->DataSource->DataSet->FieldByName
                ( "ID" )->AsString ) );
        }
        else
        {
            list->Add( DBGrid1->DataSource->DataSet->FieldByName( "ID" )
                ->AsString );
        }
        Column->Grid->Refresh( );
    }
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(
    TObject *      Sender,
    TCloseAction & Action )
{
    list->SaveToFile( "settings.txt" );
    delete list;
}

Цитата Сообщение от Kasiman Посмотреть сообщение
Нужно как то запомнить какие поля были помечены, и при перезапуске программы, они должны быть все так же закрашены.
Для этого можно задействовать как и БД (отдельное поле), так и обычный файл (или реестр), как в моем примере.

Идентификация выбранных строк происходит по полю с уникальными значениями.

Также необходимо создать для НД (ADOTable/Query) дополнительный столбец для чекбоксов. У меня данный столбец располагается первым: Column->Field->Index = 0.


P.S. Пример очень сырой, поэтому его надо дорабатывать.
3
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
03.05.2013, 15:23  [ТС] 4
Я, конечно, могу воспользоваться вашими подсказками, и так и сделаю, если не получится по другому.
Но рас уж на то пошло, предлагаю сделать еще хитрее. В самой базе создать логическое поле, там как раз, чекбоксы появляются, вот только в DBGrid они не отображаются, он выдает либо "true" либо "false" и поменять их никак нельзя, ТОЛЬКО через Access.

Так вот, хитрость заключается в том, что:
Создаем это самое булевское поле, но скрываем его. Создаем кнопку, до тех пор пока строка не выбрана, она недоступна. Как только выбрали строку, мы можем нажать на кнопку.
При нажатии (вот тут та самая штука, которую я не знаю как реализовать) должен определиться индекс выбранной строки. Далее в этой же строчке, в булевом поле, меняем "false" на "true".

Ну и где нибудь в OnDrawColumnCell сделать цикл, который проходится по всем строчкам и смотрит значение булевского поля, если вдруг попался "true" красим всю строку.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
03.05.2013, 18:26 5
Kasiman, а теперь объясните мне, пожалуйста, необходимость использования кнопки для маркировки записи?

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

Представьте: делаем фокус на строку - обращаемся к кнопке. Делаем фокус на другую строку - опять обращаемся к кнопке. И т.д. В итоге получится, что у нас очередная выбранная строка будет распределена от кнопки на некоторое расстояние, что очень неудобно.

Могу наглядно показать, как это будет.
0
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
04.05.2013, 17:29  [ТС] 6
Да, пожалуй вы правы.
Но тогда как в DBGrid'е сделать поле состоящее из чекбоксов? и еще, я еще не просмотрел толком, но ваш код меня пугает)
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
04.05.2013, 17:49 7
Kasiman,
Цитата Сообщение от Kasiman Посмотреть сообщение
Но тогда как в DBGrid'е сделать поле состоящее из чекбоксов?
А Вы знаете, может вообще без них обойдемся? Просто в той же Бухгалтерии для выбора строк чекбоксов никаких нет. Просто щелкаете на строчку и она маркируется. Еще раз по этой же строке - маркировка снимается.

А маркированные поля запоминать в БД отдельным полем, как Вы ранее писали:
Плюс к этому
Цитата Сообщение от Kasiman Посмотреть сообщение
В самой базе
Цитата Сообщение от Kasiman Посмотреть сообщение
Создаем это самое булевское поле, но скрываем его.
Как Вам такой вариант?


Цитата Сообщение от Kasiman Посмотреть сообщение
но ваш код меня пугает)
Там ничего страшного Уточняйте, что конкретно непонятно.

P.S. Почему предлагаю отказаться от чекбоксов: ведь это тоже не очень удобно. Для маркировки записи придется всегда обращаться к первому столбцу - тянуться до него мышкой Другое дело, если у Вас в самом DBGrid'е происходит редактирование (по ячейкам), то тогда без чекбоксов не обойтись. Иначе, они не нужны. ИМХО.
1
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
04.05.2013, 18:10  [ТС] 8
По поводу "обойдемся без чекбоксов" - мне кажется это не очень подходит, приклеил изображение с главным окном программы. при нажатии на строку, изображение меняется.

А хотя знаете, черт с ним, давайте сделаем как вы предлагаете, без всяких чекбоксов.
вот только у меня во вкладке меню, есть пункт - Авторизация, можно войти от лица Бухгалтера, Менеджера и Складчика. Давайте тогда уж сделаем так, что бы поля красились при клике, только если вход был от лица складчика.
0
Миниатюры
Закрасить строку DBGrid при нажатии на Button  
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
04.05.2013, 18:13  [ТС] 9
Вот, придумал кажется то что надо.
делаем кнопку, "Списать товар", при нажатии выскакивает новая форма с ДБГридом, больше там ничего нету, при нажатии на строку, она красится, при повторном, краска снимается, при закрытии формы, данные о закрашенных полях переходят, в тот же ДБГрид только на главной форме.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
04.05.2013, 18:23 10
Kasiman,
Цитата Сообщение от Kasiman Посмотреть сообщение
при нажатии выскакивает новая форма с ДБГридом
А вот дублировать совершенно ни к чему.


Лучше проверять от кого сделан вход и разрешать маркировать записи, т.е. вот так:
Цитата Сообщение от Kasiman Посмотреть сообщение
Давайте тогда уж сделаем так, что бы поля красились при клике, только если вход был от лица складчика.
Кстати говоря, надо было об этом спросить в самом начале, но спрошу сейчас: какая цель этих маркировок? Среди общего списка товаров видеть какие товары списаны, а какие нет?
1
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
04.05.2013, 20:16  [ТС] 11
Сначала я сделал кнопку удалить товар, при этом запись удалялась окончательно, и из базы тоже. Но потом решил что это не очень благоприятно для целостности базы, поэтому решил сделать что то вроде пометки, которая означала бы отсутствие или остановку поставок данного товара.

Вся проблема в том что я сам еще толком не придумал, как и что ЛУЧШЕ сделать с этим.

По поводу дублирования, мне кажется так будет лучше. На главной форме, я думаю, лучше не стоит делать закраску при клике, на это много причин. А если сделать вызов формы с той же таблицей и на ней уже разрешить закрашивать при клике, это по моему мнению будет самым подходящим вариантом.
0
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
05.05.2013, 22:08  [ТС] 12
Помогите просто реализовать пожалуйста, а то у меня что то уже на эту тему голова вообще не работает, то что делаю не срабатывает.

Я все таки решил сделать по своему: нажимаем кнопку "списать товар", вылезает форма с таблицей товаров.
При нажатии на какую либо строку (стоит MultiSelect), значение булево поля "Пометка" меняется на противоположное.
Это я сделал и вопросов нет.

А вот теперь то что я никак не могу!

На главной форме та же самая таблица товаров. Если в колонке "Пометка" стоит true, закрасить эту строку.
я пытался так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender,
      const TRect &Rect, int DataCol, TColumn *Column,
      TGridDrawState State)
{ 
for (Form5->ADOQuery1->First(); Form5->ADOQuery1->Eof==true; Form5->ADOQuery1->Next()) // так делать кажется нельзя
   {
    if (Form5->ADOQuery1->FieldByName("Пометка")->AsBoolean==true)
      {
       DBGrid1->Canvas->Brush->Color = cl3DLight;
       DBGrid1->Canvas->Font->Color = clHotLight;
      }
    DBGrid1->DefaultDrawColumnCell( Rect, DataCol, Column, State );
  }
}
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
06.05.2013, 00:57 13
Kasiman, не, так делать действительно не стоит

Оставьте только это:
C++
1
2
3
4
5
6
    if (Form5->ADOQuery1->FieldByName("Пометка")->AsBoolean==true)
      {
       DBGrid1->Canvas->Brush->Color = cl3DLight;
       DBGrid1->Canvas->Font->Color = clHotLight;
      }
    DBGrid1->DefaultDrawColumnCell( Rect, DataCol, Column, State );
Когда нужно вызвать перерисовку, используйте
C++
1
DBGrid1->Refresh();
1
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
06.05.2013, 01:54  [ТС] 14
Но это не правильно, я думал вы поможете мне исправить, а то я додуматься не могу.

В этом случае происходит примерно так (если я правильно понимаю) : на форме5 он смотрит выделенную строку, если в ее колонке "Пометка" стоит true, тогда он закрашивает ВСЮ таблицу на форме1.

Мне же надо что бы он пробегался в цикле по всем строчкам таблицы на форме 5, и если вдруг натыкался на true то сразу закрашивал бы ИМЕННО ЭТУ строчку в таблице на форме 1.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
06.05.2013, 02:00 15
Kasiman,
Цитата Сообщение от Kasiman Посмотреть сообщение
тогда он закрашивает ВСЮ таблицу на форме1.
С чего это вдруг?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void __fastcall TForm1::DBGrid1DrawColumnCell(
    TObject *      Sender,
    const TRect &  Rect,
    int            DataCol,
    TColumn *      Column,
    TGridDrawState State )
{
    if ( DBGrid1->DataSource->DataSet->FieldByName( "Страна" )
        ->AsString == "США" )
    {
        DBGrid1->Canvas->Brush->Color = cl3DLight;
        DBGrid1->Canvas->Font->Color = clHotLight;
    }
    DBGrid1->DefaultDrawColumnCell( Rect, DataCol, Column, State );
}
1
Миниатюры
Закрасить строку DBGrid при нажатии на Button  
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
06.05.2013, 02:21  [ТС] 16
О, ОТЛИЧНО, все работает, очередной раз СПАСИБО вам)
Если можно еще один небольшой вопросик, те поля, которые я во время запущенной программы пометил, он красит только после перезапуска программы. И обновление не помогает почему то.

Я прописал обновление дбгрид1 (форма 1) при клике по дбгриду на форме5.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
06.05.2013, 02:24 17
Kasiman,
Цитата Сообщение от Kasiman Посмотреть сообщение
Я прописал обновление дбгрид1
Пропишите это обновление на событие OnShow Form1.
1
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
06.05.2013, 02:31  [ТС] 18
Все равно ни в какую, попробовал и на OnShow Form1 и на OnClose Form5.

Может сделать вызов функции DBGrid1DrawColumnCell при клике по ДБГриду на форме 5? Только этого я тоже незнаю как сделать.
0
The_Immortal
1560 / 496 / 48
Регистрация: 04.04.2009
Сообщений: 1,891
06.05.2013, 02:51 19
Kasiman, что-то Вы не так делаете:

1
Kasiman
1 / 1 / 2
Регистрация: 11.11.2012
Сообщений: 93
06.05.2013, 03:22  [ТС] 20
Даже не знаю что не так. Вот под кнопку написал обновление, все равно ничего.
0
06.05.2013, 03:22
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.05.2013, 03:22

Как отключить локальную сеть при нажатии на Button?
Здравствуйте, как отключить локальную сеть при нажатии на Button? А при...

Как при нажатии на кнопку Button открыть PopupMenu?
как при нажатии на кнопку(button) открыть popMenu?

Увеличивать значение в Edit при каждом нажатии Button
Всем привет. Такой вопрос: есть Button1 и Edit1, как сделать чтобы при первом...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru