Название: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: niXman от Февраль 06, 2009, 10:59
Доброго времени суток! Есть необходимость часть текста/слова выделить другим шрифтом/цветом.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: spirit от Февраль 06, 2009, 11:19
никак. QTextLayout и прочая хрень запривачена в QLineEditPrivate. я делал такой эдитор, но весь код пришлось перетянуть из оригинального QLineEdit.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: niXman от Февраль 06, 2009, 11:20
А с QLabel такое можно проделать?
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: spirit от Февраль 06, 2009, 11:27
по идее да. не пробовал если честно :)
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: BRE от Февраль 06, 2009, 11:38
А с QLabel такое можно проделать?
QLabel поддерживает html-tags: C++ (Qt) label->setText( tr( "Text <b>Bold text</b> <font color=red>Red text</font>" ) );
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: niXman от Февраль 06, 2009, 11:51
СПАСИБО!!!
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: SABROG от Февраль 07, 2009, 12:38
никак. QTextLayout и прочая хрень запривачена в QLineEditPrivate. я делал такой эдитор, но весь код пришлось перетянуть из оригинального QLineEdit.
Все это правильно. Но если уже приперло, то можно и похакать, все тайное станет явным: C++ (Qt) #include <QtGui/QTextLayout> #include <QtGui/private/qlineedit_p.h> #include <QtGui/QLineEdit> ... class myEdit : public QLineEdit { Q_OBJECT public: myEdit(QWidget *parent) : QLineEdit(parent) { } ~myEdit(){} using QObject::d_ptr; }; ... myEdit *edit = new myEdit(this); edit->setText("test"); edit->show(); QLineEditPrivate *pedit = (QLineEditPrivate *)edit->d_ptr; QTextLayout &lay = pedit->textLayout; qDebug() << lay.text();
Вкратце расскажу, что происходит. Подключаем приватный хедер, наследумся от QLineEdit, чтобы получить доступ к приватному члену данных d_ptr и вытащить его наружу. Судя по исходникам QLineEdit в нем содержится указатель на QLineEditPrivate. Затем для теста используем обычный метод QLineEdit::setText и получаем подтверждение того, что всё работает в консоли вызывая метод QTextLayout::text(). Вопрос в том как QTextLayout нам поможет отрисовывать rich text контент?
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: niXman от Февраль 07, 2009, 14:24
Рано обрадовался... :-\ Все же придется делать аналоги QLineEdit и QListWidget с необходимым функционалом.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: ритт от Февраль 08, 2009, 05:04
необходимо хачить чтобы сработало `Q_D(QLineEdit)` => чтобы обновилось значение d->vscroll/d->hscroll => чтобы правильно срабатывали QLineEditPrivate::cursorRect(...) и т.п. /* если не забуду, отпишусь в ТТ по поводу d->vscroll/d->hscroll, т.к. из-за этой хрени фактически становится невозможным нормально наследоваться от QLineEdit */ C++ (Qt) // hardcoded in qlineedit.cpp #define verticalMargin 1 #define horizontalMargin 2 /*!\reimp */ void MyLineEdit::paintEvent(QPaintEvent *) { Q_D(QLineEdit); QPainter p(this); QRect r = rect(); QPalette pal = palette(); QStyleOptionFrameV2 panel; initStyleOption(&panel); style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this); r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this); #if QT_VERSION >= 0x040500 int left, top, right, bottom; getTextMargins(&left, &top, &right, &bottom); r.adjust(left, top, -right, -bottom); #endif p.setClipRect(r); QFontMetrics fm = fontMetrics(); Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(d->alignment)); switch (va & Qt::AlignVertical_Mask) { case Qt::AlignBottom: d->vscroll = r.y() + r.height() - fm.height() - verticalMargin; break; case Qt::AlignTop: d->vscroll = r.y() + verticalMargin; break; default: //center d->vscroll = r.y() + (r.height() - fm.height() + 1) / 2; break; } QRect lineRect(r.x() + horizontalMargin, d->vscroll, r.width() - 2*horizontalMargin, fm.height()); QTextLine line = d->textLayout.lineAt(0); int cursor = d->cursor; if (d->preeditCursor != -1) cursor += d->preeditCursor; // locate cursor position int cix = qRound(line.cursorToX(cursor)); // horizontal scrolling. d->hscroll is the left indent from the beginning // of the text line to the left edge of lineRect. we update this value // depending on the delta from the last paint event; in effect this means // the below code handles all scrolling based on the textline (widthUsed, // minLB, minRB), the line edit rect (lineRect) and the cursor position // (cix). int minLB = qMax(0, -fm.minLeftBearing()); int minRB = qMax(0, -fm.minRightBearing()); int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB; if ((minLB + widthUsed) <= lineRect.width()) { // text fits in lineRect; use hscroll for alignment switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: d->hscroll = widthUsed - lineRect.width() + 1; break; case Qt::AlignHCenter: d->hscroll = (widthUsed - lineRect.width()) / 2; break; default: // Left d->hscroll = 0; break; } d->hscroll -= minLB; } else if (cix - d->hscroll >= lineRect.width()) { // text doesn't fit, cursor is to the right of lineRect (scroll right) d->hscroll = cix - lineRect.width() + 1; } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) { // text doesn't fit, cursor is to the left of lineRect (scroll left) d->hscroll = cix; } else if (widthUsed - d->hscroll < lineRect.width()) { // text doesn't fit, text document is to the left of lineRect; align // right d->hscroll = widthUsed - lineRect.width() + 1; } // the y offset is there to keep the baseline constant in case we have script changes in the text. QPoint topLeft = lineRect.topLeft() - QPoint(d->hscroll, d->ascent - fm.ascent()); // draw text, selections and cursors #ifndef QT_NO_STYLE_STYLESHEET if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) { cssStyle->focusPalette(this, &panel, &pal); } #endif p.setPen(pal.text().color()); QVector<QTextLayout::FormatRange> selections; #ifdef QT_KEYPAD_NAVIGATION if (!QApplication::keypadNavigationEnabled() || hasEditFocus()) #endif if (d->selstart < d->selend || (d->cursorVisible && d->maskData && !d->readOnly)) { QTextLayout::FormatRange o; if (d->selstart < d->selend) { o.start = d->selstart; o.length = d->selend - d->selstart; o.format.setBackground(pal.brush(QPalette::Highlight)); o.format.setForeground(pal.brush(QPalette::HighlightedText)); } else { // mask selection o.start = d->cursor; o.length = 1; o.format.setBackground(pal.brush(QPalette::Text)); o.format.setForeground(pal.brush(QPalette::Window)); } selections.append(o); } /*+*/ if (/* условия для выделения блока текста жирным */) { /*+*/ QTextLayout::FormatRange o; /*+*/ o.start = 3; // начало блока (первый символ) /*+*/ o.length = 4; // длина блока в символах /*+*/ o.format.setFontWeight(QFont::Bold); /*+*/ selections.append(o); /*+*/ } // Asian users see an IM selection text as cursor on candidate // selection phase of input method, so the ordinary cursor should be // invisible if we have a preedit string. d->textLayout.draw(&p, topLeft, selections, r); if (d->cursorVisible && !d->readOnly && !d->hideCursor) d->textLayout.drawCursor(&p, topLeft, cursor, style()->pixelMetric(QStyle::PM_TextCursorWidth)); }
см. код, помеченный /*+*/ т.о. возможно использовать любое оформление, предусмотренное классом QTextCharFormat
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: niXman от Февраль 10, 2009, 02:04
Мысль понятна. Буду пробовать.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: ритт от Февраль 13, 2009, 08:09
ха! нашёл способ использовать произвольное оформление текста в лайнэдите вообще без наследования :) код будет позже.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: ритт от Февраль 13, 2009, 09:14
niXman, я даже не знаю чем ты со мной за это расплачиваться будешь ;) C++ (Qt) static void setLineEditTextFormat(QLineEdit* lineEdit, const QList<QTextLayout::FormatRange>& formats) { if(!lineEdit) return; QList<QInputMethodEvent::Attribute> attributes; foreach(const QTextLayout::FormatRange& fr, formats) { // [b]обязательно[/b] нужно отнять от требуемой стартовой позиции текущую позицию курсора. // можно обойтись без этого, если в начало и конец списка вставить специально подготовленные // атрибуты, но меня и такой вариант устраивает QInputMethodEvent::AttributeType type = QInputMethodEvent::TextFormat; int start = fr.start - lineEdit->cursorPosition(); int length = fr.length; QVariant value = fr.format; attributes.append(QInputMethodEvent::Attribute(type, start, length, value)); } QInputMethodEvent event(QString(), attributes); QCoreApplication::sendEvent(lineEdit, &event); } static void clearLineEditTextFormat(QLineEdit* lineEdit) { setLineEditTextFormat(lineEdit, QList<QTextLayout::FormatRange>()); } // наглядный пример: QLineEdit* lineEdit = new QLineEdit; lineEdit->setText(tr("Task Tracker - Entry")); QList<QTextLayout::FormatRange> formats; QTextCharFormat f; f.setFontWeight(QFont::Bold); QTextLayout::FormatRange fr_task; fr_task.start = 0; fr_task.length = 4; fr_task.format = f; f.setFontItalic(true); f.setBackground(Qt::darkYellow); f.setForeground(Qt::white); QTextLayout::FormatRange fr_tracker; fr_tracker.start = 5; fr_tracker.length = 7; fr_tracker.format = f; f = QTextCharFormat(); f.setForeground(Qt::gray); QTextLayout::FormatRange fr_entry; fr_entry.start = 15; fr_entry.length = 5; fr_entry.format = f; formats.append(fr_task); formats.append(fr_tracker); formats.append(fr_entry); customizeLineEditText(lineEdit, formats);
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: igor_bogomolov от Февраль 13, 2009, 10:36
А если в lineEdit нужно свойство setReadOnly(true). Как сделать чтобы форматирование сохранилось?
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: ритт от Февраль 13, 2009, 12:21
с ридонли лайнэдит отключает доставку событий QInputMethodEvent. если даже вызвать inputMethodEvent напрямую, любое событие QInputMethodEvent будет проигнорировано. единственный вариант - унаследоваться от лайнэдита и перегрузить inputMethodEvent следующим образом: C++ (Qt) void MyLineEdit::inputMethodEvent(QInputMethodEvent *e) { bool wasReadOnly = isReadOnly(); if(wasReadOnly) setReadOnly(false); QLineEdit::inputMethodEvent(QInputMethodEvent *e); setReadOnly(wasReadOnly); }
также следует добавить, что доставка отключается и для echoMode() != QLineEdit::Normal && echoMode() != QLineEdit::PasswordEchoOnEdit если изменить echoMode после такого "раскрашивания" текста, получится не то, чего пользователь ожидает :) да, ещё не забываем, такое форматирование является перманентным и позиции FormatRange-а не изменяются при изменении текста - нужно отлавливать textchanged и сбрасывать/задавать форматирование заново.
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: Андрей80 от Февраль 23, 2009, 15:13
C:\Qt\4.3.3\examples\richtext\syntaxhighlighter\release Ваш случай по моему
Название: Re: QLineEdit - фрагмент текста жирным шрифтом.
Отправлено: spirit от Февраль 23, 2009, 15:45
C:\Qt\4.3.3\examples\richtext\syntaxhighlighter\release Ваш случай по моему
хайлайтер используется вместе с QTextEdit The QSyntaxHighlighter class is a base class for implementing QTextEdit syntax highlighters. A syntax highligher automatically highlights parts of the text in a QTextEdit, or more generally in a QTextDocument. Syntax highlighters are often used when the user is entering text in a specific format (for example source code) and help the user to read the text and identify syntax errors.
а в топике идет речь о QLineEdit.
|