在 QTextEdit 的任一方向上扩展选择
Extending selection in either direction in a QTextEdit
目前,QTextEdit 允许选择文本,然后仅在锚点对面的选择一侧通过 shift-click-drag 更改该选择。锚点位于选择开始的位置。如果用户试图在开始附近更改选择,则选择将围绕锚点旋转而不是扩展。我想允许从任一侧更改选择。
我的第一次尝试是简单地将锚点设置在光标所在位置的另一侧。例如,选择从 10 到 20。如果光标在位置 8 处按住 shift 单击并拖动,则锚点将设置为 20。如果光标在位置 22 处按住 shift 单击并拖动,则anchor 将设置为 10。稍后,我会尝试更强大的东西,也许基于选择的中心点。
我认为这段代码可以工作,但它似乎根本不影响默认行为。我错过了什么?
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class TextEditor(QTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setReadOnly(True)
self.setMouseTracking(True)
def mouseMoveEvent(self, event):
point = QPoint()
x = event.x() #these are relative to the upper left corner of the text edit window
y = event.y()
point.setX(x)
point.setY(y)
self.mousepos = self.cursorForPosition(point).position() # get character position of current mouse using local window coordinates
if event.buttons()==Qt.LeftButton:
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ShiftModifier:
start = -1 #initialize to something impossible
end = -1
cursor = self.textCursor()
select_point1 = cursor.selectionStart()
select_point2 = cursor.selectionEnd()
if select_point1 < select_point2: # determine order of selection points
start = select_point1
end = select_point2
elif select_point2 < select_point1:
start = select_point2
end = select_point1
if self.mousepos > end: # if past end when shift-click then trying to extend right
cursor.setPosition(start, mode=QTextCursor.MoveAnchor)
elif self.mousepos < start: # if before start when shift-click then trying to extend left
cursor.setPosition(end, mode=QTextCursor.MoveAnchor)
if start != -1 and end != -1: #if selection exists then this should trigger
self.setTextCursor(cursor)
super().mouseMoveEvent(event)
这是实现当前选择的 shift+click 扩展的第一次尝试。好像还可以,但我还没死死测试过,所以可能会有一两个小故障。预期的行为是在选择上方或下方的 shift+click 应在该方向上扩展整个选择; shift+click 拖拽应该做同样的事情,只是连续。
请注意,我还设置了文本交互标志,以便插入符号在只读模式下可见,并且还可以使用键盘以各种方式操作选择(例如,ctrl+shift+right 扩展选择下一个单词)。
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class TextEditor(QTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setReadOnly(True)
self.setTextInteractionFlags(
Qt.TextSelectableByMouse |
Qt.TextSelectableByKeyboard)
def mouseMoveEvent(self, event):
if not self.setShiftSelection(event, True):
super().mouseMoveEvent(event)
def mousePressEvent(self, event):
if not self.setShiftSelection(event):
super().mousePressEvent(event)
def setShiftSelection(self, event, moving=False):
if (event.buttons() == Qt.LeftButton and
QApplication.keyboardModifiers() == Qt.ShiftModifier):
cursor = self.textCursor()
start = cursor.selectionStart()
end = cursor.selectionEnd()
if not moving or start != end:
anchor = cursor.anchor()
pos = self.cursorForPosition(event.pos()).position()
if pos <= start:
start = pos
elif pos >= end:
end = pos
elif anchor == start:
end = pos
else:
start = pos
if pos <= anchor:
start, end = end, start
cursor.setPosition(start, QTextCursor.MoveAnchor)
cursor.setPosition(end, QTextCursor.KeepAnchor)
self.setTextCursor(cursor)
return True
return False
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TextEditor()
window.setText(open(__file__).read())
window.setGeometry(600, 50, 800, 800)
window.show()
sys.exit(app.exec_())
目前,QTextEdit 允许选择文本,然后仅在锚点对面的选择一侧通过 shift-click-drag 更改该选择。锚点位于选择开始的位置。如果用户试图在开始附近更改选择,则选择将围绕锚点旋转而不是扩展。我想允许从任一侧更改选择。
我的第一次尝试是简单地将锚点设置在光标所在位置的另一侧。例如,选择从 10 到 20。如果光标在位置 8 处按住 shift 单击并拖动,则锚点将设置为 20。如果光标在位置 22 处按住 shift 单击并拖动,则anchor 将设置为 10。稍后,我会尝试更强大的东西,也许基于选择的中心点。
我认为这段代码可以工作,但它似乎根本不影响默认行为。我错过了什么?
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class TextEditor(QTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setReadOnly(True)
self.setMouseTracking(True)
def mouseMoveEvent(self, event):
point = QPoint()
x = event.x() #these are relative to the upper left corner of the text edit window
y = event.y()
point.setX(x)
point.setY(y)
self.mousepos = self.cursorForPosition(point).position() # get character position of current mouse using local window coordinates
if event.buttons()==Qt.LeftButton:
modifiers = QApplication.keyboardModifiers()
if modifiers == Qt.ShiftModifier:
start = -1 #initialize to something impossible
end = -1
cursor = self.textCursor()
select_point1 = cursor.selectionStart()
select_point2 = cursor.selectionEnd()
if select_point1 < select_point2: # determine order of selection points
start = select_point1
end = select_point2
elif select_point2 < select_point1:
start = select_point2
end = select_point1
if self.mousepos > end: # if past end when shift-click then trying to extend right
cursor.setPosition(start, mode=QTextCursor.MoveAnchor)
elif self.mousepos < start: # if before start when shift-click then trying to extend left
cursor.setPosition(end, mode=QTextCursor.MoveAnchor)
if start != -1 and end != -1: #if selection exists then this should trigger
self.setTextCursor(cursor)
super().mouseMoveEvent(event)
这是实现当前选择的 shift+click 扩展的第一次尝试。好像还可以,但我还没死死测试过,所以可能会有一两个小故障。预期的行为是在选择上方或下方的 shift+click 应在该方向上扩展整个选择; shift+click 拖拽应该做同样的事情,只是连续。
请注意,我还设置了文本交互标志,以便插入符号在只读模式下可见,并且还可以使用键盘以各种方式操作选择(例如,ctrl+shift+right 扩展选择下一个单词)。
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class TextEditor(QTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setReadOnly(True)
self.setTextInteractionFlags(
Qt.TextSelectableByMouse |
Qt.TextSelectableByKeyboard)
def mouseMoveEvent(self, event):
if not self.setShiftSelection(event, True):
super().mouseMoveEvent(event)
def mousePressEvent(self, event):
if not self.setShiftSelection(event):
super().mousePressEvent(event)
def setShiftSelection(self, event, moving=False):
if (event.buttons() == Qt.LeftButton and
QApplication.keyboardModifiers() == Qt.ShiftModifier):
cursor = self.textCursor()
start = cursor.selectionStart()
end = cursor.selectionEnd()
if not moving or start != end:
anchor = cursor.anchor()
pos = self.cursorForPosition(event.pos()).position()
if pos <= start:
start = pos
elif pos >= end:
end = pos
elif anchor == start:
end = pos
else:
start = pos
if pos <= anchor:
start, end = end, start
cursor.setPosition(start, QTextCursor.MoveAnchor)
cursor.setPosition(end, QTextCursor.KeepAnchor)
self.setTextCursor(cursor)
return True
return False
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TextEditor()
window.setText(open(__file__).read())
window.setGeometry(600, 50, 800, 800)
window.show()
sys.exit(app.exec_())