在 QTextEdit 中向任一方向扩展选择
Posted
技术标签:
【中文标题】在 QTextEdit 中向任一方向扩展选择【英文标题】:Extending selection in either direction in a QTextEdit 【发布时间】:2017-10-23 08:38:23 【问题描述】:目前,QTextEdit 允许选择文本,然后仅在与锚点相对的选择侧使用 shift-click-drag 来更改该选择。锚点放置在选择开始的位置。如果用户试图在开始附近更改选择,则选择围绕锚点旋转而不是延伸。我想允许从任一侧更改选择。
我的第一次尝试是简单地将锚点设置在光标所在位置的另一侧。例如,选择是从 10 到 20。如果光标在位置 8 处被 shift-click-drag 拖动,则锚点将设置为 20。如果在位置 22 上 shift-click-drag 光标,则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)
【问题讨论】:
【参考方案1】:这是实现当前选择的 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_())
【讨论】:
再一次,您的代码完美运行——我不完全理解如何。if pos <= anchor: start, end = end, start
切换变量,所以start
总是小于end
(使用我只在 Python 中见过的语法)。但是,我真的希望您必须将锚点直接移动或设置到正在修改的选择的另一侧。
@davideps。如果pos
高于(小于)当前锚点,插入符号应该在选择的顶部结束。这正是用鼠标向上 拖动选择时会发生的情况。因此,对于这种情况,必须从end
到start
进行选择,并且必须交换值。我已经稍微修改了我的示例,以便在 cursor.setPosition
调用中更加明确。以上是关于在 QTextEdit 中向任一方向扩展选择的主要内容,如果未能解决你的问题,请参考以下文章