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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема сигнал-слот при работе с double  (Прочитано 4726 раз)
dr_Begemot
Гость
« : Февраль 17, 2010, 13:12 »

Ситуация такая:
Есть некое значение min и max. Соответственно имеются setMin и setMax.

Для простоты рассмотрим только setMax:

Реализовано два сигнала и два слота для переменной m_max

Код:
public signal:
    void setMax(double val){
if( !(m_max<=val+EPS && m_max>=val-EPS) ){
                m_max=val;
                emit maxChanged(m_max);
                emit maxChanged(number(m_max));
}
    }

    bool setMax(QString val){
bool ok = false;
double dmax = val.toDouble(&ok);
if(ok)
            setMax(dmax);
return ok;
    }

    QString AxisProperty::number(double val){
return QString::number(val, 'g', getPrecision());
    }
signals:
    void maxChanged(double);
    void maxChanged(QString);

Ф-я getPrecision() вощзвращает необходимое колличество знаков, по умолчанию это 6.

Данные сигналы и слоты соединены с сигналами и слотами QLineEdit, соответственно, при вызове setMax(double val) в программе, по сигналу maxChanged(QString) вызывается  слот QLineEdit::setText(QString), тут дергается сигнал QLineEdit::textChanged(QString), на котором висит слот setMax(QString val).

Проблема в том, что если число, заданное в программе функцией setMax(double val), было точнее, чем точность, указная функцией getPrecision(), то при вызове из формы слота setMax(QString val) проверка покажет что число изменилось и будет установленное новое число.

При сравнениии вещественных числел в данном случае не помогает EPS, т.к. если, допустим, у меня есть число с 6ю знаками до запятой, то при getPrecision()==6 в QString будет записано, по сути, целое число. Изменить или увеличить значение getPrecision() нельзя, т.к. важно, сколько символов будет отображено в QLineEdit. В то же время в программе важно хранить более точное значение.

Мне в голову пришло такое решение: в слоте setMax(QString val) сравнивать значения как строки, но тут другая проблема:
если есть число 123.456 и оно будет выведено на экран как 123.456, а потом пользователь отредактирует его до 123, то число не перезапишется, т.к.  алгоритм будет считать, что в программе число более точное, а на самом деле оно просто другое.

Какие Вы видите решения проблемы?

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

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Февраль 17, 2010, 23:54 »

Проблема в том, что если число, заданное в программе функцией setMax(double val), было точнее, чем точность, указная функцией getPrecision(), то при вызове из формы слота setMax(QString val) проверка покажет что число изменилось и будет установленное новое число.
Я сталкивался с такой проблемой (правда без Qt). Пример:

- пусть отображаемая точность всего 2 знака после запятой. Пользователь ввел 3.1415, это число "принято". Затем, напр. он закрыл окно ввода и снова открыл. Отображается 3.14. Если он сейчас отредактирует - напр. 3.1, затем вернул 3.14 - точность будет потеряна, ничего не попишешь. Однако если он НЕ вводил - остается 3.1415. Это значит что я должен различать "ввод руками (пользователя)" и "ввод программно" и принимать данные только в первом случае. Насколько я знаю, в Qt это textChanged и textEdited
Записан
White Owl
Гость
« Ответ #2 : Февраль 18, 2010, 00:39 »

Скажите пожалуйста, а в чем смысл работать с одной точностью а пользователю показывать другую?
Все поля ввода должны показывать именно то, что в них введено. Точно то, что в них "хранится".
Если вам нужна большая точность во внутренних рассчетах - на здоровье, но пользователь должен видеть реальные цифры.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Февраль 18, 2010, 00:57 »

Скажите пожалуйста, а в чем смысл работать с одной точностью а пользователю показывать другую?
Все поля ввода должны показывать именно то, что в них введено. Точно то, что в них "хранится".
Если вам нужна большая точность во внутренних рассчетах - на здоровье, но пользователь должен видеть реальные цифры.
"Программа должна иметь установку сколько чисел после запятой показывать" - примерно так звучал запрос моего пользователя  Улыбающийся Да и не всегда оно "введено", бывает и "рассчитано".
Записан
White Owl
Гость
« Ответ #4 : Февраль 18, 2010, 23:54 »

"Программа должна иметь установку сколько чисел после запятой показывать" - примерно так звучал запрос моего пользователя  Улыбающийся
Ну и запросто.
В рантайме формировать маску для QLineEdit или звать setDecimals() для QDoubleSpinBox. Что может быть проще???
Записан
dr_Begemot
Гость
« Ответ #5 : Февраль 19, 2010, 09:57 »

Проблема в том, что если число, заданное в программе функцией setMax(double val), было точнее, чем точность, указная функцией getPrecision(), то при вызове из формы слота setMax(QString val) проверка покажет что число изменилось и будет установленное новое число.
Я сталкивался с такой проблемой (правда без Qt). Пример:

- пусть отображаемая точность всего 2 знака после запятой. Пользователь ввел 3.1415, это число "принято". Затем, напр. он закрыл окно ввода и снова открыл. Отображается 3.14. Если он сейчас отредактирует - напр. 3.1, затем вернул 3.14 - точность будет потеряна, ничего не попишешь. Однако если он НЕ вводил - остается 3.1415. Это значит что я должен различать "ввод руками (пользователя)" и "ввод программно" и принимать данные только в первом случае. Насколько я знаю, в Qt это textChanged и textEdited

При вызове setText(...) контролл вызывает сигнал textChanged, так же как и при редактировании пользователем тоже вызывается textChanged.
Сейчас попробую textEdited
Записан
dr_Begemot
Гость
« Ответ #6 : Февраль 19, 2010, 09:58 »

"Программа должна иметь установку сколько чисел после запятой показывать" - примерно так звучал запрос моего пользователя  Улыбающийся
Ну и запросто.
В рантайме формировать маску для QLineEdit или звать setDecimals() для QDoubleSpinBox. Что может быть проще???


Я правда не пробовал того, что Вы предложили, но подозреваю, что все равно будет вызван сигнал textChanged, причем число будет урезаным...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Февраль 19, 2010, 18:01 »

Ну и запросто.
В рантайме формировать маску для QLineEdit или звать setDecimals() для QDoubleSpinBox. Что может быть проще???
Дв, но при этом текст, попавший в QLineEdit проникает обратно в данные, обрезая их. Об этом dr_Begemot и говорит (как я понял)
Записан
White Owl
Гость
« Ответ #8 : Февраль 19, 2010, 19:06 »

Я правда не пробовал того, что Вы предложили, но подозреваю, что все равно будет вызван сигнал textChanged, причем число будет урезаным...
Правильно. Урезанным. Ну и что?
Пользователь вчера работал с числом с четырьмя знаками после запятой, а сегодня захотел работать с двумя знаками после запятой. Пользователь сходил в настройки программы и заменил там 4 на 2. Значит все поля ввода подчиняющиеся этой настройке должны урезать точность и забыть старые "более точные" значения нафиг. Пользователь хочет меньшую точность - он ее должен получить.
Не надо хранить старые более точные значения. Что есть в поле ввода, с тем и работать. Все внутренние переменные имеющие свои поля ввода должны быть равны тому что пользователь видит на экране.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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