I have implemented ComboBoxDelegate. It is derived from QStyledItemDelegate. Paint function is used to show the content of cell when it is not editing node.
void ComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QStyleOptionComboBox comboBoxOption;
comboBoxOption.rect = option.rect;
comboBoxOption.state = QStyle::State_Active | QStyle::State_Enabled;
comboBoxOption.frame = true;
comboBoxOption.currentText = index.model()->data(index).toString();
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &comboBoxOption, painter);
QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &comboBoxOption, painter);
}
Now I am trying to implement LineEditDelegate. I don't know how to write its paint function. Is there QStyleOptionComboBox like class for QLineEdit? Can you please share your code if anyone have done it?
Try this answer.
It uses QStyle::drawPrimitive with QStyle::PE_PanelLineEdit element.
Related
I have the delegate class and method paint in it. I would like to show the comboboxes in the QTreeWidget columns and do for it
ui->treeWidget->setItemDelegateForColumn(2, box);
where box is the object of my delegate
The paint method is
void ComboboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionComboBox box;
QString text = values[1];
box.currentText = text;
box.rect = option.rect;
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, 0);
QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &box, painter, 0);
}
values is the QMap with two variables - "Hello" and "Goodbye"
But instead of drawing comboboxes treewidget shows just "Hello" strings in second column
Why?
How can i fix it?
If you have qss files and want to customize your QComboBox delegate you should add some combobox in paint() method and replace that:
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, 0);
to:
QComboBox tmp;
QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, &tmp);
I have a QTableView and i want to highlight the actual word under the current mouse pointer
so how can I find this word?
void LogItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QString text = index.model()->data(index, Qt::DisplayRole).toString();
// so how can i find the word under the mousepointer
}
Try this:
QString text = index.model()->data(index, Qt::DisplayRole).toString();
if(option.state & QStyle::State_MouseOver)
{
painter->setPen(Qt::blue);
painter->drawText(option.rect,text);
}
else
{
QStyledItemDelegate::paint(painter,option,index);
}
Also you can try:
painter->drawText(option.rect.adjusted(3, 7, 0, 0),txt);
for better visual representation.
But I can predict that this will not work. Why? You should allow mouse tracking, so just add:
ui->tableView->setMouseTracking(true);
ui->tableView->setItemDelegate(new LogItemDelegate);
I have reimplemented paint() function for QTreeWidget, I want to show data of second column bold, but it doesn't work.
How can i fix it?
void extendedQItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
const QString txt = index.data().toString();
painter->save();
QFont painterFont;
if (index.column() == 1) {
painterFont.setBold(true);
painterFont.setStretch(20);
}
painter->setFont(painterFont);
drawDisplay(painter, option, rect, txt);
painter->restore();
}
I attached a screen shot of the problem, second half should be bold
You forgot to add your extendedQItemDelegate to the QTreeView/QTreeWidget object via the setItemDelegate member function.
As an example:
QTreeWidget* tree_view = ...;
extendedQItemDelegate* extended_item_delegate = ...;
tree_view->setItemDelegate(extended_item_delegate);
You need to make a copy of the const QStyleOptionViewItem &option, apply your font changes to that copy, then paint using your copy instead of the original option passed to the function.
void extendedQItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
const QString txt = index.data().toString();
painter->save();
QStyleOptionViewItem optCopy = option; // make a copy to modify
if (index.column() == 1) {
optCopy.font.setBold(true); // set attributes on the copy
optCopy.font.setStretch(20);
}
drawDisplay(painter, optCopy, rect, txt); // use copy to paint with
painter->restore();
}
(Just realized this is an old question but it had popped up to the top of qt tags.)
I am making a table control that displays some additional text data apart from those in DisplayRole of its model. In all other respects text and cell display should be identical. What i am having trouble with is correct display of highlighted cell.
I am currently using the following code:
void MatchDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (option.state & QStyle::State_Selected)
painter->fillRect(option.rect, option.palette.highlight());
painter->save();
QString str = qvariant_cast<QString>(index.data())+ "\n";
str += QString::number(qvariant_cast<float>(index.data(Qt::UserRole)));
if (option.state & QStyle::State_Selected)
painter->setBrush(option.palette.highlightedText());
else
painter->setBrush(qvariant_cast<QBrush>(index.data(Qt::ForegroundRole)));
painter->drawText(option.rect, qvariant_cast<int>(index.data(Qt::TextAlignmentRole)), str);
painter->restore();
}
However, the result looks like this:
Text color is wrong, there is no dashing line around the cell, and when the control loses focus, the cell remains blue instead of becoming light gray like drawn by default cells do.
How should painting code be changed to fix those issues?
Please try below code, It will work.
Set drawControl with take care to draw dashed line( Let Qt take care it internally ) when selected.
Fixed( Dashed line, Text color and multiline ) while selecting cell.
void MatchDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
const QWidget *widget = option.widget;
QString str = qvariant_cast<QString>(index.data())+ "\n";
str += QString::number(qvariant_cast<float>(index.data(Qt::UserRole)));
opt.text = "";
//option
QStyle *style = widget ? widget->style() : QApplication::style();
if (option.state & QStyle::State_Selected)
{
// Whitee pen while selection
painter->setPen(Qt::white);
painter->setBrush(option.palette.highlightedText());
// This call will take care to draw, dashed line while selecting
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}
else
{
painter->setPen(QPen(option.palette.foreground(), 0));
painter->setBrush(qvariant_cast<QBrush>(index.data(Qt::ForegroundRole)));
}
painter->drawText(option.rect, qvariant_cast<int>(index.data(Qt::TextAlignmentRole)), str);
}
What is the best way to present a clickable URL in a QTableView (or QTreeView, QListView, etc...)
Given a QStandardItemModel where some of the columns contain text with URLs I'd like them to become clickable and then handle the click by using QDesktopServices::openURL()
I was hoping there would be some easy way to leverage QLabel's textInteraction flags and to cram them into the table. I can't believe there's not an easier way to handle this. I really hope I'm missing something.
You'll need to create a delegate to do the painting. The code should look something like this:
void RenderLinkDelegate::paint(
QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index
) const
{
QString text = index.data(Qt::DisplayRole).toString();
if (text.isEmpty())
return;
painter->save();
// I only wanted it for mouse over, but you'll probably want to remove
// this condition
if (option.state & QStyle::State_MouseOver)
{
QFont font = option.font;
font.setUnderline(true);
painter->setFont(font);
painter->setPen(option.palette.link().color());
}
painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, text);
painter->restore();
}
Well, you can use delegates to render rich text in a qtableview with custom delegates reimplementing the paint method such as:
void CHtmlDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt(option);
QLabel *label = new QLabel;
label->setText(index.data().toString());
label->setTextFormat(Qt::RichText);
label->setGeometry(option.rect);
label->setStyleSheet("QLabel { background-color : transparent; }");
painter->translate(option.rect.topLeft());
label->render(painter);
painter->translate(-option.rect.topLeft());
}
However, it will not make hyperlinks clickable.
To do so, you can use the following hack. Reimplement the setModel method of your table/list view and use setIndexWidget.
void MyView::setModel(QAbstractItemModel *m)
{
if (!m)
return;
QTableView::setModel(m);
const int rows = model()->rowCount();
for (int i = 0; i < rows; ++i)
{
QModelIndex idx = model()->index(i, 1);
QLabel *label = new QLabel;
label->setTextFormat(Qt::RichText);
label->setText(model()->data(idx, CTableModel::HtmlRole).toString());
label->setOpenExternalLinks(true);
setIndexWidget(idx, label);
}
}
In the example above, I replace column 1 with qlabels. Note that you need to void the display role in the model to avoid overlapping data.
Anyway, I would be interested in a better solution based on delegates.
Sadly, its not that easy to render a QLabel with setOpenExternalLinks() when using a QTableView (as opposed to using a QTableWidget). There are no magic two lines of code you can call and have the job done.
use a delegate
set the delegate to the column of your table
use QTextDocument combined with setHTML() to render a html link
this means your model needs to provide an HTML fragment containing a href
calculate the geometry of the link and provide event handlers for to intercept the mouse
change the cursor when it is over the link
execute the action when the link is clicked
what a mess :( i want painter->setWidgetToCell()
--
void LabelColumnItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if( option.state & QStyle::State_Selected )
painter->fillRect( option.rect, option.palette.highlight() );
painter->save();
QTextDocument document; // <---- RichText
document.setTextWidth(option.rect.width());
QVariant value = index.data(Qt::DisplayRole);
if (value.isValid() && !value.isNull())
{
document.setHtml(value.toString()); // <---- make sure model contains html
painter->translate(option.rect.topLeft());
document.drawContents(painter);
}
painter->restore();
}