Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> класс для облегчения работы с GUI 
:(
    Опции темы
Alek86
Дата 9.1.2008, 18:36 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



в общем, вопрос из разряда "хотелось бы отакую штуку, а вдруг уже есть?"

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

очень бы хотелось иметь шаблон (не С++ template) этакого "конечного автомата" с некоторым количеством состояний (немелким, но конечным), в котором можно держать состояния видимости и доступности для контролов и в который можно было бы добавлять различные "события".

К примеру, если есть эдит, в который записывается сообщение, и кнопка - "Послать сообщение в чат".
Если эдит не заполнен, то и кнопке "Послать" нужно быть недоступной, а когда приходит событие "Эдит стал непустым", она становится доступной. При событии "Эдит опустел" она снова тухнет.

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

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

в общем, это и весь вопрос - знает кто-либо что-либо подобное?


--------------------
user posted image    user posted image
PM MAIL   Вверх
JackYF
Дата 9.1.2008, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



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


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Earnest
Дата 9.1.2008, 19:50 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



ИМХО, такие вещи лучше делать примерно так (без автоматов и явного прописывания состояний): 
1) каждый контрол имеет вирт функцию OnUpdate с каким-то подходящим параметром или, что почти тоже самое, родительская форма имеет функцию OnUpdateItem, которая вызывается для каждого элемента в определенные периоды времени.
Во втором случае можно завести таблицу (ид-р элемента -> Update-функция) - чтобы со свичами не связываться. В общем, какой-то диспетчер.

Для каждого элемента может быть установлено состояние, текст, выделение, etc (в зависимости от элемента) - и все это дело зависит от состояния родительской формы (режим, установленные значения - что угодно).

Функцию, которая вызывает эти Update'ы, назовем UpdateItems.
2) Эта функция может вызываться в цикле простоя (автоматически, средой) или прямо (формой, по наступлению каких-то событий). 

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




--------------------
...
PM   Вверх
archimed7592
Дата 9.1.2008, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(Alek86 @  9.1.2008,  18:36 Найти цитируемый пост)
К примеру, если есть эдит, в который записывается сообщение, и кнопка - "Послать сообщение в чат".
Если эдит не заполнен, то и кнопке "Послать" нужно быть недоступной, а когда приходит событие "Эдит стал непустым", она становится доступной. При событии "Эдит опустел" она снова тухнет.

QAction, TAction(VCL) и иже с ними.

В общих чертах даже вижу как реализовать такой велосипед на Qt smile.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
JackYF
Дата 9.1.2008, 20:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Earnest, я почему-то подобные решения и представлял как собственный велосипед. Например, чтобы контролу заиметь функцию OnUpdate, от него надо отнаследоваться. Разным контролам в onUpdate надо подсовывать разные типы данных - строку, число, булевское значение...


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Earnest
Дата 9.1.2008, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(JackYF @  9.1.2008,  21:15 Найти цитируемый пост)
Earnest, я почему-то подобные решения и представлял как собственный велосипед. Например, чтобы контролу заиметь функцию OnUpdate, от него надо отнаследоваться. Разным контролам в onUpdate надо подсовывать разные типы данных - строку, число, булевское значение... 

Если велосипед написать один раз, и написать хорошо, то это уже будет мопед или даже мотоцикл smile 

Насчет "отнаследоваться" - да, верно, проще пользоваться стандартными контролами в общем случае. Поэтому я и написала про несколько Апдейтов на родительской форме + диспетчеризация вызовов. А передавать разные переменные вовсе не обязательно - спрашиваем у формы то, что нас в каждом конкретном случае интересует. Например: кнопка - "Послать сообщение в чат", которая зависит от набитого в поле текста. Пишем OnUpdateSendMsg: форма, дай текстик от поля трам-пам-пам. Пустой? - засериваюсь! Ну и т.д.
Логически, вообще никакие параметры не нужны (кроме формы, конечно - эти функции могут быть и не частью формы, можно такую обновлялку как отдельный класс писать). Технически - может потребоваться какой-то вспомогательный параметр типа контекста...

Добавлено через 3 минуты и 2 секунды
Кстати, развитые фрейворки наверняка такой или похожий подход предоставляют. MFC, например. А общего класса-объекта, конечно, нет, т.к. сильно от среды зависит.


--------------------
...
PM   Вверх
Alek86
Дата 10.1.2008, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Цитата(Earnest @  9.1.2008,  20:42 Найти цитируемый пост)
А общего класса-объекта, конечно, нет, т.к. сильно от среды зависит.

почему это он зависит от среды?

к тому же при таком подходе (что предложил(а) Earnest), работа с состояниями контролов будет разнесена. А это, имхо, не есть хорошо. Повторюсь, что автомат не только позволит собрать всю эту логику в одном месте, но и автоматически протестить ее. К тому-же, благодаря шаблонам в автомат можно подсунуть не булевые переменные, а уже сами классы контролов, чтобы автомат мог сам менять их состояния. (если кто-то не понял, и очень захочет убедиться, то могу кинуть код, но он не очень мелкий).

Цитата(archimed7592 @  9.1.2008,  20:06 Найти цитируемый пост)
В общих чертах даже вижу как реализовать такой велосипед на Qt

реализовать-то можно, просто думалось, что уже есть такое....

Добавлено через 5 минут и 37 секунд
Цитата(archimed7592 @  9.1.2008,  20:06 Найти цитируемый пост)
QAction, TAction(VCL) и иже с ними.

не заметил, посмотрим-с....


--------------------
user posted image    user posted image
PM MAIL   Вверх
archimed7592
Дата 10.1.2008, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(Alek86 @  10.1.2008,  10:53 Найти цитируемый пост)
почему это он зависит от среды?

От GUI-библиотеки, если быть точнее smile.

Цитата(Alek86 @  10.1.2008,  10:53 Найти цитируемый пост)
что уже есть такое....

Ну, по хорошему, велосипед - это массив экшэнов(Action) с некоторой, минимальной, логикой smile.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
Lazin
Дата 10.1.2008, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Как то городил подобное на VCL, у меня был TActionList и набор TAction. Каждое действие назначалось как минимум одному контролу, а чаще нескольким. Затем у меня возникла необходимость некоторые из них прятать время от времени, для этого я использовал свойство Tag. Для разных категорий действий (TAction) я установил разные значения Tag и потом в коде определял по ним какие TAction когда должны-быть активны, видимы и т.д.
код уродлив но крайне эффективен  smile 
Код

//callback для обработки изменения активн. слоя
void __fastcall TMainForm::LayerChanges(TObject *Sender)
{
    for (int i = 0; i < Alist->ActionCount; i++) {
        TAction * act = dynamic_cast<TAction*>(Alist->Actions[i]);
        switch (Alist->Actions[i]->Tag) {
        case 10:
        act->Visible = (edit->layer_type() == TLayerObj::vector) ||
                        (edit->layer_type() == TLayerObj::advanced);
        break;
        case 20:
        act->Visible = (edit->layer_type() == TLayerObj::raster);
        break;
        }
    }

    StatusBar->Panels->Items[1]->Text = edit->active_layer()->name;
    update_stat_glyph(dynamic_cast<TObject*>(Select));
}

PM MAIL Skype GTalk   Вверх
mes
Дата 15.1.2008, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



в обшем виде  я делаю так  так:

В одном месте строю модель UI (без widget'ов).
При изменение своего состояния он вызывает событие на обновление вида.
Событие распределяется по всем widget`ам которые имееют отношение к этой модели

например модель контрола для отправки сообшения в чат CChatTextSender имеет
события "Активен" "Неактивен" "СтрокаОчишена" "ПоявилсяТекст" "ТекстНаОтправку" "ТекстОтправлен"

Например представление состоит из строки, кнопки и возможно еше чего нибудь.
Тогда у всех них вызывается метод UpdateUI_OnChatTextSenderEvent (...);

Итого получается что логика собрана в одном месте, а представление логики в другой. 


P.S Вид диспетчеризации сообшения приведен условно.. Вариантов несколько - но эта другая тема



Это сообщение отредактировал(а) mes - 15.1.2008, 17:24


--------------------
PM MAIL WWW   Вверх
Alek86
Дата 15.1.2008, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



повторюсь, у меня главная идея была в том, чтобы абстрагироваться от контролов и собрать все это в одном классе smile


--------------------
user posted image    user posted image
PM MAIL   Вверх
mes
Дата 15.1.2008, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Alek86 @  15.1.2008,  14:54 Найти цитируемый пост)
повторюсь, у меня главная идея была в том, чтобы абстрагироваться от контролов и собрать все это в одном классе  


Ну и я про то же...
Вначале забываешь про контролы и составляешь  функциональный объект.
Каждый такой объект может генерировать UpdateUI  с параметрами события.
например так:
Код

class CChatTextSender
{
public:
   void  SetEnable (bool flag);
   void ClearText ();
   void SendText ();
protected:
   void SendUpdateUIEvent(.....);
   
};
class CChatTextView
{
public:
   void OnMsg (Msg)
protected:
   void SendUpdateUIEvent(.....);
};

Потом составляешь форму.  Бросаешь туда контролы.
Каждый контрол подписываешь на события от одного или более функциональнго объекта.
А в в обработку внутренних событий контрола (например нажатие кнопки) бросаешь метод от ф. обьекта.

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

то есть контролы выглядит примерно так:
Код

nameespace ChatTextSender 
{

class WButtonControl : public ...
{  ...
public:
   OnUpdateUI (....) ;
   SetPChatTextSender (....) {...};
protected:
   OnButtonPressed () { if (p_Sender)  p_Sender->SetText(); };   
private:
    CChatTextSender * p_Sender;
};

class WTextControl: ..
{
public:
   OnUpdateUI (....) ;
   SetPChatTextSender (....) {...};
protected:
   OnEnterPressed  () { if (p_Sender)  p_Sender->SetText(); };   
private:
    CChatTextSender * p_Sender;
};
};


При том получение контрола возмоэно двумя путями. Наследоваться от кнопки и дополнить ее функционалом
Или включать в себя кнопку как объект (указатель на него) и подписываться на события.
Второй способ мне кжется предпочтительней.

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

Это сообщение отредактировал(а) mes - 15.1.2008, 17:30


--------------------
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0671 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.