2016-12-16 3 views
0

Я написал исполняемый пример - вы можете его протестировать. Когда вы запустите эту программу, вы получите три QPushButton() -объекты и один QLineEdit() -объект. Там вы можете установить или удалить/удалить фильтр событий или закрыть приложение. Установите фильтр событий и введите текст. Вы увидите то, что я хочу. Я хочу, чтобы программа примера защищала пробел. В этой текущей версии пользователь не может нажать клавишу пробела более 2 раз. Эта программа работает.PyQt 4. Я не могу удалить содержимое QLineEdit() - object

Но У меня есть небольшая проблема. Когда я пишу текст в QLineEdit() -объект, а затем выделяю текст и нажимаю клавишу «Удалить» или «Возвращать», ничего не происходит. Я не могу удалить текст. Я также не могу скопировать выделенный текст.

Неправильный код внизу?

#!/usr/bin/env python 
import sys 

from PyQt4.QtCore import QEvent, Qt 
from PyQt4.QtGui import QMainWindow, QWidget, QApplication, QVBoxLayout, QLineEdit, QPushButton 

class Window(QMainWindow): 

    def __init__(self, parent=None): 

     QMainWindow.__init__(self, parent) 

     self.count_space_pressed = 0 
     self.current_pos = None 

     self.init_ui() 
     self.init_signal_slot_push_button() 

    def init_ui(self): 
     centralwidget = QWidget(self) 
     self.input_line_edit = QLineEdit(self) 


     self.close_push = QPushButton(self) 
     self.close_push.setEnabled(False) 
     self.close_push.setText("Close") 

     self.push_install = QPushButton(self) 
     self.push_install.setText("Install eventFilter") 

     self.push_deinstall = QPushButton(self) 
     self.push_deinstall.setText("Deinstall eventFilter") 

     layout = QVBoxLayout(centralwidget)   
     layout.addWidget(self.input_line_edit) 
     layout.addWidget(self.push_install) 
     layout.addWidget(self.push_deinstall) 
     layout.addWidget(self.close_push) 

     self.setCentralWidget(centralwidget) 
     return 

    def install_filter_event(self, widget_object): 
     widget_object.installEventFilter(self) 
     return 

    def deinstall_filter_event(self, widget_object): 
     widget_object.removeEventFilter(self) 
     return 

    def init_signal_slot_push_button(self): 

     self.close_push.clicked.connect(self.close) 
     self.push_install.clicked.connect(lambda: self.install_filter_event(self.input_line_edit)) 
     self.push_deinstall.clicked.connect(lambda: self.deinstall_filter_event(self.input_line_edit)) 
     return 

    def strip_string(self, content, site=None): 
     if site == "right": 
      return content.rstrip() 
     elif site == "right_left": 
      return content.strip() 
     elif site == "left": 
      return content.lstrip() 

    def eventFilter(self, received_object, event): 

     content_line_edit = unicode(received_object.text()) 

     if event.type() == QEvent.KeyPress: 

      if event.key() == Qt.Key_Space: 
       ''' 
        Yes, the user did press the Space-Key. We 
        count how often he pressed the space key. 
       ''' 
       self.count_space_pressed = self.count_space_pressed + 1 

       if int(self.count_space_pressed) > 1: 
        ''' 
         The user did press the space key more than 1 time. 
        ''' 

        self.close_push.setEnabled(False) 

        ''' 
         Now we know the user did press the 
         space key more than 1 time. We take a look, 
         if variablenamed (sel.current_pos) is None. 
         That means, no current position is saved. 
        ''' 
        if self.current_pos is None: 
         ''' 
          Well no current position is saved, 
          that why we save the new position anf 
          then we set the position of the cursor. 
         ''' 

         self.current_pos = received_object.cursorPosition() 

         received_object.setCursorPosition(int(self.current_pos)) 

         received_object.clear() 
         received_object.setText(self.strip_string(content_line_edit, site="right")) 

        else: 
         ''' 
          Well the user press the space key again, for 
          example 3, 4, 5, 6 times we want to keep the 
          old position of the cursor until he press 
          no space key. 
         '''       
         received_object.setCursorPosition(int(self.current_pos)) 

         ''' 
          We have to remove all spaces in a string 
          on the right side and set the content on QLineEdit-widget. 
         ''' 
         received_object.clear() 
         received_object.setText(self.strip_string(content_line_edit, site="right")) 

       else: pass     

      else: 
       ''' 
        No the user didn't press the space key. 
        So we set all setting on default. 
       ''' 
       self.close_push.setEnabled(True) 
       self.current_pos = None 
       self.count_space_pressed = 0 

       received_object.clear() 
       received_object.setText(self.strip_string(content_line_edit, site="left")) 

     # Call Base Class Method to Continue Normal Event Processing 
     return QMainWindow.eventFilter(self, received_object, event) 

if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    window = Window() 
    window.show() 
    app.exec_() 

EDIT:

import sys, re 
from PyQt4 import QtCore, QtGui 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     self.edit = QtGui.QLineEdit(self) 

     self.edit.textChanged.connect(self.handleTextChanged) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.edit) 

     # First we save the the regular expression pattern 
     # in a variable named regex. 
     #@ This means: one whitespace character, followed by 
     #@ one or more whitespaces chatacters 

     regex = r"\s\s+" 

     # Now we comple the pattern. 
     # After then we save the compiled patter 
     # as result in a variable named compiled_re. 
     self.compiled_re = re.compile(regex) 

    def handleTextChanged(self, text): 
     # When the text of a widget-object is changed, 
     # we do something. 

     # Here I am really not sure. 
     # Do you want to look if the given text isn't empty? 
     #@ No, we want to search the string to see if it 
     #@ contains any runs of multiple spaces 

     if self.compiled_re.search(text): 

      # We know that given text is a QString-object. 
      # So we have to convert the given text 
      # into a python-string, because we want to work 
      # with them in python. 
      text = unicode(text) 

      # NOTICE: Do replacements before and after cursor pos 

      # We save the current and correct cursor position 
      # of a QLineEdit()-object in the variable named pos. 
      pos = self.edit.cursorPosition() 

      # Search and Replace: Here the sub()-method 
      # replaces all occurrences of the RE pattern 
      # in string with text. 
      # And then it returns modified string and saves 
      # it in the variables prefix and suffix. 

      # BUT I am not sure If I understand this: [:pos] 
      # and [pos:]. I will try to understnand. 
      # I think we are talking about slicing, right? 
      # And I think the slicing works like string[start:end]: 

      # So text[:pos] means, search and replace all whitesapce 
      # at the end of the text-string. And the same again, but 
      # text[pos:] means, search and replace all whitesapce 
      # at the start of the string-text. 
      #@ Right, but the wrong way round. text[:pos] means from 
      #@ the start of the string up to pos (the prefix); and 
      #@ text[pos:] means from pos up to the end of the string 
      #@ (the suffix) 

      prefix = self.compiled_re.sub(' ', text[:pos]) 
      suffix = self.compiled_re.sub(' ', text[pos:])  

      # NOTICE: Cursor might be between spaces 
      # Now we take a look if the variable prefix ends 
      # with a whitespace and we check if suffix starts 
      # with a whitespace. 

      # BUT, why we do that? 
      #@ Imagine that the string is "A |B C" (with the cursor 
      #@ shown as "|"). If "B" is deleted, we will get "A | C" 
      #@ with the cursor left between multiple spaces. But 
      #@ when the string is split into prefix and suffix, 
      #@ each part will contain only *one* space, so the 
      #@ regexp won't replace them. 

      if prefix.endswith(' ') and suffix.startswith(' '): 

       # Yes its True, so we overwrite the variable named 
       # suffix and slice it. suffix[1:] means, we starts 
       # at 1 until open end. 
       #@ This removes the extra space at the start of the 
       #@ suffix that was missed by the regexp (see above) 

       suffix = suffix[1:] 

      # Now we have to set the text of the QLineEdit()-object, 
      # so we put the both varialbes named prefix and suffix 
      # together. 
      self.edit.setText(prefix + suffix) 

      # After then, we have to set the cursor position. 
      # I know that the len()-method returns the length of the 
      # variable named prefix. 

      # BUT why we have to do that? 
      #@ When the text is set, it will clear the cursor. The 
      #@ prefix and suffix gives the text before and after the 
      #@ old cursor position. Removing spaces may have shifted 
      #@ the old position, so the new postion is calculated 
      #@ from the length of the current prefix 

      self.edit.setCursorPosition(len(prefix)) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(500, 150, 300, 100) 
    window.show() 
    sys.exit(app.exec_()) 

EDIT 2:

Два вопроса:

Первый вопрос: в if.condition, где мы посмотрим если префикс заканчивается, а суффикс начинается с sapces, то мы являемся чтобы удалить дополнительное пространство в начале суффикса. Но почему бы нам не удалить лишнее пространство при запуске префикса? Представьте себе: пользователь вводит «Префикс и суффикс» - с дополнительными пробелами в начале и конце. Не нужно ли нам удалять лишнее пространство при запуске префикса - например: prefix= prefix[:1]?

Второй вопрос: В конце handleTextChanged() -метода, мы должны вычислить новое положение курсора. В текущем случае мы используем префикс для получения длины строки. Почему не len из нового измененного текста, который является частью префикса и суффикса? Пример: старая строка - «Префикс и суффикс», пользователь удаляет слово «и». Теперь наша строка выглядит как «Префикс | Суффикс»После того, как все пробельные символы будут удалены, мы получим новый измененный текст:„. Префикс Суффикс“Почему мы не вычисляем новое положение из измененного текста Или я что-то пропустил

EDIT 3:?

Я извиняюсь, я до сих пор не понимаю ситуацию

Первая ситуация: Когда пользователь печатает следующую строку:.. «A B C |» (| показано, как курсор) Теперь пользователь нажимает пробел более 2 раз, мы получаем префикс, который содержит «A B C |» - и никакого суффикса. И в настоящее время l ength of prexis - 6 - суффикс не имеет длины, потому что его пустой. И все слово - длина 6. Текущее положение курсора - 7.

Вторая ситуация: Пользовательский тип «A B D E F |». И теперь он понимает, что письмо отсутствует: C.Он перемещает курсор назад между B и D и типы C, а затем он собирается нажать клавишу пробела 2 раза. Теперь у нас есть префикс, который содержит «A B C» и суффикс, содержимое которого «D E F». Длина префикса равна 6, а суффикса - 5. Длина всего слова равна 11. И в этот момент текущая позиция курсора равна 7. В этой ситуации вы берете длину префикса и устанавливаете позицию курсора, вправо ?

ответ

2

Фильтровать нажатия клавиш недостаточно, если вы действительно хотите предотвратить несколько пробелов.

Например, пользователь может просто перетаскивать несколько пробелов; или вставлять их либо с помощью мыши, встроенного контекстного меню, либо со стандартными сочетаниями клавиш.

Это также очень легко разбить ваш метод подсчета пробелов: например, просто введите A B C, затем переместите два места и удалите B!

Более надежный способ сделать это - подключиться к сигналу textChanged и использовать регулярное выражение, чтобы проверить, есть ли несколько пробелов. Если есть, используйте одно и то же регулярное выражение для их замены, а затем верните курсор в исходное положение.

Вот демо:

import sys, re 
from PyQt4 import QtCore, QtGui 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     self.edit = QtGui.QLineEdit(self) 
     self.edit.textChanged.connect(self.handleTextChanged) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.edit) 
     self.regexp = re.compile(r'\s\s+') 

    def handleTextChanged(self, text): 
     if self.regexp.search(text): 
      text = unicode(text) 
      # do replacements before and after cursor pos 
      pos = self.edit.cursorPosition() 
      prefix = self.regexp.sub(' ', text[:pos]) 
      suffix = self.regexp.sub(' ', text[pos:]) 
      # cursor might be between spaces 
      if prefix.endswith(' ') and suffix.startswith(' '): 
       suffix = suffix[1:] 
      self.edit.setText(prefix + suffix) 
      self.edit.setCursorPosition(len(prefix)) 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    window = Window() 
    window.setGeometry(500, 150, 300, 100) 
    window.show() 
    sys.exit(app.exec_()) 
+0

Ваш демо является очень полезным и полезным. Я должен администратор. Я начинаю Python. Именно по этой причине я анализирую ваш код. Я хочу все понять. Я редактировал свой первый вопрос. Я написал свои мысли и вопросы в код как комментарии. Я попытался убрать тебя. В этих комментариях вы увидите мою проблему с пониманием, и вы также увидите, правильно ли я вас понял. – Sophus

+0

@Sophus. Я добавил несколько комментариев к вашему новому коду (все они начинаются с '# @'). – ekhumoro

+0

Спасибо. Есть еще одна проблема понимания. Я написал в своем приветственном вопросе под заголовком «EDIT 2:» – Sophus

Смежные вопросы