2017-10-23 35 views
1

현재 QTextEdit에서는 텍스트를 선택한 다음 해당 선택 항목을 앵커 반대쪽의 선택 부분에서만 shift-click-drag로 변경합니다. 앵커는 선택 영역이 시작된 곳에 배치됩니다. 사용자가 시작 부분 근처에서 선택 영역을 변경하려고하면 선택 영역이 확장 대신 고정 점 주위를 선회합니다. 선택을 양쪽에서 변경하는 것을 허용하고 싶습니다.QTextEdit에서 양방향으로 선택 확장

첫 번째 시도는 커서가있는 반대쪽에 앵커를 설정하는 것입니다. 커서가 위치 8에서 Shift 키를 누른 상태에서 드래그하면 앵커는 20으로 설정됩니다. 커서가 위치 22에서 Shift 키를 누른 상태에서 클릭 드래그하면 앵커는 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 + 클릭 확장을 구현하는 첫 번째 방법이 있습니다. 괜찮아 보이지만 죽을 때까지 테스트하지 않았으므로 하나 또는 두 가지 결함이있을 수 있습니다. 의도 된 동작은 선택 영역 위 또는 아래의 Shift + 클릭으로 해당 방향의 전체 선택 영역을 확장해야한다는 것입니다. 그리고 드래그로 Shift + 클릭은 똑같은 일을 계속해야합니다.

또한 텍스트 상호 작용 플래그를 설정하여 캐럿이 읽기 전용 모드로 표시되고 키보드를 사용하여 다양한 방법으로 선택 사항을 조작 할 수도 있습니다 (예 : Ctrl + Shift + 오른쪽으로 선택 항목 확장). 다음 단어로).

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_()) 
+0

다시 한번 귀하의 코드는 완벽하게 작동합니다. 'if pos <= anchor : start, end = end, start'는'start'가 항상'end'보다 작아 지도록 (Python에서만 보았던 구문을 사용하여) 변수를 전환합니다. 그러나 실제로는 수정하려는 선택 항목의 반대쪽으로 직접 앵커를 이동하거나 설정해야한다고 생각했습니다. – davideps

+0

@davideps. 'pos'가 현재의 엥커의 위 (보다 작은 경우) 인 경우, caret는 선택의 최상부에서 끝나야합니다. 마우스로 선택 영역을 위로 드래그 할 때 일어날 일입니다. 그래서 그 경우에, 선택은'end'에서'start'까지 이루어져야하며, 그 값들은 교환되어야합니다. 필자는 커서를'cursor.setPosition' 호출에서 좀 더 명확하게하기 위해 예제를 약간 수정했습니다. – ekhumoro