Seite 1 von 1

PyQt 4.4: In QTextEdit auf Return-Event reagieren

Verfasst: Sonntag 15. März 2009, 15:24
von snafu
Hallo!

Mein Ziel ist es, Nutzereingaben, die direkt in einem TextEdit gemacht werden, weiterzuverabeiten.

Ich habe mal ein Minimalbeispiel zum Vergleichen gemacht:

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui


class Window(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        centralwidget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(centralwidget)
        inpline = QtGui.QLineEdit()
        QtCore.QObject.connect(inpline, QtCore.SIGNAL('returnPressed()'),
                               lambda: outbox.setText(inpline.text()))
        layout.addWidget(inpline)
        outbox = QtGui.QTextEdit()
        QtCore.QObject.connect(outbox, QtCore.SIGNAL('returnPressed()'),
                               lambda: outbox.setText('Typed text in outbox'))
        layout.addWidget(outbox)
        self.setCentralWidget(centralwidget)
        

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    app.exec_()
Eigaben, die in der Zeile oben gemacht werden, übernimmt er korrekt ins Textfeld. Aber wenn ich im Textfeld etwas eingebe, passiert gar nichts.

Was mache ich falsch?

Verfasst: Sonntag 15. März 2009, 16:54
von lunar
Wie kommst du den darauf, QTextEdit hätte ein "returnPressed()"-Signal? In der Doku (die du in diesem Fall wohl nicht gelesen hast) steht das jedenfalls nicht.

Verfasst: Sonntag 15. März 2009, 17:23
von snafu
Ehrlich gesagt hab ich das einfach vorausgesetzt ohne nachzugucken. :oops:

Wie würde man denn jetzt vorgehen? Gibt es ein alternatives Widget zu `QTextEdit()`, das eine beschreibbare Textbox liefert und `returnPressed()` kennt oder muss ich das Event selbst implementieren (bin gerade auf `QKeyEvent()` gestoßen)? Habe sowas bisher nicht machen müssen.

Verfasst: Sonntag 15. März 2009, 17:28
von lunar
snafu hat geschrieben:Wie würde man denn jetzt vorgehen? Gibt es ein alternatives Widget zu `QTextEdit()`, das eine beschreibbare Textbox liefert und `returnPressed()` kennt oder muss ich das Event selbst implementieren (bin gerade auf `QKeyEvent()` gestoßen)? Habe sowas bisher nicht machen müssen.
Soweit ich weiß, exportieren weder QTextEdit noch QPlainTextEdit ein gleichwertiges Signal. Das wäre auch reichlich sinnlos, da die Eingabetaste in diesen Widgets auch nur eine normale Taste ist, die halt einen Zeilenumbruch anstatt einen Buchstaben einfügt. Ein QLineEdit kennt keine Zeilenumbruch, daher dient die Eingabetaste da als Indikator für eine beendete Eingabe.

Eine Möglichkeit wäre, auf das "textChanged()"-Signal zu lauschen, und den Text auf einen Zeilenumbruch zu überprüfen, aber das ist ziemlich hässlich. Das Überschreiben von ".keyPressEvent()" bzw ".keyReleaseEvent" ist imho die beste Lösung.

Verfasst: Sonntag 15. März 2009, 18:29
von snafu
Okay, ich schaffe es jetzt, eine Meldung im Terminal anzuzeigen, wenn <Return> in meiner abgeleiteten Klasse gedrückt wird (hoffe das ist so richtig gemacht). Nun reagiert er auf andere Tasten aber leider gar nicht mehr, sprich: Er schreibt nichts ins Textfeld rein. Wie bringe ich ihn dazu, nur auf eine Taste speziell zu reagieren und sich ansonsten so wie normalerweise üblich zu verhalten?

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui


class MyOutbox(QtGui.QTextEdit):

    def __init__(self):
        QtGui.QTextEdit.__init__(self)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Return:
            print 'Typed text in outbox'


class Window(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        centralwidget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(centralwidget)
        inputline = QtGui.QLineEdit()
        QtCore.QObject.connect(inputline, QtCore.SIGNAL('returnPressed()'),
                               lambda: outbox.setText(inputline.text()))
        layout.addWidget(inputline)
        outbox = MyOutbox()
        layout.addWidget(outbox)
        self.setCentralWidget(centralwidget)


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

Verfasst: Sonntag 15. März 2009, 18:32
von lunar
Naja, du solltest vielleicht die Methode der Vater-Klasse ebenfalls aufrufen. Das ist jetzt aber Grundwissen über Klassenvererbung in Python ...

Verfasst: Sonntag 15. März 2009, 18:38
von snafu
Ja, da hab ich wohl etwas schneller gefragt als nachgedacht.

Code: Alles auswählen

class MyOutbox(QtGui.QTextEdit):

    def __init__(self):
        QtGui.QTextEdit.__init__(self)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Return:
            return self.setText('Typed text in outbox')
        return QtGui.QTextEdit.keyPressEvent(self, event)
Danke dir. :)

Verfasst: Montag 16. März 2009, 00:55
von snafu
So, jetzt will ich nach <Return> den kompletten Text ausgeben lassen:

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui


class MyTextbox(QtGui.QTextEdit):

    def __init__(self):
        QtGui.QTextEdit.__init__(self)
        self.setText('Write what you want: ')

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Return:
            print self.text()
        return QtGui.QTextEdit.keyPressEvent(self, event)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    textbox = MyTextbox()
    textbox.show()
    app.exec_()
Warum wirft das einen Fehler?

Code: Alles auswählen

~$ ./test.py
Traceback (most recent call last):
  File "./test.py", line 14, in keyPressEvent
    print self.text()
AttributeError: text
`QTextEdit() ` hat doch eine `text()`-Methode. Oder muss ich bei der abgeleiteten Klasse noch etwas besonderes beachten?

Falls das alles etwas merkwürdig erscheint: Ich will das letztlich nutzen, um für mein Terminal-Projekt das eingegebene Kommando auslesen zu können. Aber so weit bin ich ja noch nicht.

EDIT: Hab schon. Man muss `toPlainText()` benutzen. Ich bin mal wieder beim Suchen in die falsche Doku gekommen. :(

Verfasst: Montag 16. März 2009, 11:54
von hive
snafu hat geschrieben:Warum wirft das einen Fehler?
Weil es "self.toPlainText()" heisst.

Code: Alles auswählen

 
def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Return:
            print self.toPlainText()
        return QtGui.QTextEdit.keyPressEvent(self, event)

hive

Verfasst: Montag 16. März 2009, 11:55
von lunar
Das hatte er auch schon selbst herausgefunden ;)

Verfasst: Montag 16. März 2009, 12:19
von burli
Nur mal so nebenbei: ein Blick in die Doku offenbart, welche Signals es gibt. Ich hab hier im Moment nur Qt4.3 installiert. Da gibt es bei QTextEdit

Code: Alles auswählen

void copyAvailable ( bool yes )
void currentCharFormatChanged ( const QTextCharFormat & f )
void cursorPositionChanged ()
void redoAvailable ( bool available )
void selectionChanged ()
void textChanged ()
void undoAvailable ( bool available )
QScintilla kann auch nicht viel mehr, sonst hätte ich gesagt, nimm das

Code: Alles auswählen

void cursorPositionChanged (int line, int pos)
void copyAvailable (bool yes)
void linesChanged ()
void marginClicked (int margin, int line, Qt::KeyboardModifiers state)
void modificationAttempted ()
void modificationChanged (bool m)
void selectionChanged ()
void textChanged ()
void userListActivated (int id, const QString &string)