Seite 1 von 1
Abfangen einzelner Zeichen
Verfasst: Dienstag 13. Dezember 2016, 22:20
von Sophus
Hallo Leute,
nachfolgend habe ich für euch ein kleines Beispiel geschrieben. Was möchte ich tun? Nun, ich möchte grundlegend jedes Zeichen einzeln abfangen, die der Benutzer eingibt (in diesem Fall in die QLineEdit). Dieses Problem versuche ich derzeit mit dem eventFilter() zu lösen, indem ich diese Funktion reimplementierte. Allerdings hat mein Beispiel ein kleinen
Schönheitsfehler. Wenn ich nun in der QLineEdit Zeichen (Buchstaben, Zahlen etc.) eintippe, dann wird nur das aktuell getippte Zeichen ausgegeben, die anderen bereits getippten Zeichen verschwinden. Wie kann ich das Problem lösen?
An dieser Stelle eine kleine Anmerkung: Ich weiß, das
QLineEdit das
textChanged()-Signal bereit hält. Allerdings wüsste ich nicht, wie ich an jedes einzelnes Zeichen käme, ohne gleich den gesamten Inhalt der
QLineEdit() mittels der
text()-Methode zubekommen und diese dann durch die For-Schleife zu jagen.
Code: Alles auswählen
#!/usr/bin/env python
import sys
from PyQt4.QtCore import QEvent
from PyQt4.QtGui import QMainWindow, QWidget, QApplication, QVBoxLayout, QLineEdit
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
centralwidget = QWidget(self)
self.input_line_edit = QLineEdit()
layout = QVBoxLayout(centralwidget)
layout.addWidget(self.input_line_edit)
self.setCentralWidget(centralwidget)
# Install the event filter to QlineEdit object
self.input_line_edit.installEventFilter(self)
def eventFilter(self, received_object, event):
if(event.type() == QEvent.KeyPress):
self.input_line_edit.setText(unicode((event.text())))
print u"You Pressed: {}".format(event.text())
# I returned True right here, because I want the event
# would be filtered and reach the obj.
return True
else:
return super(QMainWindow, self).eventFilter(received_object, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()
Re: Abfangen einzelner Zeichen
Verfasst: Dienstag 13. Dezember 2016, 22:34
von Sirius3
@Sophus: Du setzt den Text auf »event.text()« und wunderst Dich, dass genau dieses Zeichen im Textfeld erscheint? Dein Code hat zu viele Leerzeilen und Klammern an ungewöhnlichen Stellen. Das macht ihn schwer lesbar.
Code: Alles auswählen
def eventFilter(self, received_object, event):
if event.type() == QEvent.KeyPress:
print u"You Pressed: {}".format(event.text())
return super(QMainWindow, self).eventFilter(received_object, event)
Re: Abfangen einzelner Zeichen
Verfasst: Dienstag 13. Dezember 2016, 22:57
von Sophus
@Sirius3: Besten dank. Manchmal bin ich echt ein Dussel. Du meintest, dass mein Quelltext zu viele Leerzeilen habe. Ich habe absichtlich alles weiter auseinander "gezogen", damit die Einzelschritte besser sichtbar werden. Zumindest hilft mir das immer. Und zu viele Klammern? Da waren doch nur die Klammern bei der If-Abfrage "zu viel"

Re: Abfangen einzelner Zeichen
Verfasst: Dienstag 13. Dezember 2016, 23:41
von Sophus
Was mich ein wenig beschäftigt und wobei ich mir nicht sicher bin, ist die Frage, warum die reimplementierte eventFilter()-Methode die super()-Methode, auf die die eventFilter()-Methode angewendet wurde, zurückgibt?
Re: Abfangen einzelner Zeichen
Verfasst: Dienstag 13. Dezember 2016, 23:49
von BlackJack
@Sophus: Das tut sie nicht.
Re: Abfangen einzelner Zeichen
Verfasst: Mittwoch 14. Dezember 2016, 00:03
von Sophus
@BlackJack: Ich bin noch mehr verwirrt. Stecht nicht direkt hinter der return-Anweisund die super()-Methode?
Re: Abfangen einzelner Zeichen
Verfasst: Mittwoch 14. Dezember 2016, 12:05
von BlackJack
@Sophus: Da steht der *Aufruf* der super()-Funktion und dann deren Rückgabewert. Da wird also nicht die Methode zurückgegeben sondern das Ergebnis des Aufrufs der Methode.
Re: Abfangen einzelner Zeichen
Verfasst: Mittwoch 14. Dezember 2016, 17:10
von Sophus
@"BlackJack: Stimmt, erst wird die super()-Funktion aufgerufen, und anschließend den, der dabei raus kam, zurückgegeben.
Aber ich habe noch zwei Frage:
Warum
muss ich in der
eventFilter()-Methode den eigenen "Konstrukteur" aufrufen und den Wert zurückgeben? Ich habe ja mal versucht zu verstehen, indem ich mir die Rückgabewerte mittels der Print-Anweisung anzeigen ließ. Es wird ja solange
False zurückgegeben, bis man eine Taste drückt. Aber wozu ist das nötig? Irgendwie fehlt mir zum Verständnis ein kleiner Schritt.
Dann die zweite Frage.
Ich habe eben versucht, anstatt der super()-Funktion die Methode der Eltern-Klasse direkt aufzurufen.
Also aus:
Code: Alles auswählen
return super(QMainWindow, self).eventFilter(received_object, event)
wird:
Code: Alles auswählen
return QMainWindow.__init__(self).eventFilter(received_object, event)
Aber dann bekomme ich folgende Fehlermeldung:
Traceback (most recent call last):
File "C:\Users\Sophus\Desktop\py_scripts\check_press.py", line 31, in eventFilter
return QMainWindow.__init__(self).eventFilter(received_object, event)
AttributeError: 'NoneType' object has no attribute 'eventFilter'
Re: Abfangen einzelner Zeichen
Verfasst: Mittwoch 14. Dezember 2016, 18:20
von BlackJack
@Sophus: Du musst die Methode auf der Basisklasse nicht aufrufen. Kannst das ja mal weg lassen, dann siehst Du ja was (nicht) passiert. Was aber auch irgendwie offensichtlich sein sollte was nicht passiert wenn man die nicht aufruft.
Du hast *nicht* versucht statt `super()` die Methode der Elternklasse direkt aufzurufen. *Das* hätte nämlich geklappt. Du hast stattdessen unsinnigerweise versucht die `__init__()` noch mal aufzurufen, was a) keinen Sinn macht und b) grundsätzlich `None` liefert, und darauf kann man dann natürlich nichts aufrufen was eigentlich zu `QWindow` bzw. `QObject` gehört. Das hätte so aussehen müssen:
Code: Alles auswählen
return QMainWindow.eventFilter(self, received_object, event)
Re: Abfangen einzelner Zeichen
Verfasst: Donnerstag 15. Dezember 2016, 21:33
von Sophus
Ich habe mal das Beispiel erweitert. Nachfolgend werde ich euch das Beispiel vorstellen.
Mein
Problem ist, dass - sobald ich den
eventFilter() installiert habe - die Cursortasten, Löschen- und Entfern-Tasten nicht wirklich greifen. In diesem Beispiel möchte ich, dass der Benutzer nicht so oft mit der Leertaste rumspielt. Ich möchte also seine Leertaste
überwachen.
Problem-Hergang. Sobald das Beispiel-Programm gestartet wird,kann man mittels der Schaltflächen den
eventFilter() installieren, und wahlweise auch deinstallieren. Wenn der
eventFilter() nun installiert ist, und ich markiere den getippten Text im
QLineEdit()-Objekt und drücke anschließend die Lösch- und/oder Entfern-Taste, dann passiert
gar nichts. Der Inhalt des
QLineEdit()-Objektes wird nicht gelöscht. Muss ich jetzt hingehen und sämtliche Tasten nun händisch verwalten?
Code: Alles auswählen
#!/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_()
Re: Abfangen einzelner Zeichen
Verfasst: Freitag 16. Dezember 2016, 00:33
von Sirius3
@Sophus: Du änderst den Inhalt Deines Editfeldes und wunderst Dich, dass Kopieren und Löschen dabei nicht funktioniert? Hör einfach auf, den Inhalt zu ändern, wenn Du das überhaupt nicht brauchst. Nebenbei solltest Du Dir ein paar Unsitten abgewöhnen: Leerzeilen, wo sie nicht zur Lesbarkeit beitragen, keine »return« oder »else: pass« die nichts tun. Mehrzeilige Strings sind kein Ersatz für Kommentare. Diese werden mit # gemacht.
Re: Abfangen einzelner Zeichen
Verfasst: Freitag 16. Dezember 2016, 01:02
von Sophus
@Sirius3: An welchen Stellen soll ich aufhören die Inhalte des QLineEdit()-Objektes zu verändern? Wie du siehst, muss ich an einige Stellen die Inhalte verändern, wenn ich die Leerzeichen per lstrip()/rstrip()/strip() löschen will. Du meinst sicherlich die Zeilen 104, 120 und 134 - korrekt?