Animation Overlay

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Dragonfire
User
Beiträge: 22
Registriert: Dienstag 28. Februar 2012, 09:03

Kurz noch eine weitere Frage,
ist es möglich in python QT eine Art Overlay zu erzeugen?

In C++ geht es angeblich:
http://www.developer.nokia.com/Communit ... of_another

Habe dies nicht in PythonQT portiert bekommen ...

Code: Alles auswählen

from PyQt4 import QtGui, QtCore

class Overlay (QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
#        self.setPalette(QtCore.Qt.transparent)
        self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
        
    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setRenderHint(0x01)
        painter.setPen(QtGui.QColor());
        painter.drawLine(100, 100, 1000, 1000);
        

class MainWindows(QtGui.QMainWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
        widget = QtGui.QWidget()
        editor = QtGui.QTextEdit()
#        editor.setMinimumSize(100, 100)
        layout = QtGui.QGridLayout(widget)
        
        layout.addWidget(editor, 0,0,1,2)
        self.setCentralWidget(widget)
        
        overlay = Overlay(self.centralWidget())
    
app = QtGui.QApplication([])
win = MainWindows()
win.setMinimumSize(500, 500)
win.show()
app.exec_()
Grobe Vorstellung:
Ich würde z.B. eine Widget ausgrauen und ein Ladekreis darüber anzeigen lassen ...

Sollte dies nicht gehen,
müsste ich mit einem Stacked Widget arbeiten,
was ich nicht ganz so schön finde, da man dann die Komponenten darunter nicht sieht.
lunar

@Dragonfire: In "MainWindows.__init__()" muss "widget", "editor" und "overlay" ein "parent" zugewiesen werden. Ansonsten werden diese Objekte am Ende von ".__init__()" wieder gelöscht. Das verlinkte Beispiel ist in dieser Hinsicht nicht besser, denn es verursacht Speicherlecks. Außerdem solltest Du statt "0x01" "QPainter.Antialiasing" an "painter.setRenderHint()" übergeben.

Für die Zukunft: Es reicht nicht, einfach nur den Quelltext hinzuklatschen. Du musst schon beschreiben, welche Fehler auftreten und was nicht funktioniert. Ansonsten können wir nur raten, was in diesem Fall nicht schwer war, weil der Fehler ziemlich offensichtlich ist. Wäre das Raten aber kompliziert wird, kann es passieren, dass einfach niemand antwortet.

Im Übrigen heißt es "Qt" und "PyQt"...
Dragonfire
User
Beiträge: 22
Registriert: Dienstag 28. Februar 2012, 09:03

lunar hat geschrieben:@Dragonfire: In "MainWindows.__init__()" muss "widget", "editor" und "overlay" ein "parent" zugewiesen werden. Ansonsten werden diese Objekte am Ende von ".__init__()" wieder gelöscht. Das verlinkte Beispiel ist in dieser Hinsicht nicht besser, denn es verursacht Speicherlecks. Außerdem solltest Du statt "0x01" "QPainter.Antialiasing" an "painter.setRenderHint()" übergeben.
Habe ich einen Denkfehler?

Ich erzeuge ein QWidget (sagen wir mal mainPanel), was ich mit einem QGridLayout (LayoutManager) ausstatte ...
Auf diesem Layout packe ich das QTextEdit Widget.

Anschließend füge ich das "mainPanel" auf dem QMainWindows ...
Sollte ich nichts mehr verändern wollen könnte ich das ja alles wegschmeißen ...

[...]

Ich dachte ich hätte genau genug beschrieben, was ich vorhatte (siehe Abschnitt unter dem Quellcode).
In meinem Beispiel hätte ich jetzt erstmal nur Lienen die "über" den normalen Widget gezeichnet werden sollten,
wie in meinem verlinktem Beispiel, nur anders positioniert.
Allerdings muss ich viel falsch gemacht haben, immerhin sieht man das Fenster mit TextFeld^^

Nochmal:

Ich möchte ein Widget ausgrauen/verdunkeln und darüber ein Ladekreis (http://standorte.deutschepost.de/images ... ekreis.gif)
anzeigen lassen. Der Ladekreis ist eine extra Geschichte, entweder nehme ich mir da ein gif,
oder zeichne es selbst über paintEvent, wie es in dem Beispiel erstmal versucht wurde (nur mit festen Lienen).

###

Das große Problem ist ja,
dass man durch das überschreiben der paintEvent Methode in MainWindows leider nur den Hintergrund verändern kann.


Ich hatte es so verstanden, dass dieses Beispiel:

http://www.developer.nokia.com/Communit ... of_another

diese Eigenschaft aufhebt, mithilfe eines OverlayWidget, welches als Vater das zentrale Widget des Fensters bekommt.
lunar

@Dragonfire: Ich würde schwören, dass "self.centralWidget()" noch nicht als Argument an "Overlay()" übergeben wurde, als ich meine Antwort verfasst habe. Seis drum, vielleicht habe ich mich auch nur verlesen...

Das eigentlichen Problem ist, dass Du das Beispiel schlicht und einfach nicht vollständig übertragen hast. Die Definition von "resizeEvent()" hast Du ganz einfach ignoriert, obwohl sie essentiell ist, weil sie die Größe Overlay-Widgets anpasst, wenn sich die Fenstergröße ändert. Ohne diese Definition wird das Overlay-Widget zwar angezeigt, aber eben mit einer Höhe und Breite von 0 Pixeln.

Korrigierte Version
Dragonfire
User
Beiträge: 22
Registriert: Dienstag 28. Februar 2012, 09:03

lunar hat geschrieben:@Dragonfire: Ich würde schwören, dass "self.centralWidget()" noch nicht als Argument an "Overlay()" übergeben wurde, als ich meine Antwort verfasst habe. Seis drum, vielleicht habe ich mich auch nur verlesen...
Ich würde schwören, dass "resizeEvent" noch da stand xD
Es kommt der ganzen Sache schon näher ;)

Code: Alles auswählen

from PyQt4 import QtGui, QtCore

class Overlay (QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setPalette(QtGui.QPalette(QtCore.Qt.transparent))
        self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)

        self.movie_screen = QtGui.QLabel()
        
        # expand and center the label 
        self.movie_screen.setSizePolicy(QtGui.QSizePolicy.Expanding, 
            QtGui.QSizePolicy.Expanding)        
        self.movie_screen.setAlignment(QtCore.Qt.AlignCenter) 
     

        main_layout = QtGui.QVBoxLayout() 
        main_layout.addWidget(self.movie_screen)
        self.setLayout(main_layout) 
                
        # use an animated gif file you have in the working folder
        # or give the full file path
        self.movie = QtGui.QMovie("ladekreis.gif", QtCore.QByteArray(), self) 
        self.movie.setCacheMode(QtGui.QMovie.CacheAll) 
        self.movie.setSpeed(100) 
        self.movie_screen.setMovie(self.movie) 
        self.movie.start()
        
    def paintEvent(self, e):

        qp = QtGui.QPainter()
        qp.begin(self)
        qp.setBrush(QtGui.QColor(255, 255, 255, 200))
        qp.drawRect(0, 0, 1000, 1000)
        qp.end()


class MainWindows(QtGui.QMainWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
        widget = QtGui.QWidget()
        editor = QtGui.QTextEdit('Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.')
        layout = QtGui.QGridLayout(widget)

        layout.addWidget(editor, 0,0,1,2)
        self.setCentralWidget(widget)

        self.overlay = Overlay(self.centralWidget())

    def resizeEvent(self, event):
        self.overlay.resize(event.size())
        QtGui.QMainWindow.resizeEvent(self, event)


def main():
    app = QtGui.QApplication([])
    win = MainWindows()
    win.setMinimumSize(500, 500)
    win.show()
    app.exec_()


if __name__ == '__main__':
    main()
Ps.: Man braucht nur noch:
http://standorte.deutschepost.de/images ... ekreis.gif

VIELEN VIELEN DANK !!!
Antworten