PyQt 4.我无法删除QLineEdit()-object的内容

问题描述 投票:0回答:2

我写了一个可执行的示例 - 你可以测试它。当您启动此程序时,您将获得三个 QPushButton() 对象和一个 QLineEdit() 对象。您可以在那里安装或卸载/卸载事件过滤器或关闭应用程序。请安装事件过滤器并输入文本。你会看到我想要的。我希望示例程序能够保护空格键。在当前版本中,用户不能按空格键超过 2 次。这个程序确实有效。

但是我有一个小问题。当我在 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_()

编辑:

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

编辑2:

两个问题:

第一个问题:在if.条件中,我们检查前缀是否以sapces结尾并且后缀是否以sapces开头,我们将删除后缀开头的额外空格。但为什么我们不删除前缀开头的额外空格呢? 想象一下:用户输入“前缀和后缀” - 在开头和结尾处有额外的空格。我们是否必须删除前缀开头的额外空格 - 例如:

prefix= prefix[:1]

第二个问题:handleTextChanged() 方法的最后,我们必须计算光标的新位置。在当前情况下,我们使用前缀来获取字符串的长度。为什么不是新修改文本中的 len,它是前缀和后缀的一部分? 示例:旧字符串是“ Prefix and Suffix ”,用户删除了单词“and”。现在我们的字符串看起来像“ Prefix | Suffix ”。后缀“。删除所有空格后,我们得到新的修改后的文本:“前缀后缀”。为什么我们不根据修改后的文本计算新位置?或者我错过了什么?

编辑3:

抱歉,我还是不明白情况。

第一种情况:当用户输入以下字符串:“

A B C |
”(|显示为光标)。现在用户按空格键超过 2 次,我们得到一个包含“
A B C |
”的前缀 - 并且没有后缀。目前前缀的长度是 6 - 后缀没有长度,因为它是空的。整个单词长度为6。当前光标位置为7。

第二种情况:用户输入“

A B D E F |
”。现在他意识到少了一封信:
C
。他将光标移回
B
D
之间并输入
C
,然后他准备按两次空格键。现在我们有包含“
A B C
”的前缀和内容“
D E F
”的后缀。前缀的长度是6,后缀的长度是5。整个单词的长度是11。此时光标的当前位置是7。在这种情况下,你取前缀的长度并设置光标位置,右?

python-2.7 validation pyqt4 qt4 qlineedit
2个回答
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 并且已创建用于删除最后一个字符的按钮,请执行以下操作

self.PB_Back.clicked.connect(self.Keypad_Back)
  def Keypad_Back(self):
        self.LE_Edit.setText(self.LE_Edit.text()[:-1]) 

这将一次删除最后一个字符

要一次删除所有字符,请执行以下操作

self.PB_DeleteResult.clicked.connect(self.Keypad_DeleteResult)
def Keypad_DeleteResult(self):
        self.LE_Edit.setText("")
© www.soinside.com 2019 - 2024. All rights reserved.