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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Специализированные шаблоны для контролов Qt  (Прочитано 18107 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« : Апрель 17, 2015, 14:28 »

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

Код общих методов написан и отлажен на примере одного контрола, но сейчас при создании других контролов придётся дублировать как тела методов, так и их объявления в заголовках. Тупо можно было бы и макрос написать, но шаблоны мощнее и современнее. Если бы в Qt было разрешено множественное наследование от QObject, я бы сделал всё очень просто. Но увы, так нельзя. Если бы у классов не было различий, можно было бы все контролы накрыть одним шаблоном и узбагоиться. Но из-за наличия существенных различий контролов, классы примерно на 50% одинаковые, и на 50% различаются. Похоже это надо делать на специализированных шаблонах. Я их совместно с Qt не использовал (честно говоря, вообще в реальных приложениях ни разу не использовал), поэтому вопрос - нет ли каких-либо подводных камней при использовании специализированных шаблонов в контексте GNU CC/MinGW и Qt конкретно версии 4.7? Кто-нибудь использует эту технику в реальных проектах? Вообще моя задача решаема этим способом?
Записан

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

Сообщений: 2094



Просмотр профиля
« Ответ #1 : Апрель 17, 2015, 15:33 »

Цитировать
Код общих методов написан и отлажен на примере одного контрола, но сейчас при создании других контролов придётся дублировать как тела методов, так и их объявления в заголовках. Тупо можно было бы и макрос написать, но шаблоны мощнее и современнее.
А так ли здесь нужны шаблоны?
Пишите свой базовый класс, в котором реализуете все общие методы, а от него уже наследуете другие контролы, в которых дописываете только  специфмчные для них методы. и т.д.
Или я чего-то не понял?
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Апрель 17, 2015, 15:50 »

А так ли здесь нужны шаблоны?
Пишите свой базовый класс, в котором реализуете все общие методы, а от него уже наследуете другие контролы, в которых дописываете только  специфмчные для них методы. и т.д.
Или я чего-то не понял?
А по-моему нужны (вот уж никак не ожидал себя в такой роли Улыбающийся). Дело в том что базовый класс не может быть QObject, ему придется включать напр QLineEdit (или др Qt контрол) агрегатом - и это здесь очень неудобно. Напр QLineEdit получил сигнал - и что, надо передавать в базовый, а тот не QObject (и понеслась)
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #3 : Апрель 17, 2015, 15:57 »

Цитировать
А по-моему нужны (вот уж никак не ожидал себя в такой роли Улыбающийся). Дело в том что базовый класс не может быть QObject
Почему?
Базовый класс наследуется от QWidget, т.к.
Цитировать
Они должны уметь перемещаться по родительскому виджету не вылезая за его границы, выдавать данные о своей геометрии, реагировать на набор общих сигналов. Все эти функции совершенно одинаковы для всех контролов, которые все являются виджетами.
« Последнее редактирование: Апрель 17, 2015, 15:59 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Апрель 17, 2015, 16:09 »

Почему?
Базовый класс наследуется от QWidget, т.к.
Цитировать
Они должны уметь перемещаться по родительскому виджету не вылезая за его границы, выдавать данные о своей геометрии, реагировать на набор общих сигналов. Все эти функции совершенно одинаковы для всех контролов, которые все являются виджетами.
Но не "одним и тем же виджетом/классом". Унаследовавшись от QWidget - уже не унаследоваться от того же QLineEdit
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #5 : Апрель 17, 2015, 16:17 »

Базовый класс наследуется от QWidget, т.к.

QWidget наследует от QObject. Все стандартные контролы тоже наследуют от QWidget. И там еще хуже - если установлен родитель для QWidget, то нельзя установить родителя для QObject, от которого он наследует (если бы можно было, я бы выкрутился).

Просьба не продолжать вариант с множественным наследованием - в Qt это нереализуемо. Если бы было допустимо двойное наследование от QObject, я бы уже так и сделал.

Единственный вариант - специализированные шаблоны. Но прежде чем начинать чеканить плохо изученный металл, я хочу пообщаться с теми, кто так делал.
« Последнее редактирование: Апрель 17, 2015, 16:31 от Гурман » Записан

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

Сообщений: 4349



Просмотр профиля
« Ответ #6 : Апрель 17, 2015, 16:57 »

Можно попробовать сделать так (кстати, со множественным наследованием Улыбающийся ):
Код
C++ (Qt)
class Common
{
public:
   Common( QWidget *w ) : m_w( w ) {}
 
   // Описываем общие методы для всех виджетов
   void func1()
   {
       m_w->setSize( 100500 );
   }
 
private:
   QWidget *m_w;
};
 
class MyLineEdit : public QLineEdit, public Common
{
   Q_OBJECT
public:
   MyLineEdit( QWidget *parent ) : QLineEdit( parent ), Common( this ) {}
 
   void method()
   {
       func1();      // Используем общие методы из Common
   }
};
 
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Апрель 17, 2015, 17:07 »

Единственный вариант - специализированные шаблоны. Но прежде чем начинать чеканить плохо изученный металл, я хочу пообщаться с теми, кто так делал.
Ну если единственный, т.е. Вы уже все решили - зачем нужно еще какое-то общение? Улыбающийся Конкретно для Qt контролов не делал, поэтому в первую очередь проверил бы нет ли там засады с Q_OBJECT т.е. можно ли так
Код
C++ (Qt)
template <class T>
class MyBaseWidget <T> : public T {
Q_OBJECT
...
};
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #8 : Апрель 17, 2015, 17:25 »

Можно попробовать сделать так (кстати, со множественным наследованием Улыбающийся ):

Без множественного наследования от QObject.

Код
C++ (Qt)
class Common
{
public:
   Common( QWidget *w ) : m_w( w ) {}
 
   // Описываем общие методы для всех виджетов
   void func1()
   {
       m_w->setSize( 100500 );
   }
 
private:
   QWidget *m_w;
};
 
class MyLineEdit : public QLineEdit, public Common
{
   Q_OBJECT
public:
   MyLineEdit( QWidget *parent ) : QLineEdit( parent ), Common( this ) {}
 
   void method()
   {
       func1();      // Используем общие методы из Common
   }
};
 
 

Сейчас именно так и сделано для отладки кода общих методов. Но беда в том, что большинство методов, которые общие для всех расширенных контролов - сигналы или слоты. Так у меня дизайн сделан, и это нельзя изменить. Причём у всех контролов они одинаковые. Фактически в класс Common получилось вынести только обработку событий мыши. И то не роскошно - события то принимать надо в классе MyLineEdit из примера. А в режиме нормальной работы контролов необходимо вызывать методы приёмников у родительского класса. В общем, пришлось пока объявить typedef-ом общий SuperClass, который должен быть классом контрола, то есть typedef QLineEdit SuperClass, и вызывать SuperClass::mousePressEvent(event) когда надо, чтобы кнопка нажималась, или строка редактировалась. Но это всё, включая ваш пример, не отменило необходимости копировать все методы, которые являются сигналами или слотами. Поскольку Common - не QObject...
« Последнее редактирование: Апрель 17, 2015, 17:28 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #9 : Апрель 17, 2015, 17:27 »

в первую очередь проверил бы нет ли там засады с Q_OBJECT

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

Записан

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

Сообщений: 4349



Просмотр профиля
« Ответ #10 : Апрель 17, 2015, 17:32 »

Вот я об этом и спрашиваю - работал ли кто-либо с таким вариантом. Мне это может сэкономить день (с учетом поиска вариантов обхода, которых может быть и не существует), а отвечающему - занять несколько минут.
Это не работает с moc.
Записан
Bepec
Гость
« Ответ #11 : Апрель 17, 2015, 17:33 »

Пытались люди использовать шаблоны с QObject'ом.

Ничего кроме крови пота и боли они не получили. Но попробуйте, вдруг у вас получится Улыбающийся
Записан
Nimbus
Гость
« Ответ #12 : Апрель 17, 2015, 18:21 »

Пытались люди использовать шаблоны с QObject'ом.

Ничего кроме крови пота и боли они не получили. Но попробуйте, вдруг у вас получится Улыбающийся
Да, пропатчить moc, чтобы он находил по коду проекта все инстанцинации шаблонов таких классов и генерил для каждого соответственный метаобъектный код. Смеющийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #13 : Апрель 17, 2015, 18:29 »

Но это всё, включая ваш пример, не отменило необходимости копировать все методы, которые являются сигналами или слотами.
Тела слотов можно выносить в функции common, а в самих слотах вызывать эти функции.
Кстати, в Qt5 можно не объявлять методы слотами, использовать новый вариант connect.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

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


Просмотр профиля
« Ответ #14 : Апрель 17, 2015, 19:03 »

Но это всё, включая ваш пример, не отменило необходимости копировать все методы, которые являются сигналами или слотами.
Тела слотов можно выносить в функции common, а в самих слотах вызывать эти функции.

Смысла особого нет, поскольку тела слотов из 2-3 строк.

Но еще можно мега-макрос написать... наверно я так и сделаю, если есть проблемы с шаблонами и Q_OBJECT.

Кстати, в Qt5 можно не объявлять методы слотами, использовать новый вариант connect.

На 4.7 делается.
« Последнее редактирование: Апрель 17, 2015, 21:06 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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