I know this thread is older than Saint Nicholas, but I had the exact same problem today and I found a solution that at least works for Qt 4.7.4.
Setup:
A customized QGraphicsTextItem class named TextItem.
In the constructor, it gets these settings:
setFlags(ItemIsSelectable | ItemIsMovable | ItemIsFocusable);
setTextInteractionFlags(Qt::NoTextInteraction);
setFlags(ItemIsSelectable | ItemIsMovable | ItemIsFocusable);
setTextInteractionFlags(Qt::NoTextInteraction);
To copy to clipboard, switch view to plain text mode
This public function turns text editor mode on or off:
void SetTextInteraction(bool on, bool selectAll = false)
{
if(on && textInteractionFlags() == Qt::NoTextInteraction)
{
// switch on editor mode:
setTextInteractionFlags(Qt::TextEditorInteraction);
// manually do what a mouse click would do else:
setFocus(Qt::MouseFocusReason); // this gives the item keyboard focus
setSelected(true); // this ensures that itemChange() gets called when we click out of the item
if(selectAll) // option to select the whole text (e.g. after creation of the TextItem)
{
setTextCursor(c);
}
}
else if(!on && textInteractionFlags() == Qt::TextEditorInteraction)
{
// turn off editor mode:
setTextInteractionFlags(Qt::NoTextInteraction);
// deselect text (else it keeps gray shade):
c.clearSelection();
this->setTextCursor(c);
clearFocus();
}
}
void SetTextInteraction(bool on, bool selectAll = false)
{
if(on && textInteractionFlags() == Qt::NoTextInteraction)
{
// switch on editor mode:
setTextInteractionFlags(Qt::TextEditorInteraction);
// manually do what a mouse click would do else:
setFocus(Qt::MouseFocusReason); // this gives the item keyboard focus
setSelected(true); // this ensures that itemChange() gets called when we click out of the item
if(selectAll) // option to select the whole text (e.g. after creation of the TextItem)
{
QTextCursor c = textCursor();
c.select(QTextCursor::Document);
setTextCursor(c);
}
}
else if(!on && textInteractionFlags() == Qt::TextEditorInteraction)
{
// turn off editor mode:
setTextInteractionFlags(Qt::NoTextInteraction);
// deselect text (else it keeps gray shade):
QTextCursor c = this->textCursor();
c.clearSelection();
this->setTextCursor(c);
clearFocus();
}
}
To copy to clipboard, switch view to plain text mode
Now we want to turn on the editor mode on mouseDoubleClick:
{
qDebug("mouseDoubleClickEvent '%s'", this->toPlainText().toStdString().c_str());
if(textInteractionFlags() == Qt::TextEditorInteraction)
{
// if editor mode is already on: pass double click events on to the editor:
return;
}
// if editor mode is off:
// 1. turn editor mode on and set selected and focused:
SetTextInteraction(true);
// 2. send a single click to this QGraphicsTextItem (this will set the cursor to the mouse position):
// create a new mouse event with the same parameters as evt
click->setButton(evt->button());
click->setPos(evt->pos());
delete click; // don't forget to delete the event
}
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *evt)
{
qDebug("mouseDoubleClickEvent '%s'", this->toPlainText().toStdString().c_str());
if(textInteractionFlags() == Qt::TextEditorInteraction)
{
// if editor mode is already on: pass double click events on to the editor:
QGraphicsTextItem::mouseDoubleClickEvent(evt);
return;
}
// if editor mode is off:
// 1. turn editor mode on and set selected and focused:
SetTextInteraction(true);
// 2. send a single click to this QGraphicsTextItem (this will set the cursor to the mouse position):
// create a new mouse event with the same parameters as evt
QGraphicsSceneMouseEvent *click = new QGraphicsSceneMouseEvent(QEvent::GraphicsSceneMousePress);
click->setButton(evt->button());
click->setPos(evt->pos());
QGraphicsTextItem::mousePressEvent(click);
delete click; // don't forget to delete the event
}
To copy to clipboard, switch view to plain text mode
To leave the editor mode, it is sufficient to wait for the deselection event:
{
if(change
== QGraphicsItem::ItemSelectedChange) qDebug
("itemChange '%s', selected=%s", this
->toPlainText
().
toStdString().
c_str(), value.
toString().
toStdString().
c_str());
&& textInteractionFlags() != Qt::NoTextInteraction
&& !value.toBool())
{
// item received SelectedChange event AND is in editor mode AND is about to be deselected:
SetTextInteraction(false); // leave editor mode
}
}
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if(change == QGraphicsItem::ItemSelectedChange) qDebug("itemChange '%s', selected=%s", this->toPlainText().toStdString().c_str(), value.toString().toStdString().c_str());
if(change == QGraphicsItem::ItemSelectedChange
&& textInteractionFlags() != Qt::NoTextInteraction
&& !value.toBool())
{
// item received SelectedChange event AND is in editor mode AND is about to be deselected:
SetTextInteraction(false); // leave editor mode
}
return QGraphicsTextItem::itemChange(change, value);
}
To copy to clipboard, switch view to plain text mode
That's all.
I left the qDebug() outputs in the code for your convenience. :-)
Since SetTextInteraction() is public, you can call it after creating a TextItem, so the user can start typing directly (you need to make sure that the view and the scene have the keyboard focus).
Bookmarks