Seite 1 von 1

Python - Qt - AniGif

Verfasst: Freitag 29. Juni 2018, 07:17
von Ulrich_G
Guten Morgen,
muss mich leider noch mal bei euch melden ... komme leider überhaupt nicht weiter mit meinem animierten Gif
Mein aktueller Code sieht wie folgt aus:

Code: Alles auswählen

from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sys
import serial

class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi('firstgui.ui', self)
        self.btn_write.clicked.connect(self.read_Spannung)
        self.btn_read.clicked.connect(self.read_Kennung)
        self.btn_start.clicked.connect(self.statusPicture)
        self.btn_abbruch.clicked.connect(self.disable_FMInfo)
        self.status_txt = QtGui.QLabel()
        movie = QtGui.QMovie("etc/loading.gif")
        self.status_txt.setMovie(movie)
        movie.start()
        self.status_txt.setLayout(QtGui.QHBoxLayout())
        self.status_txt.layout().addWidget(QLabel('Loading...'))
        self.show()
    
    def statusPicture(self):
        pixmap = QPixmap('status_pass.png')
        self.pic_Status.setPixmap(pixmap)
        self.pic_Status.show()

    def read_Spannung(self):
        with serial.Serial('COM1',9600, 8, 'N',1) as ser:
            ser.write(b':MEASure:PRIMary:VOLTage:DC?\n')
            read_value = float(ser.readline())
            self.textBrowser.append(str(read_value)) 
            ser.close() 

    def read_Kennung(self):
        with serial.Serial('COM1',9600, 8, 'N',1) as ser:
            ser.write(b'*IDN?\n') 
            read_value = ser.readline()
            self.textBrowser.append(str(read_value)) 
            ser.close()

    def disable_FMInfo(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04,0x00,0x00,0x26,0x01,0x00,0x00,0x01,0x00,0x84,0xA2,0x05])) 
            RS232_Antwort = (str(ser.read(13)))
            self.textBrowser.append(RS232_Antwort)
            ser.close()    

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    sys.exit(app.exec_())
Daraufhin bekomme ich immer die Meldung: E0602:Undefined variable 'QLabel'
was mache ich falsch?

Gruß
Ulrich

Re: Python - Qt - AniGif

Verfasst: Freitag 29. Juni 2018, 08:34
von __deets__
Da fehlt ein QtGui vor dem QLabel. Schau dir noch mal die Sektionen im Python Tutorial zu Importen an, um das besser zu verstehen.

Re: Python - Qt - AniGif

Verfasst: Freitag 29. Juni 2018, 08:38
von __blackjack__
@Ulrich_G: Die ganzen ``ser.close()`` sind übrigens überflüssig. Genau das erledigt die ``with``-Anweisung.

Re: Python - Qt - AniGif

Verfasst: Montag 2. Juli 2018, 08:20
von Ulrich_G
Guten Morgen,
ich komme leider keinen Schritt weiter und bin etwas verzweifelt :-(
Ein QtGui steht ab PyQt5 anscheinend nicht mehr vor dem QLabel. Mein Code würde an sich schon auch laufen nur wird mir keine Animation angezeigt. Füge ich ein self.pic_AniGif.show() hinzu wird mir das AniGif nur als Popup angezeigt... jedoch nicht im Hauptfenster.

Mein aktueller Code:

Code: Alles auswählen

import sys
import serial
from PyQt5 import uic
from PyQt5.QtWidgets import (QWidget, QToolTip, QPushButton, QApplication, QMessageBox, QMainWindow, QLabel, QHBoxLayout)
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QFont, QMovie, QPixmap

class Ui(QMainWindow):
    def __init__(self):
        super().__init__()
        #super(Ui, self).__init__()
        self.title = 'PyQt5 image - pythonspot.com'
        uic.loadUi('firstgui.ui', self)
        self.btn_write.clicked.connect(self.read_Spannung)
        self.btn_read.clicked.connect(self.read_Kennung)
        self.btn_start.clicked.connect(self.statusPicture)
        self.btn_abbruch.clicked.connect(self.disable_FMInfo)
        self.btn_Bootloader.clicked.connect(self.load_Bootloader)
        self.btn_Firmware.clicked.connect(self.load_Firmware)
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        
        # Create widget
        self.pic_AniGif = QLabel()
        movie = QMovie('C:\warten.gif')
        self.pic_AniGif.setMovie(movie)
        movie.start()
        #self.pic_AniGif.setLayout(QHBoxLayout())
        #self.pic_AniGif.layout().addWidget(QLabel('Loading...'))
        self.show()
    
    def statusPicture(self):
        pixmap = QPixmap('status_pass.png')
        self.pic_Status.setPixmap(pixmap)
        self.pic_Status.show()
        self.pic_AniGif.show()

    def read_Spannung(self):
        with serial.Serial('COM1',9600, 8, 'N',1) as ser:
            ser.write(b':MEASure:PRIMary:VOLTage:DC?\n')
            read_value = float(ser.readline())
            self.textBrowser.append(str(read_value)) 
            #ser.close() 

    def read_Kennung(self):
        with serial.Serial('COM1',9600, 8, 'N',1) as ser:
            ser.write(b'*IDN?\n') 
            read_value = ser.readline()
            self.textBrowser.append(str(read_value)) 
            #ser.close()

    def disable_FMInfo(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04,0x00,0x00,0x26,0x01,0x00,0x00,0x01,0x00,0x84,0xA2,0x05])) 
            RS232_Antwort = (str(ser.read(13)))
            self.textBrowser.append(RS232_Antwort)
            #ser.close()   

    def load_Bootloader(self):
        with serial.serial('COM1',115200,8,'N',1) as ser:
            ser.write()
                #strProgramName = "C:\SMC\ToolsPart1\DownloadPart1.exe"
                #strArgument = COMPort & " " & DB_Pfad & "ToolsPart1\bootloader.bin"
            #ser.close() 

    def load_Firmware(self):
        with serial.serial('COM1',115200,8,'N',1) as ser:
            ser.write()
                #strProgramName = "C:\SMC\ToolsPart1\DownloadPart1.exe"
                #strArgument = COMPort & " " & DB_Pfad & "ToolsPart1\" & Firmware & " protect"
            #ser.close() 

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Ui()
    sys.exit(app.exec_())
Wäre es möglich meinen Code so abzuändern damit ich auf einen grünen Zweig komme? bin momentan etwas ratlos und auf Hilfe angewiesen.

Gruß
Ulrich

Re: Python - Qt - AniGif

Verfasst: Montag 2. Juli 2018, 08:40
von __deets__
Ich mag mich vertan haben, es muss vielleicht QWidgets sein. Aber nochmal: du musst die Importe verstehen. Die Qt Dokumentation separiert die verschiedenen Klasse klar in Teilprojekte, und PyQt bildet das nach. Wenn in der Doku steht, das etwas Teil von QtCore ist, dann musst du das von da holen. Und entsprechend auch für die anderen.

Re: Python - Qt - AniGif

Verfasst: Montag 2. Juli 2018, 08:46
von __deets__
Nachtrag: ich habe deinen Post missverstanden. Vergiss meine letzte Bemerkung.

Re: Python - Qt - AniGif

Verfasst: Montag 2. Juli 2018, 08:50
von __deets__
Du musst dem QLabel dein Fenster als parent übergeben. QWidgets formen eine Hierarchie, und das steht auch so in dem Beispiel das ich dir gezeigt habe. Da bekommt das QLabel ein this-Argument, was irgendeine Fenster oder Widget Instanz ist.

Re: Python - Qt - AniGif

Verfasst: Dienstag 3. Juli 2018, 08:24
von Ulrich_G
Hallo,
konnte das Problem jetzt lösen.
Hier der Code ... wenn es jemanden interessiert:

Code: Alles auswählen

import sys
import serial
import subprocess
from PyQt5 import uic
from PyQt5.QtWidgets import (QWidget, QMainWindow, QPushButton, QApplication, QLabel, QSizePolicy, QVBoxLayout)
from PyQt5.QtCore import QSize, QByteArray
from PyQt5.QtGui import QFont, QMovie, QPixmap#, QFontMetrics, QPainter
import ctypes  # An included library with Python install.

class SMCTool(QWidget):
    def __init__(self, filename, title, parent=None):
        QWidget.__init__(self, parent)
        uic.loadUi('frame.ui', self)

        self.btn_reboot.clicked.connect(self.Set_Reboot)
        self.btn_FMInfo.clicked.connect(self.Set_disable_FMInfo)
        self.btn_led_green.clicked.connect(self.Set_LEDgreen)
        self.btn_status.clicked.connect(self.Read_Status)
        self.btn_start.clicked.connect(self.statusPicture)
        self.btn_abbruch.clicked.connect(self.Set_disable_FMInfo)
        self.btn_bootloader.clicked.connect(self.load_Bootloader)
        self.btn_firmware.clicked.connect(self.load_Firmware)

        # Load the file into a QMovie
        self.movie = QMovie(filename, QByteArray(), self)
        self.status_txt = QLabel()

        # Create the layout
        self.main_layout.addWidget(self.status_txt)

        # Add the QMovie object to the label
        self.movie.setCacheMode(QMovie.CacheAll)
        self.movie.setSpeed(100)
        self.status_txt.setMovie(self.movie)
        self.movie.start()

    def statusPicture(self):
        pixmap = QPixmap('status_pass.png')
        self.pic_Status.setPixmap(pixmap)
        self.pic_Status.show()
    
    def Set_Reboot(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04, 0xFF, 0xFF, 0x27, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6E, 0xD3, 0x05]))

    def Set_LEDgreen(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04, 0xFF, 0xFF, 0x23, 0x01, 0x00, 0x03, 0x00, 0x02, 0xB4, 0xAD, 0x05]))  

    def Read_Status(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04,0x00,0x00,0x26,0x01,0x00,0x00,0x01,0x00,0x84,0xA2,0x05])) 
            RS232_Antwort = (str(ser.read(13)))
            self.textBrowser.append(RS232_Antwort)
            #ser.close()   

    def Set_disable_FMInfo(self):
        with serial.Serial('COM1',115200, 8, 'N',1) as ser:
            ser.write(serial.to_bytes([0x04,0x00,0x00,0x26,0x01,0x00,0x00,0x01,0x00,0x84,0xA2,0x05])) 
            RS232_Antwort = str(ser.read(13))
            self.textBrowser.append(RS232_Antwort) 

    def load_Bootloader(self):
        p = subprocess.Popen(['C:\\SMC\\ToolsPart1\\DownloadPart1.exe', '1', 'C:\\SMC\\ToolsPart1\\bootloader.bin'], stdout=subprocess.PIPE)
        p.wait()
        str1 = str(p.stdout.read(), 'utf-8')
        print(str1)
        str2 = "Done"
        if str1.find(str2) > 0:     
            Mbox('Upload', 'Prozess erfolgreich abgeschlossen', 1) 
        else:
            Mbox('Upload', 'Prozess fehlerhaft', 1) 

    def load_Firmware(self):
        p = subprocess.Popen(['C:\\SMC\\ToolsPart1\\DownloadPart1.exe', '1', 'C:\\SMC\\ToolsPart1\\SMC47_crc_encr_V5_0.bin'], stdout=subprocess.PIPE)
        p.wait()
        str1 = str(p.stdout.read(), 'utf-8')
        print(str1)
        str2 = "Done"
        if str1.find(str2) > 0:     
            Mbox('Upload', 'Prozess erfolgreich abgeschlossen', 1) 
        else:
            Mbox('Upload', 'Prozess fehlerhaft', 1) 

def Mbox(title, text, style):
    return ctypes.windll.user32.MessageBoxW(0, text, title, style)

if __name__ == "__main__":
    gif = "Movie.gif"
    app = QApplication(sys.argv)
    player = SMCTool(gif, "was")
    player.show()
    sys.exit(app.exec_())
Danke für die Unterstützung

Gruß
Ulrich

Re: Python - Qt - AniGif

Verfasst: Dienstag 3. Juli 2018, 09:08
von Sirius3
Du solltest Dich auf eine Schreibweise beschränken, also die Methoden entweder nach QT-Style oder in Pythonkonvention benennen und nicht mischen und noch eigene Varianten erfinden, also entweder `readStatus` oder `read_status`, und das einheitlich für alle Methoden.
Es ist selten sinnvoll, die Stringrepräsentation von Bytes zu verwenden. Was sinnvoll ist, kommt drauf an, was Du mit der RS232_Anwort weiter machst.
`Read_Status` und `Set_disable_FMInfo` sind identisch, ist das so gewollt?
Benutze statt subprocess.Popen subprocess.run oder subprocess.check_output.
Variablen durchzunummerieren und dann noch so generische Namen wie str1 und str2 zu verwenden, sind ein Zeichen dafür, dass man nicht weiß, um was es sich bei den Werten handelt. Die Zuweisung der Konstanten ist komplett überflüssig, statt find benutze den in-Operator. Beim Benutzen von subprocess.check_output sollte hoffentlich schon ein nicht erfolgreicher Lauf eine Exception werfen, so dass das fragile Parsen des Outputs überflüssig ist.
Warum benutzt Du user32.MessageBox statt einer QT-Messagebox?

Re: Python - Qt - AniGif

Verfasst: Donnerstag 5. Juli 2018, 16:16
von Ulrich_G
Vielen Dank für deine Tipps . Komme schon viel besser damit klar.

Hab noch eine kleine Frage:
Mein animiertes Gif wird während eines Uploads (Fremdprogramm über Exe) unterbrochen bis der Upload durchgeführt wurde. Es bleibt also stehen.
Kann man das umgehen? Welchen Ansatz würdet ihr mir hierzu empfehlen?

Gruß
Ulrich

Re: Python - Qt - AniGif

Verfasst: Donnerstag 5. Juli 2018, 16:42
von __deets__
Na du wartest ja auch darauf, dass der Prozess beendet wird. Dann blockiert die GUI. Da musst du anders rangehen, zb über eine Timer periodisch prüfen, ob der Prozess schon fertig ist.

Re: Python - Qt - AniGif

Verfasst: Donnerstag 5. Juli 2018, 17:08
von __blackjack__
Ich sehe beim Aufrufen der Prozesse noch ein weiteres Problem: erst `wait()` und dann die gepipete Ausgabe lesen führt zu einem Deadlock wenn das Programm mehr ausgibt als in den Puffer zwischen den beiden Prozesse passt.

Re: Python - Qt - AniGif

Verfasst: Donnerstag 5. Juli 2018, 17:46
von Sirius3
@__deets__: dann muß man aber auch periodisch den Ausgabepuffer leeren, also z.B. über ein nicht-blockierendes read.