Russian Qt Forum
Май 02, 2024, 06:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: автоматизировать связи changed*() РЕШЕНО  (Прочитано 13995 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Июнь 15, 2010, 08:56 »

есть многостраничный диалог настроек с десятками контролов, надо собрать с них всех сигналы changed*(), чтобы знать, когда надо копировать настройки при закрытии диалога, когда не надо (можно, конечно, по Ок переписывать всегда, а по Cancel всегда хренить, но как-то это не очень нравится, тем более, что надо по Cancel выдать предупреждение, если настройки были изменены)

а эти changed*() Тролли умудрились сделать очень разнообразными, где-то параметр int, где-то другой...

и теперь грустно, что придется руками писать, кроме копирования настроек, еще и различные слоты, к которым changed*() должны быть присоединены, и в конструкторе диалога настроек еще все это соединять, и не забыть, и не пропустить ничего, а контролов... десятки...

может есть какой-то автоматизированный способ это все отследить? я его в документации не вижу, может кто делал уже, подскажет?
« Последнее редактирование: Июнь 16, 2010, 12:44 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Kolobok
Гость
« Ответ #1 : Июнь 15, 2010, 09:55 »

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

Воспользуйся QSignalMapper

может есть какой-то автоматизированный способ это все отследить?

Как вариант, если лень самому все делать, храни настройки в бд. По Ок делай commit, по Cancel rollback.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #2 : Июнь 15, 2010, 09:57 »

Никто вам не мешает навешивать один слот changed() без аргументов на все "changed*()" сигналы.
Записан

Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #3 : Июнь 15, 2010, 10:16 »

можно конечно и один слот changed() сделать, но это ничего не меняет по существу - все контролы все равно нужно будет по отдельности подключать, поскольку нельзя написать SIGNAL(colorChanged()) если он colorChanged(QColor), подключение просто не выполнится, и регулярный механизм для гомогенного подключения сигналов QtColorPicker::colorChanged(QColor) и QComboBox::currentIndexChanged(int) тут не просматривается

а QSignalMapper наверно было бы то, что надо, но в другой реализации - а так все равно надо руками его подключать ко всем контролам, нет разницы, также точно можно и без QSignalMapper просто один слот в классе диалога создать

вот если бы родительские классы для разных контролов имели некий общий сигнал changed(), который выдается, если объект изменился, независимо от его структуры... например, у QWidget если бы такой сигнал был, или даже у QObject... то есть, сигналы changed*() у дочерних классов все равно остаются, но обязательно вызывают этот сигнал у своего родителя - тогда все элементарно бы получалось и автоматизировалось, я бы в цикле по всем контролам пробежал и их подключил, и дальше можно добавлять или удалять контролы, они бы автоматом подключались, но поскольку у их changed*() разные имена и параметры, так не получается  Грустный
« Последнее редактирование: Июнь 15, 2010, 10:21 от Гурман » Записан

2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #4 : Июнь 15, 2010, 10:28 »

Цитировать
...поскольку нельзя написать SIGNAL(colorChanged()) если он colorChanged(QColor), подключение просто не выполнится
Вы меня не поняли. Я говорил про другое.
Зачем менять содержимое сигнала? Нужно правильно описать сигнал и повесить на него один общий слот:

Код
C++ (Qt)
connect( colorPicker, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( changed() ) );
connect( comboBox, SIGNAL( currentIndexChanged( int ), this, SLOT( changed() ) );
 

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

Qt 5.11/4.8.7 (X11/Win)
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Июнь 15, 2010, 10:48 »

На самом деле, можно сделать намного красивее и вообще не завязываться на "changed*()".
Во время создания диалога в свойствах контрола сохраните его значение. В accept() пробежитесь по всем контролам и сравните текущее с сохраненным. Всё просто)
Записан

Qt 5.11/4.8.7 (X11/Win)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #6 : Июнь 15, 2010, 11:07 »

Цитировать
Вы меня не поняли. Я говорил про другое.
Зачем менять содержимое сигнала? Нужно правильно описать сигнал и повесить на него один общий слот:

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

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

Цитировать
Во время создания диалога в свойствах контрола сохраните его значение. В accept() пробежитесь по всем контролам и сравните текущее с сохраненным. Всё просто

с точки зрения количества подключений и вероятности ошибки это практически тоже самое, что подключить все контролы к одному слоту построчно, поскольку функции получения значения контрола у всех типов контролов разные, и возвращают разные типы данных, значит их нельзя просто пробежать в цикле foreach( control, controlList )
Записан

2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #7 : Июнь 15, 2010, 11:17 »

Цитировать
с точки зрения количества подключений и вероятности ошибки это практически тоже самое, что подключить все контролы к одному слоту построчно, поскольку функции получения значения контрола у всех типов контролов разные, и возвращают разные типы данных, значит их нельзя просто пробежать в цикле foreach( control, controlList )

Мде, т.е. вам нужна волшебная палочка)
На самом деле тролли подумали о ней. Копайте QObject::property() и QVariant().
Записан

Qt 5.11/4.8.7 (X11/Win)
BRE
Гость
« Ответ #8 : Июнь 15, 2010, 11:21 »

В Qt есть возможность:
* получить список всех дочерних виджетов на главном;
* добавить property для каждого объекта, в том числе дочернего виджета;
* получить имя класса для объекта;
* для каждого класса виджета имя сигнала об изменении - известно.

Все просто.  Улыбающийся
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #9 : Июнь 15, 2010, 17:14 »

Цитировать
Копайте QObject::property() и QVariant().

вот-вот-вот... истина где-то рядом... (С) Малдер

если бы property() понимал сложный запрос с wildcard типа property( "*Changed(*" - можно было бы просто запросить каждый контрол... хотя наверно можно через metaObject получить все сигналы, и QRegExp-ом отобрать нужные

кто-нибудь делал? все получается?
« Последнее редактирование: Июнь 15, 2010, 17:22 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июнь 15, 2010, 20:31 »

Я накручивал примерно так (псевдокод)
Код
C++ (Qt)
struct DataRec {
enum dataType {
 data_int = 1,
 data_float = 2,
 ...
};
 
enum ctlType {
 ctl_LineEdit = 1,
 ctl_Combo = 2,
 ...
};
 
dataType mDataType;
ctlType mCtlType;
union {
 void * voidPtr;
 int *   intPtr;
 float * floatPtr;
 ...
};
};
 
QHash <QWidget *, DataRec> theControlList;
 
Ну понятно DataRec имеет много методов для передачи данных из UI в пользовательские структуры и наоборот. Задумка автоматизировать операции пробегаясь по QHash (знаем источник и приемник). Впрочем для немодальных окон changed() все равно приходится отслеживать/связывать, можно лишь упростить дальнейшую обработку.
« Последнее редактирование: Июнь 15, 2010, 21:03 от Igors » Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #11 : Июнь 15, 2010, 20:49 »

все равно в таблицу надо руками добавлять, и не попутать dataType и ctrlType, хочется чисто динамически, поскольку диалог настроек полностью рисуется в Дизайнере

хватает только написания кода для передачи всех настроек из класса Settings::QSettings и обратно... но там хоть запутаться сложно, хотя пропустить что-нибудь, как нефик делать

просто контролов в настройках очень много

че-то не вижу я, как получить список слотов КуОбъекта, наверняка есть, но не туда смотрю
« Последнее редактирование: Июнь 15, 2010, 20:53 от Гурман » Записан

2^7-1 == 127, задумайтесь...
BRE
Гость
« Ответ #12 : Июнь 15, 2010, 21:04 »

Посмотри эту статью: http://doc.trolltech.com/qq/qq11-mandatoryfields.html
Думаю идея появится.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #13 : Июнь 15, 2010, 21:52 »

ну влоб их способ не годится - там описан метод add() который добавляет контролы, а у меня они в дизайнере рисуются

а вот widget->inherits( <имя класса> ) и подключение сигнала изменения этого класса - похоже на то, что надо, можно пробежать по всем виджетам настроек, и аналогичным образом их подключить

надо только не забывать добавлять соответствующую проверку имени класса, если будет использоваться контрол, наследующий какой-нибудь класс, который еще не включен в проверки
Записан

2^7-1 == 127, задумайтесь...
BRE
Гость
« Ответ #14 : Июнь 16, 2010, 08:14 »

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

надо только не забывать добавлять соответствующую проверку имени класса, если будет использоваться контрол, наследующий какой-нибудь класс, который еще не включен в проверки
Добавить в конец одну секцию else с Q_ASSERT_X вроде сложно забыть.  Улыбающийся
« Последнее редактирование: Июнь 16, 2010, 08:16 от BRE » Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.09 секунд. Запросов: 22.