PyQt 4.4: In QTextEdit auf Return-Event reagieren

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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?
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.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
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.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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

Naja, du solltest vielleicht die Methode der Vater-Klasse ebenfalls aufrufen. Das ist jetzt aber Grundwissen über Klassenvererbung in Python ...
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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. :)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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. :(
hive
User
Beiträge: 7
Registriert: Sonntag 15. März 2009, 20:14

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
lunar

Das hatte er auch schon selbst herausgefunden ;)
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

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) 
Antworten