es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Por qué estoy experimentando lo que parece ser un retraso en la actualización de este QGraphicsItem móvil de PyQt5, y cómo puedo solucionarlo?

Cuando ejecuto este código en mi computadora, funciona bien en su mayor parte. Pero si hago clic y arrastro el círculo muy rápidamente, el lado que está “adelante” en términos de movimiento será ocultado por el color de fondo. Si arrastro muy rápido, obtengo imágenes residuales discretas y blancas del objeto (aunque el objeto es rojo). Supongo que el código que actualiza el lienzo tarda demasiado en llegar con el primero; Realmente no sé acerca de las imágenes residuales.

Es difícil de describir, así que recomiendo que mires este screencast del comportamiento.

El código está debajo. ¿Hay alguna forma de solucionar esto?

import sys
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
from PyQt5.QtWidgets import QGraphicsEllipseItem, QGraphicsRectItem, QGraphicsItem
from PyQt5.QtGui import QBrush, QPen
from PyQt5.QtCore import Qt

app = QApplication(sys.argv)

scene = QGraphicsScene(0,0,600,400)

rect = QGraphicsRectItem(50,20,200,50)
circle = QGraphicsEllipseItem(75,30,100,100)

brush = QBrush(Qt.red)
pen = QPen(Qt.black)
pen.setWidth(2)

circle.setBrush(brush)
circle.setPen(pen)
rect.setBrush(brush)
rect.setPen(pen)

scene.addItem(circle)
scene.addItem(rect)

scene.setBackgroundBrush(QBrush(Qt.cyan))

circle.setFlag(QGraphicsItem.ItemIsMovable)
rect.setFlag(QGraphicsItem.ItemIsMovable)

view = QGraphicsView(scene)
view.show()
app.exec_()
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que la escena gráfica no se actualiza lo suficientemente rápido cuando el círculo se arrastra rápidamente. Una forma de solucionar esto es llamar a QCoreApplication.processEvents() dentro del método mouseMoveEvent de QGraphicsEllipseItem. Esto asegura que la cola de eventos se procese entre cada evento de movimiento del ratón, permitiendo que la escena se actualice con mayor frecuencia.

    Así es cómo puedes modificar el código para solucionar este problema:

    import sys
    from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene
    from PyQt5.QtWidgets import QGraphicsEllipseItem, QGraphicsRectItem, QGraphicsItem
    from PyQt5.QtGui import QBrush, QPen
    from PyQt5.QtCore import Qt, QCoreApplication
    
    app = QApplication(sys.argv)
    
    scene = QGraphicsScene(0,0,600,400)
    
    rect = QGraphicsRectItem(50,20,200,50)
    circle = QGraphicsEllipseItem(75,30,100,100)
    
    # así es cómo se cambian el color de relleno y el contorno
    brush = QBrush(Qt.red)
    pen = QPen(Qt.black)
    pen.setWidth(2)
    
    circle.setBrush(brush)
    circle.setPen(pen)
    rect.setBrush(brush)
    rect.setPen(pen)
    
    # se mantiene el orden de apilamiento; utiliza setZValue para reorganizar
    scene.addItem(circle)
    scene.addItem(rect)
    
    scene.setBackgroundBrush(QBrush(Qt.cyan))
    
    # podemos establecer que el elemento sea movible DESPUÉS de que se añada a la escena
    circle.setFlag(QGraphicsItem.ItemIsMovable)
    rect.setFlag(QGraphicsItem.ItemIsMovable)
    
    class CustomEllipseItem(QGraphicsEllipseItem):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
        def mouseMoveEvent(self, event):
            super().mouseMoveEvent(event)
            QCoreApplication.processEvents()
    
    circle = CustomEllipseItem(75,30,100,100)
    circle.setBrush(brush)
    circle.setPen(pen)
    
    scene.addItem(circle)
    
    view = QGraphicsView(scene)
    view.show()
    app.exec_()
    

    Al crear una nueva subclase de QGraphicsEllipseItem y sobrescribir el método mouseMoveEvent, agregamos la llamada a QCoreApplication.processEvents() después de la llamada al método super(). Esto asegura que la escena se actualice con mayor frecuencia cuando el círculo se arrastra rápidamente, evitando el problema de la ocultación y las imágenes residuales blancas.

Comments are closed.