TextChanged-Funktion funktioniert nicht

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
THE_PYTHON_GUY
User
Beiträge: 18
Registriert: Samstag 6. November 2021, 09:58

Hallo,
in diesem Programm soll immer wenn der Text geändert wird, die Variable Text ausgegeben werden.
Weiß jemand wieso das nicht fuktioniert? Es gibt keine Fehlermeldung.

Code: Alles auswählen

import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from random import *
from PyQt5.QtCore import *

class Fenster(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initMe()

    def initMe(self):

        def fontdef(name, y):
            name.setGeometry(200, 25, 200, 25)
            if y == "large":
                size = 20
            elif y == "medium":
                size = 12
            elif y == "small":
                size = 7
            else:
                print("ERROR: DIE EINGABE IN FONTDEF WURDE NICHT ERKANNT.")
                size = 50
            name.setFont(QFont("Arial", size))

        self.setGeometry(450, 150, 850, 550) #1+2. = Position
        self.setWindowTitle("Notizen")

        self.Ueberschrift_eins = QLabel("Notes", self)
        fontdef(self.Ueberschrift_eins, "large")
        self.Ueberschrift_eins.move(20, 20)

        Textname = "Erste Notiz"
        Texte = QPushButton(self)
        Texte.clicked.connect(self.Text_oeffnen)
        Texte.setText(Textname)
        Texte.setGeometry(200, 50, 200, 50)
        Texte.move(10, 200)
        Texte.setToolTip("Notiz sehen")

        self.show()

    def Text_oeffnen(self):
        print("Der Button zum öffnen eines Textes wurde gedrückt.")

        def fontdef(name, y):
            name.setGeometry(200, 25, 200, 25)
            if y == "large":
                size = 20
            elif y == "medium":
                size = 12
            elif y == "small":
                size = 7
            else:
                print("ERROR: DIE EINGABE IN FONTDEF WURDE NICHT ERKANNT.")
                size = 50
            name.setFont(QFont("Arial", size))

        datei = open("Test.txt", "r")
        Inhalt = datei.read()

        self.Textfeld = QTextEdit(self)
        self.Textfeld.adjustSize()
        self.Textfeld.setText(Inhalt)
        self.Textfeld.setGeometry(300, 0, 550, 551)
        self.Textfeld.setFont(QFont("Arial", 12))
        self.Textfeld.textChanged.connect(self.Textfeld_def)
        self.Textfeld.show()


    def Textfeld_def(self, text):
        print(text)

app = QApplication(sys.argv)
w = Fenster()
w.show()
sys.exit(app.exec_())
Vielen Dank für die Hilfe
THE_PYTHON_GUY
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Warum rufst du aus der Init eine weitere Methode auf, die die eigentliche Initialisierung durchführt? Das muss in der __init__ passieren.
Warum legst du self.Textfeld nicht in der __init__ an, wo das Objekt initialisiert wird, sondern magisch in einer anderen Methode?
Warum verwendest du verschachtelte Funktionen in Methoden? Und dann sind die inneren Funktionen auch noch identisch?
Warum benennst du die Methoden nicht nach dem Python-Konvetionen? Alle Namen klein_mit_unterstrich außer die Namen von Klassen (PascalCase) und die Namen von Konstanten (KOMPLETT_GROSS).
Warum verwendest du *-Importe. Das vermeidet man ausdrücklich, weil man sich unkontrolliert Namen ins Programm holt, die auch kollidieren können. Und kein Mensch weiß, woher ein Namen denn nun kommt.
Welchen Sinn genau hat ein _def am Methodennamen?
Warum zeigt sich das Fenster aus __init__ heraus selbst an? Du machst es doch am Ende des Codes richtig. Und so wird show() halt doppelt aufgerufen - was sinnlos ist.

Soviel zum Code, was ich auf Anhieb gesehen habe.
Zu deinem Problem:

Signale werden, wie die Objekte auch, in der __init__ angelegt und nicht irgendwo in irgend einer Methode.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ergänzend: Die ganzen `setGeometry()`- und `move()`-Aufrufe mit absoluten Koordinaten und Grössen sollten nicht sein. Dafür gibt es Layouts.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
THE_PYTHON_GUY
User
Beiträge: 18
Registriert: Samstag 6. November 2021, 09:58

@sparrow
Dieser Code ist nur für private Zwecke gedacht. Daher ist die Namenvergabe aus emine Sicht komplett egal.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da der Code hier praesentiert wird, und damit von jemand anderem als nur dir gelesen wird, ist das eine Fehleinschaetzung. Denn es verwirrt diejenigen, die dir helfen sollen, deine Probleme zu loesen. Und solltest du Interesse daran haben, irgendwann mal irgendwo Code zu schreiben, der fuer diese Oeffentlichkeit gedacht ist, woher genau hast du dann gelernt, wie man es richtig macht? Vom nicht-ueben an privaten Projekten eher nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@THE_PYTHON_GUY: Es wird auf der Konsole doch eine aussagekräftige Fehlermeldung ausgegeben:

Code: Alles auswählen

TypeError: Textfeld_def() missing 1 required positional argument: 'text'
Schau noch mal in die Dokumentation von dem Signal was das (nicht) an Daten überträgt.

Bei den Importen ist eine Zeile doppelt, und `QtCore` wird importiert, aber nirgends verwendet. Dafür wird alles *aus* `QtCore` per * importiert, es gäbe also zwei Wege um die Werte zu erreichen und es wäre nicht wirklich klar warum wann welcher gewählt würde, falls `QtCore` tatsächlich verwendet werden würde.

Es wird anscheinend auch nichts aus `random` verwendet, obwohl auch hier alles per * importiert wird. Das gleiche gilt für alles aus `QtCore`.

Die in `Text_oeffnen()` definierte `fontdef()`-Funktion wird nirgends verwendet.

`fontef()` und die Argumente sind schlecht benannt. Statt einer Zeichenkette und dem ``if``/``elif``-Konstrukt würde man auch eher Konstanten definieren. Da die zusammengehören, bietet sich `enum.Enum` als Basistyp dafür an.

`texte` ist kein wirklich naheliegender Name für eine Schaltfläche.

Wie schon im letzten Beitrag gesagt verwendet man `setGeometry()` und `move()` nicht. Wenn man es verwenden würde, wäre es unsinnig die beiden direkt hintereinander zu verwenden, denn die Position kann man im `setGeometry()` bereits angeben. Warum also dort erst etwas falsches/unsinniges angeben, was dann durch das `move()` überschrieben wird?

Dateien die man öffnet, sollte man auch sauber wieder schliessen. Bei `open()` bietet sich die ``with``-Anweisung an. Aber man kann sich das mit dem `pathlib`-Modul auch ein bisschen einfacher machen.

Der Unterstrich bei `exec_()` ist veraltet und in PyQt6 nicht mehr möglich. Das ist ein Relikt aus Python 2 Zeiten, wo ``exec`` noch ein Schlüsselwort der Sprache war.

Code: Alles auswählen

#!/usr/bin/env python3
import sys
from enum import Enum
from pathlib import Path

from PyQt5.QtCore import QRect, QSize
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import (
    QApplication,
    QLabel,
    QMainWindow,
    QPushButton,
    QTextEdit,
)


class SizeType(Enum):
    LARGE = 20
    MEDIUM = 12
    SMALL = 7


def set_font(widget, size):
    widget.setFont(QFont("Arial", size.value))


class Fenster(QMainWindow):
    def __init__(self):
        super().__init__(windowTitle="Notizen", minimumSize=QSize(850, 550))

        ueberschrift = QLabel("Notes", self)
        set_font(ueberschrift, SizeType.LARGE)
        ueberschrift.move(20, 20)

        QPushButton(
            "Erste Notiz", self, toolTip="Notiz sehen", clicked=self.load_text
        ).move(10, 200)

        self.textfeld = QTextEdit(
            self,
            font=QFont("Arial", 12),
            geometry=QRect(300, 0, 550, 551),
            textChanged=self.on_text_changed,
        )

    def load_text(self):
        print("Der Button zum öffnen eines Textes wurde gedrückt.")
        self.textfeld.setText(Path("test.txt").read_text(encoding="utf-8-sig"))

    def on_text_changed(self):
        print(self.textfeld.toPlainText())


def main():
    app = QApplication(sys.argv)
    fenster = Fenster()
    fenster.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
Die absoluten Grössen sowohl bei `SizeType` für die Schrift, als auch die `QSize`- und `QRect`-Objekte sollten nicht sein, weil das nicht wirklich funktioniert. Verwende relative Angaben und Layouts.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten