QT 4: программирование GUI на С++
Шрифт:
Функция evalTerm очень напоминает функцию evalExpression, но, в отличие от последней, она имеет дело с операциями умножения и деления. В функции evalTerm необходимо
Функция evalFactor немного сложнее, чем evalExpression и evalTerm. Мы начинаем с проверки, не является ли фактор отрицательным. Затем мы проверяем наличие открытой скобки. Если она имеется, мы анализируем значение внутри скобок как выражение, вызывая evalExpression. При анализе выражения в скобках evalExpression вызывает функцию evalTerm, которая вызывает функцию evalFactor,
Если фактором не является вложенное выражение, мы выделяем следующую лексему (token), и она должна задавать обозначение ячейки или быть числом. Если эта лексема удовлетворяет регулярному выражению в переменной QRegExp, мы считаем, что она является ссылкой на ячейку, и вызываем функцию value для этой ячейки. Ячейка может располагаться в любом месте в электронной таблице, и она может ссылаться на другие ячейки. Такая зависимость не вызывает проблемы и просто приводит к дополнительным вызовам функции value и к дополнительному синтаксическому анализу ячеек с признаком «dirty» («грязный») для перерасчета значений всех зависимых ячеек. Если лексема не является ссылкой на ячейку, мы рассматриваем ее как число.
Что произойдет, если ячейка A1 содержит формулу «=A1»? Или если ячейка A1 содержит «=A2», а ячейка A2 содержит «=A1»? Хотя нами не написан специальный программный код для обнаружения бесконечных циклов в рекурсивных зависимостях, парсер прекрасно справится с этой ситуацией и возвратит недопустимое значение переменной типа QVariant. Это даст нужный результат, поскольку мы устанавливаем флажок cacheIsDirty на значение false и переменную cachedValue на значение Invalid в функции value перед вызовом evalExpression. Если evalExpression рекурсивно вызывает функцию value для той же ячейки, она немедленно возвращает значение Invalid, и тогда все выражение принимает значение Invalid.
Теперь мы завершили программу синтаксического анализа формул. Ее можно легко модифицировать для обработки стандартных функций электронной таблицы, например «sum» и «avg», расширяя грамматическое определение фактора. Можно также легко расширить эту реализацию, обеспечив возможность выполнения операции «+» над строковыми операндами (для их конкатенации); это не потребует внесения изменений в грамматику.
Глава 5. Создание пользовательских виджетов
В данной главе объясняются способы создания пользовательских виджетов с помощью средств разработки Qt. Пользовательские виджеты могут создаваться путем определения подкласса существующего виджета Qt или путем определения непосредственно подкласса QWidget. Мы продемонстрируем оба подхода, и мы рассмотрим также способы интеграции пользовательского виджета в Qt Designer, чтобы его можно было применять совершенно так же, как встроенный виджет Qt. Мы закончим данную главу примером пользовательского виджета, в котором используется двойная буферизация — эффективный метод быстрого рисования.
Настройка виджетов Qt
В некоторых случаях мы обнаруживаем необходимость в более специализированной настройке виджета Qt по сравнению с той, которую можно обеспечить путем установки его свойств в Qt Designer или с помощью вызова его функций. Простое и прямое решение заключается в создании подкласса соответствующего виджетного класса и адаптации его под наши требования.
Рис. 5.1. Виджет HexSpinBox.