Quantcast
Channel: Preguntas activas con las etiquetas pyqt - Stack Overflow en español
Viewing all articles
Browse latest Browse all 79

Problema con cursor en redimensionamiento de ventana sin borde en Pyqt

$
0
0

Soy nuevo en python y aún mas nuevo usando Pyqt así que he estado revisando y estudiando algunos ejemplos. Encontré este ejemplo que, en resumen, crea una ventana sin borde usando QtCore.Qt.FramelessWindowHint y luego le crea grips personalizados en los bordes y las esquinas que permiten redimensionzar la ventana, aquí el enlace: https://stackoverflow.com/questions/62807295/how-to-resize-a-window-from-the-edges-after-adding-the-property-qtcore-qt-framel

El código parece funcionar bien pero encontré un detalle. Primero debo aclarar que usé el mismo código del ejemplo, lo único que modifiqué es que usé setMinimumSize() para establecer un tamaño minimo de 100 x 100 para la ventana. Aquí el código que estoy usando:

from PyQt5 import QtCore, QtGui, QtWidgetsclass SideGrip(QtWidgets.QWidget):    def __init__(self, parent, edge):        QtWidgets.QWidget.__init__(self, parent)        if edge == QtCore.Qt.LeftEdge:            self.setCursor(QtCore.Qt.SizeHorCursor)            self.resizeFunc = self.resizeLeft        elif edge == QtCore.Qt.TopEdge:            self.setCursor(QtCore.Qt.SizeVerCursor)            self.resizeFunc = self.resizeTop        elif edge == QtCore.Qt.RightEdge:            self.setCursor(QtCore.Qt.SizeHorCursor)            self.resizeFunc = self.resizeRight        else:            self.setCursor(QtCore.Qt.SizeVerCursor)            self.resizeFunc = self.resizeBottom        self.mousePos = None    def resizeLeft(self, delta):        window = self.window()        width = max(window.minimumWidth(), window.width() - delta.x())        geo = window.geometry()        geo.setLeft(geo.right() - width)        window.setGeometry(geo)    def resizeTop(self, delta):        window = self.window()        height = max(window.minimumHeight(), window.height() - delta.y())        geo = window.geometry()        geo.setTop(geo.bottom() - height)        window.setGeometry(geo)    def resizeRight(self, delta):        window = self.window()        width = max(window.minimumWidth(), window.width() + delta.x())        window.resize(width, window.height())    def resizeBottom(self, delta):        window = self.window()        height = max(window.minimumHeight(), window.height() + delta.y())        window.resize(window.width(), height)    def mousePressEvent(self, event):        if event.button() == QtCore.Qt.LeftButton:            self.mousePos = event.pos()    def mouseMoveEvent(self, event):        if self.mousePos is not None:            delta = event.pos() - self.mousePos            self.resizeFunc(delta)    def mouseReleaseEvent(self, event):        self.mousePos = Noneclass Main(QtWidgets.QMainWindow):    _gripSize = 8    def __init__(self):        QtWidgets.QMainWindow.__init__(self)        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)        self.sideGrips = [            SideGrip(self, QtCore.Qt.LeftEdge),             SideGrip(self, QtCore.Qt.TopEdge),             SideGrip(self, QtCore.Qt.RightEdge),             SideGrip(self, QtCore.Qt.BottomEdge),         ]        # corner grips should be "on top" of everything, otherwise the side grips        # will take precedence on mouse events, so we are adding them *after*;        # alternatively, widget.raise_() can be used        self.cornerGrips = [QtWidgets.QSizeGrip(self) for i in range(4)]        self.setMinimumSize(100, 100)    @property    def gripSize(self):        return self._gripSize    def setGripSize(self, size):        if size == self._gripSize:            return        self._gripSize = max(2, size)        self.updateGrips()    def updateGrips(self):        self.setContentsMargins(*[self.gripSize] * 4)        outRect = self.rect()        # an "inner" rect used for reference to set the geometries of size grips        inRect = outRect.adjusted(self.gripSize, self.gripSize,            -self.gripSize, -self.gripSize)        # top left        self.cornerGrips[0].setGeometry(            QtCore.QRect(outRect.topLeft(), inRect.topLeft()))        # top right        self.cornerGrips[1].setGeometry(            QtCore.QRect(outRect.topRight(), inRect.topRight()).normalized())        # bottom right        self.cornerGrips[2].setGeometry(            QtCore.QRect(inRect.bottomRight(), outRect.bottomRight()))        # bottom left        self.cornerGrips[3].setGeometry(            QtCore.QRect(outRect.bottomLeft(), inRect.bottomLeft()).normalized())        # left edge        self.sideGrips[0].setGeometry(            0, inRect.top(), self.gripSize, inRect.height())        # top edge        self.sideGrips[1].setGeometry(            inRect.left(), 0, inRect.width(), self.gripSize)        # right edge        self.sideGrips[2].setGeometry(            inRect.left() + inRect.width(),             inRect.top(), self.gripSize, inRect.height())        # bottom edge        self.sideGrips[3].setGeometry(            self.gripSize, inRect.top() + inRect.height(),             inRect.width(), self.gripSize)    def resizeEvent(self, event):        QtWidgets.QMainWindow.resizeEvent(self, event)        self.updateGrips()app = QtWidgets.QApplication([])m = Main()m.show()m.resize(240, 160)app.exec_()

Ahora que la ventana tiene un tamaño mínimo establecido evidentemente los grips no permiten redimensionar la ventana por debajo de esas dimensiones, esto funciona bien. El problema ocurre cuando doy click izquierdo en cualquier grip de las esquinas (los laterales funcionan bien) y lo arrastro de tal manera que al soltar el "click" este está por fuera de la ventana (esto es posible debido a que se estableció un tamaño mínimo para la ventana). Entonces, después de soltar el "click" y al poner el cursor nuevamente sobre la ventana este adquiere el cursor del grip por el cual entró a la ventana. Es decir, si entra por un lateral de la ventana el cursor adquiere SizeHorCursor para TODA la ventana y lo mismo ocurre si entra por la parte de arriba, por la parte de abajo o por las esquinas, adquiere el cursor del grip por el que pasa para toda la ventana. Si se da click en cualquier parte de la ventana o sobre los grips el problema se arregla y todo funciona bien de nuevo.

Entiendo que el cursor solo debería cambiar si está sobre los grips así que no entiendo por qué sucede esto. Recalco que esto solo ocurre con los grips de las esquinas, los laterales responden bien al evento que describo. Mi suposición es que el evento de soltar el click no se registra correctamente al estar fuera de la ventana pero no sé que hacer al respecto. Entiendo que parece un problema estético solamente pero me gustaría entender por qué pasa esto y arreglarlo de ser posible o tener una solución alternativa que haga lo mismo.

Esta en mi primera pregunta en Stackoverflow así que espero haberla redactado bien y haber proporcionado información suficiente para que me puedan ayudar con este problema, Gracias!


Viewing all articles
Browse latest Browse all 79

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>