Search code examples
pythonpyqtpyqt5qtoolbutton

Python Create a real circle button in pyqt5


I try to create a circle button but in fact pyqt still creates a square button.All examples found just creates square buttons and put a round image in it but still when i try to hide background of the button it fails.I also try to add some hover function but this should work afterwords so you can skip it.My code is here:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QAction
from PyQt5.QtGui import QPalette
# from video import VideoWindow
import sys

class HoverButton(QtWidgets.QToolButton):

    def __init__(self, parent=None):
        super(HoverButton, self).__init__(parent)
        self.setMouseTracking(True)

    def enterEvent(self,event):
        # print("Enter")
        self.setStyleSheet('''   
                                 border-image: url("images/exit.jpg") 10 10 2 2;
                                 border-top: 10px transparent;
                                 border-bottom: 10px transparent;
                                 border-right: 2px transparent;
                                 border-left: 2px transparent''')
        self.setGeometry(QtCore.QRect(1100, 550, 160, 161))

    def leaveEvent(self,event):
        self.setStyleSheet('''  
                                 border-image: url("images/exit.jpg") 10 10 2 2;
                                 border-top: 10px transparent;
                                 border-bottom: 10px transparent;
                                 border-right: 2px transparent;
                                 border-left: 2px transparent''')
        self.setGeometry(QtCore.QRect(1100, 550, 140, 141))

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1371, 924)
        MainWindow.setAcceptDrops(True)
        self.button =  HoverButton(self)
        self.button.setGeometry(QtCore.QRect(1100, 550, 140, 141)) 
        self.button.setStyleSheet('''background: transparent;
                                 border-image: url("images/exit.jpg") 3 10 3 10;
                                 border-top: 3px transparent;
                                 border-bottom: 3px transparent;
                                 border-right: 10px transparent;
                                 border-left: 10px transparent;
                                 ''')
        self.button.setObjectName('button')
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Output: enter image description here


Solution

  • One possible solution is to use setMask(), the advantage of this implementation is that the click event will only be for points inside the region.:

    class HoverButton(QtWidgets.QToolButton):
        def __init__(self, parent=None):
            super(HoverButton, self).__init__(parent)
            self.setStyleSheet('''border-image: url("imagen.jpg")''')
    
        def resizeEvent(self, event):
            self.setMask(QtGui.QRegion(self.rect(), QtGui.QRegion.Ellipse))
            QtWidgets.QToolButton.resizeEvent(self, event)
    

    Before:

    enter image description here

    After:

    enter image description here

    In your case the QRect() that is passed to QRegion must be adapted to the size of your image since the circular element is smaller than your image, a much easier way is to edit your image making the circle perfectly inscribed in your image as my image is.