View Full Version : QGraphicsTextItem and text cursor position via QPoint
Lykurg
17th April 2009, 11:49
Hi,
I have a customized QGraphicsTextItem. By default the item is not editable. If one would like to change the content he has to double click the item:
void MyWordItem::mouseDoubleClickEvent(QGraphicsSceneMo useEvent */*event*/)
{
setTextInteractionFlags(Qt::TextEditorInteraction) ;
}
Now every time the blinking cursor is at the position 0, but I want the text cursor to be near the mouse double click position. (Like the result if one click the mouse button a third time.) Looking through QTextCursor, QTextDocument for a function like setTextCursorPos(QPoint) faild (I would like to use event->pos()). Even in the sources I don't figure out how the trolls do it in the mouse press reimp...
Passing the event to QGraphicsTextItem::mouseDoubleClickEvent(event); or QGraphicsTextItem::mousePressEvent(event); ends in a total selection of the content.
Any suggestions?
Thanks
mhennings
6th December 2012, 16:37
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);
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)
{
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();
}
}
Now we want to turn on the editor mode on mouseDoubleClick:
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::GraphicsSceneMous ePress);
click->setButton(evt->button());
click->setPos(evt->pos());
QGraphicsTextItem::mousePressEvent(click);
delete click; // don't forget to delete the event
}
To leave the editor mode, it is sufficient to wait for the deselection event:
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);
}
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).
Rafe
10th July 2017, 19:38
Thanks for this!
Here is a near-verbatim refactor to Python that runs:
(Replace YOUR_CLASS with your class)
.
def setTextInteraction(self, state, selectAll=False):
if state and self.textInteractionFlags() == QtCore.Qt.NoTextInteraction:
# switch on editor mode:
self.setTextInteractionFlags(QtCore.Qt.TextEditorI nteraction)
# manually do what a mouse click would do else:
self.setFocus(QtCore.Qt.MouseFocusReason) # give the item keyboard focus
self.setSelected(True) # ensure 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)
c = self.textCursor()
c.select(QtGui.QTextCursor.Document)
self.setTextCursor(c)
elif not state and self.textInteractionFlags() == QtCore.Qt.TextEditorInteraction:
# turn off editor mode:
self.setTextInteractionFlags(QtCore.Qt.NoTextInter action)
# deselect text (else it keeps gray shade):
c = self.textCursor()
c.clearSelection()
self.setTextCursor(c)
self.clearFocus()
def mouseDoubleClickEvent(self, event):
log.warn("mouseDoubleClickEvent '%s'", self.toPlainText())
if self.textInteractionFlags() == QtCore.Qt.TextEditorInteraction:
# if editor mode is already on: pass double click events on to the editor:
super(YOUR_CLASS, self).mouseDoubleClickEvent(event)
return
# if editor mode is off:
# 1. turn editor mode on and set selected and focused:
self.setTextInteraction(True)
# 2. send a single click to this QGraphicsTextItem (will set the cursor to the mouse pos)
# create a mouse event with the same parameters as event
click = QtGui.QGraphicsSceneMouseEvent(QtCore.QEvent.Graph icsSceneMousePress)
click.setButton(event.button())
click.setPos(event.pos())
self.mousePressEvent(click)
def itemChange(self, change, value):
if change == QtGui.QGraphicsItem.ItemSelectedChange:
log.warn("itemChange '%s', selected=%s", self.toPlainText(), value)
if change == QtGui.QGraphicsItem.ItemSelectedChange \
and self.textInteractionFlags() != QtCore.Qt.NoTextInteraction \
and not value:
# item received SelectedChange event AND is in editor mode AND is about to be deselected
self.setTextInteraction(False) # leave editor mode
return super(YOUR_CLASS, self).itemChange(change, value)
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.