Textlabel ändert sich nicht

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
DL3AD
User
Beiträge: 27
Registriert: Montag 31. August 2015, 19:03

Donnerstag 13. Februar 2020, 12:08

Hallo,

habe in einem kleinen Testprog versucht ein TextLabel zu beschreiben - tut sich aber nix
Das Prog starten aber ohne Fehler
Was mache ich falsch ?

Code: Alles auswählen

import sys
from PyQt5 import QtWidgets
import form1

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = form1.Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.Btn_Calc.clicked.connect(my_hallo) #Btn geklickt dann my_hallo aufrufen
        
        
def my_hallo():
    MainWindow().ui.Lbl_Erg.text = 'Hallo' # Label Lbl_Erg mit text 'Hallo' beschreiben
   

def main():
    app = QtWidgets.QApplication(sys.argv)
    my_form1 = MainWindow()
    my_form1.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
__deets__
User
Beiträge: 7712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 12:15

Klassen vs Objekte verhalten sich wie Blaupausen zu danach konstruierten Dingen. Wenn ich dir eine Blaupause eines 3er-BMWs gebe, und du baust einen neuen BMW und oeffnest dessen Tuer - dann gehen ja auch nicht die von dem 3er im Hof die Tuer auf. Genau das tust du aber, wenn du MainWindow() aufrufst - du machst eine NEUE Instanz von MainWindow. Du musst dich aber auf die bestehende beziehen.

Statt eine frei-stehenden Funktion musst du also eine Methode machen. Und einfach ein Attribut setzten funktioniert auch nicht, du musst in die Dokumentation von QLabel schauen, und die richtige Methode raussuchen. Wahrscheinlich setText.
Benutzeravatar
__blackjack__
User
Beiträge: 5546
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 13. Februar 2020, 12:37

@DL3AD: Ergänzend: Die Argumente bei `super()` sind überflüssig.

So wie Du den generieren Quelltext (was man nicht macht) mit `MainWindow` über `setupUi()` verbandelst gibt es nun für den ganzen Kram zwei Wege, einmal `self` und dann `self.ui`. Das macht keinen Sinn.

Namen sollten weder abgekürzt werden, noch nummeriert, noch sollte man sinnfreie Prä-/Suffixe wie `my` irgendwo dran pappen. Sich an Namenskonventionen halten wäre auch sinnvoll. Wenn schon nicht an die von Python dann doch wenigstens die von Qt.
long long ago; /* in a galaxy far far away */
DL3AD
User
Beiträge: 27
Registriert: Montag 31. August 2015, 19:03

Donnerstag 13. Februar 2020, 13:17

... ich komme noch nicht weiter
hier mal ein Beispiel in Pascal

Code: Alles auswählen

unit Unit1;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
  { TForm1 }
  TForm1 = class(TForm)
    Btn_Calc: TButton;//Button
    Lbl_Erg: TLabel;  //Label
    procedure Btn_CalcClick(Sender: TObject);//Ereignissbehandlung Klick

  private
  public
  end;

var
  Form1: TForm1;

implementation
{$R *.lfm}
{ TForm1 }
//Ereignissbehandlung Btn Klick
procedure TForm1.Btn_CalcClick(Sender: TObject);
begin
  Lbl_erg.Caption:= 'Hallo'; //Label beschreiben
end;


end.                   
was müsste im obigen Python Code geändert werden
Sirius3
User
Beiträge: 11625
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 13. Februar 2020, 13:34

Methoden in Pascal benutzen implizit die Instanz, auf der sie aufgerufen werden.
`my_hallo` ist aber gar keine Methode, sondern eine frei stehende Funktion. Mach daraus eine Methode und benutze self.ui...
DL3AD
User
Beiträge: 27
Registriert: Montag 31. August 2015, 19:03

Donnerstag 13. Februar 2020, 13:41

ich probiere schon den ganzen Tag herum,
kanns du mir bitte mal mit der Methode helfen damit ich das Prinzip erkennen kann ?
Benutzeravatar
__blackjack__
User
Beiträge: 5546
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 13. Februar 2020, 13:47

Um das Pascal-Programm mal als Ausgangsbeispiel zu nehmen: Ungefähr das hier hast Du in Python versucht: Der Rückruf geht an eine Prozedur/Funktion statt an eine Methode und es wird in der Prozedur nicht auf das existierende Objekt zugegriffen sondern noch mal lokal ein neues erstellt.

Code: Alles auswählen

unit Unit1;
{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
  { TForm1 }
  TForm1 = class(TForm)
    Btn_Calc: TButton;
    Lbl_Erg: TLabel;

  private
  public
  end;

var
  Form1: TForm1;

procedure Btn_CalcClick(Sender: TObject);

implementation
{$R *.lfm}
{ TForm1 }

procedure Btn_CalcClick(Sender: TObject);
var form: TForm1;
begin
  form.Lbl_erg.Caption := 'Hallo';
end;

end.
long long ago; /* in a galaxy far far away */
DL3AD
User
Beiträge: 27
Registriert: Montag 31. August 2015, 19:03

Donnerstag 13. Februar 2020, 13:52

... hmm und wie wir das in Python gemacht ?
__deets__
User
Beiträge: 7712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 13:56

Habe ich dir doch gesagt. Du musst aus deinem Callback eine METHODE machen. Was das ist wird zB hier beschrieben: https://docs.python.org/3/tutorial/clas ... at-classes
DL3AD
User
Beiträge: 27
Registriert: Montag 31. August 2015, 19:03

Donnerstag 13. Februar 2020, 14:06

ist es denn so schwierig für euch Experten mir als Anfänger mal zwei codezeilen als Beispiel zu geben ?
__deets__
User
Beiträge: 7712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 14:06

Hier mal ein einfaches Beispiel, um das zu illustrieren:

Code: Alles auswählen


class A:

    def __init__(self, zahl):
         self._zahl = zahl
    def methode(self):
         print(self._zahl)


instanz_a = A(100)
instanz_b = A(200)
instanz_a.methode()
instanz_b.methode()
A.methode() # das kracht!
__deets__
User
Beiträge: 7712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 14:11

Und noch ein bisschen weitergehend, mit dem Konzept "gebundene Methode als Rueckruffunktion":

Code: Alles auswählen

callback = instanz_a.methode # OHNE KLAMMERN
callback() # kann spaeter aufgerufen werden, ohne dass man die Instanz verfuegbar haben muss.
Benutzeravatar
__blackjack__
User
Beiträge: 5546
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 13. Februar 2020, 14:22

@DL3AD: In dem Tutorial das __deets__ verlinkt hat sind viele Beispiele. Zum ausprobieren und herumspielen um Verständnis und Gefühl dafür zu bekommen. Aber Du willst immer ”Beispiele” die exakt auf Dein Problem passen um die nachmachen zu können, ohne das Du da drüber nachdenken und sie tatsächlich verstehen musst. Wenn man so ”lernt” kann man nichts selber was man nicht schon mal irgendwo gesehen hat und nur leicht anpassen muss. Es würde wirklich Sinn machen erst einmal Python zu lernen und dann Qt. Bevor man sich mit dem Designer Sachen erstellen lässt die man nicht versteht.

@__deets__: Dir ist schon klar das Du da gerade das Tutorial ”abschreibst”, denn genau so ein Beispiel ist da auch drin:
9.3.4. Method Objects

Usually, a method is called right after it is bound:

Code: Alles auswählen

x.f()
In the MyClass example, this will return the string 'hello world'. However, it is not necessary to call a method right away: x.f is a method object, and can be stored away and called at a later time. For example:

Code: Alles auswählen

xf = x.f
while True:
    print(xf())
will continue to print hello world until the end of time.
Aber hey, DL3AD will ja wirklich alles auf dem Silbertablett serviert haben…
long long ago; /* in a galaxy far far away */
__deets__
User
Beiträge: 7712
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 13. Februar 2020, 14:23

@__blackjack__: joa, ist mir schon klar. Berg, Prophet - bilden sie einen Satz ;)
Benutzeravatar
__blackjack__
User
Beiträge: 5546
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 13. Februar 2020, 14:27

„Der Prophet wohnt in Kreuzberg und man darf keine Bilder von ihm malen — sonst Blutbad oder mindestens wütender Mob der irgendwelche Fahnen verbrennt.“ ☝️ 😉
long long ago; /* in a galaxy far far away */
Antworten