Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > Как реализовать аналог бегущей строки? |
Автор: KL7 27.7.2009, 12:28 |
Для определенных задумок необходим аналог QLineEdit, но с полным контролем горизонтального расположения текста... Будем считать что надо реализовать нециклическую бегущую строку (прям как в новостях ![]() Анимационная составляющая мне кажется не проблемой (освоюсь с таймерами и справлюсь наверно), но проблема в том, что мне нужно плавное движение текста, т.е. возможность при необходимости передвинуть текст скажем на 1px... Так же необходима грамотная обработка виджета справа и слева, т.е. как же будут появляться и исчезать символы, после того, как они появились в видимой области или покинули ее... Как ето можно реализовать? Идеи у меня есть, но пока они слишком абстрактны... Если у кого-то есть варианты, буду благодарен за любые предложения ![]() |
Автор: andrew_121 27.7.2009, 13:29 | ||
Что-то вроде:
По моему, нужно копать в сторону QPaintDevice. Не уверен. |
Автор: Любитель 27.7.2009, 13:40 |
Тебе нужно только отображение данных или и редактирование тоже? |
Автор: pan2004 27.7.2009, 15:38 |
Делаешь свой виджет, и пишешь в нем свою paintEvent(), в котором выводишь строку в зависимости от QTimeLine. Можно и с субпиксельной точностью, благо QPainter поддерживает дробные координаты Если нужно редактирование, при щелчке заменяешь его на обычный QLineEdit. Я думаю, бегающую строку неудобно редактировать в анимированном виде) |
Автор: SABROG 27.7.2009, 16:04 |
http://qt.shamangrad.net/doku.php?id=%D0%B1%D0%B5%D0%B3%D1%83%D1%89%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0, может почерпнешь какую-нибудь идею. |
Автор: KL7 28.7.2009, 21:34 |
SABROG, как выяснилось, в исходниках представлен "простой" вариант бегущей строки, в которой текст сдвигается посимвольно... мне же хотелось бы иметь попиксельный вариант... в общем я начал писать свой виджет =) вопрос первый: текст я буду рисовать в нужной позиции, используя QPainter, т.е. в конечном счете текст превратится в изображение... но мне необходимо, чтобы в окне был виден только та часть текста, которая находится внутри моего виджета... для етого надо использовать ClipArea? в свою очередь мне хотелось бы, чтобы виджет был ограничен рамкой, схожей с рамкой QLineEdit, которая с радостью подвергается изменениям через таблицы стилей: изменяется ее цвет, толщина, радиус и отступ(padding)... как ето реализовать? чем я должен ограничить свой виджет для таких целей и как ето сделать? судя по документации QLineEdit рисует рамку через QFrame (весьма логично), искользуя свойства из QStyleOptionFrame... ето можно сделать через drawPrimitive, используя все те же свойства... но как инициализировать QStyleOptionFrame используя правила из stylesheet-файла? и как потом получить размер и положение области, которая находится полностью внутри QFrame (желательно с учетом padding)? если ее получить, то она может выступать в качестве ClipArea... дальше пока все выглядит весьма прозрачно... рисую текст в нужной позиции (все что вне виджета будет просто оставаться невидимым), а по таймеру пересчитываю позиции и если нужно редактирую отображаемый текст (если символ уже гарантированно вылез из поля виджета, то он просто удаляется из строки, а при необходимости справа добавляются новые символы)... |
Автор: KL7 4.8.2009, 11:45 |
пишу потиху свой виджет... возникло пару вопросов... 1. Мой виджет путем drawPrimitive обретает вокруг себя рамочку... ета рамочка рисуется с учетом всех stylesheet-свойств, в том числе padding... потом, используя SE_FrameContent, я получаю прямоугольник, расположенный внутри рамочки и внутри padding-a, в котором я рисую свой текст... а теперь мне надо получить точно такой же прямоугольник, но уже содержащий padding-область... ето прямоугольник я хочу залить 50/50 двумя фоновыми цветами... но я так и не смог получить ни сам треугольник прямоугольник, ни размеры padding-a (можно наверно самому проанализировать stylesheet и из него вытянуть, например, "padding: 5px", но может есть более приемлемые методы?) 2. Мой виджет подразумевает ввод текста... или скорее не ввод, а обработку текста... вобщем он должен особым образом реагировать на нажатия клавиш, отвечающих за печатные символы... как ето грамотно сделать? что надо работать с keyPressEvent - ето мне понятно... про модификаторы (shift) также что-то читал, но общая схема пока не понятна... буду благодарен за помощь... |
Автор: SABROG 4.8.2009, 12:41 |
Вероятно опечатка? Ты выбрал для себя не простую задачу. Мало у кого есть опыт рисования собственного виджета, а те у кого он есть ввязываться в это не будут, т.к. прекрасно понимают сколько там еще геморроя впереди. Я как-то заморачивался с собственным titlebar'ом и чужим combobox'ом, больше мне не хочется в это втягиваться. Могу лишь посоветовать изучать исходники Qt и исходники чужих виджетов. |
Автор: KL7 4.8.2009, 15:06 | ||
так и есть =)
спасибо, обнадежили =) ну я не имею наполеоновских планов... просто пока у меня нет ни одной конкретной задачи, вот решил что-нибудь пописать, но чтобы интересно было... не получится - значит не получится, но опыт какой-то точно получу.. если рисовать совсем свой виджет без поддержки stylesheet-ов, то все не так уж и сложно... сам как-нибудь обработал отступы, рамочки и можно даже для всего сделать настройки... но я хотел попытаться адаптировать самодельный виджет под Qt-стили... но все оказалось труднее, чем я предполагал, поскольку прямого доступа к элементам стиля не имеешь, а предлагаемые примитивы (элементы виджетов, различные области) похоже охватывают не все аспекты... а исходники... все конечно хорошо, но сложно... я пытался изучать QLineEdit... какую-то информацию оттуда почерпнул, но в реализации класса широко применяются свои внутренние технологии, которые в "общественном" Qt никак не представлены (или просто не описаны)... так, например, там используется какой-то удивительный заголовочный private-файл, различные макросы и те же элементы стиля (отступы, толщина и ширина) берутся из какого-то удивительного объекта, сущность которого я пока не осознал... возможно в етом и нет необходимости... буду ковыряться - до сентября еще месяц каникул =) и все же если будут предложения - буду признателен... тут пожалуй основная проблема - внутри чего рисовать етот текст... был бы QFrame более навороченным (возможно я его плохо знаю ![]() |
Автор: SABROG 4.8.2009, 15:21 |
Посмотри может исходники виджетов http://www.wysota.eu.org/wwwidgets/ и тут http://www.qt-apps.org/index.php?xcontentmode=4298 |
Автор: KL7 4.8.2009, 18:05 | ||||
спасибо... буду изучать... хотя wwwidget-ы написаны в том же стиле, что и стандартные, а там мне далеко не все понятно... но буду разбираться =) а подскажите, как получить прямоугольник, описывающий внутреннюю область рамки, которая рисуется таким вот образом:
рамочка имеет толщину и закругления, заданные через stylesheet... пока ето основная проблема... |
Автор: SABROG 4.8.2009, 19:16 | ||
К сожалению у меня были плохие оценки в школе, я совершенно не понимаю, что от меня требуется, когда читаю задачу.
А эти параметры нельзя получить, если в документации кликнуть на ссылку "List of all members, including inherited members"? |
Автор: KL7 5.8.2009, 07:26 | ||||
попытаюсь объяснить доходчивее... http://ipicture.ru/Gallery/Viewfull/21794321.html мне нужно любым путем получить характеристики желтого прямоугольника... буду признателен, если прямо и без иронии скажете, как ето сделать...
применительно к какому классу? QFrame-а у меня в коде нет... возможно стоит наследовать мой виджет от QFrame, но ето другой вопрос... int QStyleOptionFrame::lineWidth пока мне ничего кроме нуля не согласился вернуть, хотя рамочка рисуется толщиной в 6 пикселей... радиус закругления мне в принципе не нужен, но ради интереса поискал - не нашел я его нигде в Qt Assistant-e... так что этот параметр похоже нельзя получить даже "если в документации кликнуть на ссылку "List of all members, including inherited members"... |
Автор: Любитель 5.8.2009, 07:50 |
Привязываться к стайлшитам не есть гуд. Вообще говоря - эта рамка зависит от стиля (QStyle) для текущего виджета/апилкейшена. При установке стайлшита используется прокси-стиль QStyleSheetStyle. Который.. вообще говоря вроде не экспортируется из Qt (всмысле экспортируется то - само собой, но в официальных инклюдах его нет). Далее - у него есть метод renderRule, позволяющий получить правила отображения для конкретного виджета, у коготорого метод borderRect... Одним словом - документированного способа получить толщину бордера нельзя. К сожалению, но это минус проектирования QStyle (хотя скорее - стайлшитов, ибо можно было в QStyleOption::initFrom считывать стиль виджета, а у стиля иметь методы инициализирующие ту же толщину бордера.. Как-то так. |
Автор: KL7 5.8.2009, 08:35 |
понятно... и если нужна полноценная поддержка чего-то наподобие скинов, то надо читать в сторону стилей? подумаем... не хотелось бы разводить много тем, так что еще спрошу: покажите, где почитать про private-классы (например, QLabel активно взаимодействует с QLabelPrivate), которые нередко в Qt используются... хоть какую-то информацию о том, каково предназначение и как использовать ету технологию... она ведь наверняка как-то обоснована... |
Автор: Любитель 5.8.2009, 08:48 | ||||
Стайлшиты реализуются через QStyleSheetStyle. Только его почему-то решили сделать недокументированным.. Но тем не менее - это один из стилей.
Ну, по сути классический с++-ный паттерн PImpl. Преимущество в отсутствии необходимости вынесения деталей в хидер. Ведь даже при изменении прайват данных класса мы должны перекомпилировать всё, что использует этот класс (всмысле использует класс, а не используется классом). Выделение же отдельного внутреннего класса + указатель на объект этого класса в хидере позволяет этого избежать. Другими словами - это общепринятый костыль ![]() |
Автор: KL7 8.8.2009, 18:30 | ||||||
во-первых, спасибо за информацию =) почитал, стало гораздо понятнее... пытался применить в данном проекте, но пока и без новых паттернов проблем хватает, но в будущем буду знакомится с такими вещами... а теперь... мой виджет... функциональность реализована примерно на 80% =) Т.е. он уже почти умеет все, что должен... но качество реализации не важное... ![]() собственно код... main.cpp
typingarea.h
typingarea.cpp
1. Буду благодарен за любую критику (как в сторону реализации, так и в сторону грамотности кода). Только не в слишком грубой форме. 2. Проблема анимации... В светлом будущем, в которое мы с Вами идет, етот виджет станет основной частью клавиатурного тренажера. Причины две: мне нужна интересная задача, чтобы набраться опыта, и мне нужен тернажер моей мечты с плавной прокруткой строки и другими моментами. Поетому ето должен быть хороший продуманный виджет, который не будет сильно нагружать железо. Но как оказалось все не так-то просто Анимацию я реализовал как сумел. Етот код у меня на староватом компе вроде как работает, но как только я меняю величину шрифта с 35 на 55, то все начинает жутко виснуть. Размер шрифта должен лишь зумировать виджет, а скорость отклика должна сохранится.... Но виджет начинает реагировать гораздо хуже и буковки ползут раз в пять медленее... Хотелось бы решить ету проблему, так что нужен совет и пояснение, что же тут не так... Заранее приношу большие извинения за отсутствие каких-либо комментариев. И буду искренне благодарен, если Вы (абстрактный программист) не заленитесь почитать етот быть может не слишком достойный код... PS как заставить eclipse по Ctrl+Tab мирно ходить по всем вкладкам, а не только по двум последним? ![]() |
Автор: SABROG 8.8.2009, 22:20 | ||||||
На самом деле хотелось бы больше скриншотов и аттач с исходниками. На форуме не удобно изучать код. Тут, я так понимаю, приносится в жертву кроссплатформенность библиотеки. В чем необходимость наследования от QFrame, если рамку можно нарисовать самому? Возможно это лишнее. Более базового таймера чем QObject::startTimer() и QObject::timerEvent() еще не придумали.
Не знаю как остальные программисты, но я предпочитаю подобные методы оставлять в хедерах с ключевым словом inline.
Надо проанализировать профайлером. Возможно косяк в коде. Может быть готовую картинку можно закэшировать и всего-лишь двигать по виджету. |
Автор: KL7 9.8.2009, 00:18 | ||||||||||||
завтра исправлюсь...
Что имеется ввиду? В принципе это значение по умолчанию временно и оно будет пересмотрено =)
Рамка и рисуется самостоятельно, т.е. через drawPrimitive, а наследование осталось из-за первоначальных задумок. Надо заменить на QWidget
Примерно представляю, что такое профайлер, но если не трудно - задайте направление, где почитать. Кэширование, думаю, возможно, но над етим надо поработать. Несколько вариантов более простой оптимизации уже придумал. А ошибка в коде очень вероятно... Пару дней назад я в paintEvent вызывал унаследованный от QFrame метод drawFrame - виджет перерисовывался без остановки и все сильно висло. Потратил не мало времени, пока разобрался. |
Автор: SABROG 9.8.2009, 08:42 | ||
Шрифт.
http://www.ibm.com/developerworks/ru/library/l-gnuprof/index.html |
Автор: KL7 9.8.2009, 12:30 |
это я понял... Вы хотели сказать, что Comic Sans есть далеко не на всех платформах или что? почитал... в принципе разобрался... Но судя по тому, что я нашел, для работы с qt и gprof необходимо все библиотеки пересобрать в статик с параметром -pg. Если сам не смогу решить проблему, то все же пересоберу. Кое-какие корректировки в коде сделал. Лучше работать пока не стало. ![]() ------ edited ----- только что договорился с gprof, буду изучать... а наибольшие временные затраты идут на drawText... чем больше (по размерам!) текст, тем труднее приходится процессору... я оптимизировал код, но все равно на большом размере шрифта подтормаживает... буду думать |
Автор: DK2 26.4.2011, 22:26 |
Подскажите как получить значение текста из QTextEdit |
Автор: borisbn 27.4.2011, 00:05 |
DK2, ты чего ? Задаёшь вопрос в чужой теме, в которой уже почти 2 года не было обновлений ![]() ![]() |
Автор: DK2 27.4.2011, 19:05 |
темой ошибся. |