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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: "Общий" ввод  (Прочитано 7307 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Сентябрь 07, 2009, 11:56 »

Добрый день

Имею много немодальных диалогов но очень простых. Для подавляющего большинства control'ов реакция однотипна:

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

Мне не хочется иметь десятки членов класса и возиться с каждым из них. А хочется иметь один большой switch, например

Код:
bool MyDialog::GetEditVal( int theItemID, double & val )
{
    QLineEdit * edit = qobject_cast <QLineEdit *> ID2Widget(theItemID);
    if (!edit) return false;
    val = edit->text().toDouble();
    return true;
}

void MyDialog::InterfaceChanged( int theItemID )
{
    switch (theItemID) {
      case ID_VELOCITY:
        GetEditVal(theItemID, theData.velocity);
        break; 

      case ID_ACCEL:
        GetEditVal(theItemID, theData.accel);
        break; 
      .....
      .....
    }
}
Получить/присвоить ID - без проблем. Но как мне получить общий сигнал InterfaceChanged без забот с каждым конкретным control'ом?

Спасибо
Записан
BRE
Гость
« Ответ #1 : Сентябрь 07, 2009, 13:35 »

Можно сделать класс наследник от QDialog, перекрыть в нем виртуальную функцию:
void QObject::childEvent ( QChildEvent * event )   [virtual protected]

При каждом добавлении/удалении контроллов в этой функции можно делать connect/disconnect нужного сигнала с нужным слотом.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Сентябрь 07, 2009, 13:51 »

Можно сделать класс наследник от QDialog, перекрыть в нем виртуальную функцию:
void QObject::childEvent ( QChildEvent * event )   [virtual protected]

При каждом добавлении/удалении контроллов в этой функции можно делать connect/disconnect нужного сигнала с нужным слотом.

Мне не нужно добавлять/удалять control'ы на ходу. Не нужен в данном случае и сигнал/слот - control'ы для этого слишком примитивны Улыбающийся. Хочу просто получить управление когда "произошел ввод от такой-то widget" - а дальше я разберусь
Записан
BRE
Гость
« Ответ #3 : Сентябрь 07, 2009, 14:09 »

Мне не нужно добавлять/удалять control'ы на ходу. Не нужен в данном случае и сигнал/слот - control'ы для этого слишком примитивны Улыбающийся.
Хочу просто получить управление когда "произошел ввод от такой-то widget" - а дальше я разберусь
При изменении данных в виджете посылается сигнал. Тебе нужно сигналы от контроллов соединить с одним слотом (InterfaceChanged). Тогда при изменении данных в любом контролле, будет вызван твой слот, где и будет происходить обработка.
Обработка события childEvent позволит тебе автоматически связать сигналы нужных контроллов с твои слотом. Событие это будет происходить при конструировании твоих диалогов.
Записан
SASA
Гость
« Ответ #4 : Сентябрь 07, 2009, 14:33 »

QSignalMapper
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Сентябрь 07, 2009, 14:36 »

Обработка события childEvent позволит тебе автоматически связать сигналы нужных контроллов с твои слотом. Событие это будет происходить при конструировании твоих диалогов.
Меня и "не-автоматически" вполне устроит, children всегда под рукой
При изменении данных в виджете посылается сигнал. Тебе нужно сигналы от контроллов соединить с одним слотом (InterfaceChanged). Тогда при изменении данных в любом контролле, будет вызван твой слот, где и будет происходить обработка.
Да коряво выходит. Понятно что в слоте-приемнике могу получить widget через sender(). Но аргументы для посылаемых сигналов разные: valueChanged( double ), valueChanged( int ) и.т.п. Как мне нацелить их все на 1 slot? (желательно без возни с qobject_cast)
Записан
BRE
Гость
« Ответ #6 : Сентябрь 07, 2009, 14:45 »

Да коряво выходит. Понятно что в слоте-приемнике могу получить widget через sender(). Но аргументы для посылаемых сигналов разные: valueChanged( double ), valueChanged( int ) и.т.п. Как мне нацелить их все на 1 slot? (желательно без возни с qobject_cast)
Код
C++ (Qt)
connect( w1, SIGNAL( valueChanged( int ) ), SLOT( changed() ) );
connect( w2, SIGNAL( valueChanged( double ) ), SLOT( changed() ) );
 
А в changed() по sender() получаешь свой ID, а по ID ты и так тип знаешь.

SASA напомнил про QSignalMapper. С ним, думаю, будет попроще.
« Последнее редактирование: Сентябрь 07, 2009, 14:48 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Сентябрь 07, 2009, 19:25 »

Код
C++ (Qt)
connect( w1, SIGNAL( valueChanged( int ) ), SLOT( changed() ) );
connect( w2, SIGNAL( valueChanged( double ) ), SLOT( changed() ) );
 
Не понял. В букваре написано мутно
Цитировать
The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches.
Так должны они по типам аргументов точно совпадать? Или приемник может иметь меньшее число параметров?  Или как?

SASA напомнил про QSignalMapper. С ним, думаю, будет попроще.
Я пока вижу здесь он не лепится но при случае пригодиться очень даже может, спасибо. Тогда мне может лучше иметь приемником не parent widget а member ee, порожденный от QAction?
« Последнее редактирование: Сентябрь 07, 2009, 19:30 от Igors » Записан
BRE
Гость
« Ответ #8 : Сентябрь 07, 2009, 19:57 »

Так должны они по типам аргументов точно совпадать? Или приемник может иметь меньшее число параметров?  Или как?
Самое простое попробовать самому.  Подмигивающий

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Сентябрь 07, 2009, 20:23 »

Самое простое попробовать самому.  Подмигивающий
Да я много чего могу сам попробовать Улыбающийся Но хотелось бы услышать авторитетное мнение "лучших собаководов" Улыбающийся 
Записан
SABROG
Гость
« Ответ #10 : Сентябрь 09, 2009, 11:38 »

Самое простое попробовать самому.  Подмигивающий
Да я много чего могу сам попробовать Улыбающийся Но хотелось бы услышать авторитетное мнение "лучших собаководов" Улыбающийся 

К варианту, который предложил BRE нужен комментарий. Ты сможешь узнать, что значение изменилось. Но не по пришедшим в метод параметрам, т.к. параметров не будет:

Код
C++ (Qt)
void MainWindow::changed()
{
}

, а только через sender(). Но тут возникнет другая проблема. К какому из контролов приводить указатель QObject? QSpinBox или QDoubleSpinBox? В принципе это можно узнать через sender()->metaObject()->className(). Или можно воспользовать общим базовым классом QAbstractSpinBox и использовать QVariant'ное свойство value() и преобразовывать в то, чем удобнее пользоваться:

Код
C++ (Qt)
void MainWindow::changed()
{
   QAbstractSpinBox *sb = qobject_cast<QAbstractSpinBox *>(sender());
   qDebug() << sender()->metaObject()->className() << sb->property("value");
}
 
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #11 : Сентябрь 09, 2009, 12:08 »

, а только через sender(). Но тут возникнет другая проблема. К какому из контролов приводить указатель QObject? QSpinBox или QDoubleSpinBox?
Как минимум я могу тупо приводить "к известному мне типу", т.е. я просто знаю что "под этим ID у меня  QDoubleSpinBox, а под этим - QLineEdit" и.т.д  Ошибки легко отловить (qobject_cast вернет NULL). Может это и не идеально, но все же лучше чем иметь массу видимых объектов и слотов.
Записан
SABROG
Гость
« Ответ #12 : Сентябрь 09, 2009, 12:43 »

С моей точки зрения это плохой тон программирования. Потом интерфейс программы будет тяжело модифицировать, т.к. при каждом удалении, добавлении придется вспоминать в каких местах кода нужно сделать изменения. Лучше сделать 10 слотов под каждый тип данных, чем один, но с возможным будущим геморроем.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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