How to use css's :after for widgets in pyqt

Viewed 328

I am thinking to create a PyQt6 Application.

I want that application to be more beautiful and modern. So I found some good looking css buttons and chose this codepen button:

* {
  margin: 0;
  padding: 0;
}

html,
body {
  box-sizing: border-box;
  height: 100%;
  width: 100%;
}

body {
  background: #FFF;
  font-family: 'Noto Sans JP', sans-serif;
  font-weight: 400;
}

.buttons {
  display: flex;
  flex-direction: row;
      flex-wrap: wrap;
  justify-content: center;
  text-align: center;
  width: 100%;
  height: 100%;
  margin: 0 auto;
/*   padding: 2em 0em; */
}

.container {
  align-items: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  background-color: #FFF;
  padding:  40px 0px;
  width: 240px;
}

h1 {
  text-align: left;
  color: #444;
  letter-spacing: 0.05em;
  margin: 0 0 0.4em;
  font-size: 1em;
}

p {
  text-align: left;
  color: #444;
  letter-spacing: 0.05em;
  font-size: 0.8em;
  margin: 0 0 2em;
}


.btn {
  letter-spacing: 0.1em;
  cursor: pointer;
  font-size: 14px;
  font-weight: 400;
  line-height: 45px;
  max-width: 160px;
  position: relative;
  text-decoration: none;
  text-transform: uppercase;
  width: 100%;
}
.btn:hover {
  text-decoration: none;
}

/*btn_background*/
.effect01 {
  color: #FFF;
  border: 4px solid #000;
  box-shadow:0px 0px 0px 1px #000 inset;
  background-color: #000;
  overflow: hidden;
  position: relative;
  transition: all 0.3s ease-in-out;
}
.effect01:hover {
  border: 4px solid #666;
  background-color: #FFF;
  box-shadow:0px 0px 0px 4px #EEE inset;
}

/*btn_text*/
.effect01 span {
  transition: all 0.2s ease-out;
  z-index: 2;
}
.effect01:hover span{
  letter-spacing: 0.13em;
  color: #333;
}

/*highlight*/
.effect01:after {
  background: #FFF;
  border: 0px solid #000;
  content: "";
  height: 155px;
  left: -75px;
  opacity: .8;
  position: absolute;
  top: -50px;
  -webkit-transform: rotate(35deg);
          transform: rotate(35deg);
  width: 50px;
  transition: all 1s cubic-bezier(0.075, 0.82, 0.165, 1);/*easeOutCirc*/
  z-index: 1;
}
.effect01:hover:after {
  background: #FFF;
  border: 20px solid #000;
  opacity: 0;
  left: 120%;
  -webkit-transform: rotate(40deg);
          transform: rotate(40deg);
}
<div class="buttons">
  <div class="container">
      <h1>光の反射</h1>
      <p>Light reflection</p>
      <a href="https://twitter.com/masuwa1018" class="btn effect01" target="_blank"><span>Hover</span></a>
  </div>
</div>

My question is: how can I use pyqt's functions to perform the :after.

I guess I cant just use a widget's stylesheet to perform.

Here is the Python Code that I have written so far:

from PyQt6.QtCore import QRect, Qt
from PyQt6.QtGui import QEnterEvent
from PyQt6.QtWidgets import QGraphicsOpacityEffect, QMainWindow, QPushButton


class QButton(QPushButton):
    def __init__(self , main_window: QMainWindow):
        super().__init__(main_window)
        
        self.main_window = main_window
        
        self.setText("Welcome")
        
        self.render()
        
    def render(self):
        self.setStyleSheet("""
            QPushButton{
                background-color: #2E3440;
                letter-spacing: 0.1px;
                font-size: 14px;
                font-weight: 400;
                line-height: 45px;
                text-decoration: none;
                color: #FFF;
                border: 4px solid #4C566A;
            }
        """)
        
        self.setFlat(True)
        
        self.setCursor(Qt.CursorShape.PointingHandCursor)
        
        self.setGeometry(QRect(200 , 200 , 200 , 50))
        
    def setText(self , text: str):
        text = text.upper()
        
        super().setText(text)
        
    def enterEvent(self, event: QEnterEvent) -> None:
        self.setStyleSheet("""
            background-color: #D8DEE9;
            letter-spacing: 0.13em;
            color: #2E3440;              
            border: 0px;
        """)
        
        opacity = QGraphicsOpacityEffect()
        
        opacity.setOpacity(.8)
        
        self.setGraphicsEffect(opacity)
        
        return super().enterEvent(event)

class Renderer:
    def __init__(self, main_window: QMainWindow) -> None:
        self.main_window = main_window
    
    def render(self):
        button = QButton(self.main_window)
                
    
if __name__ == "__main__":
    app = QApplication([])
    
    window = QMainWindow()
    
    renderer = Renderer(window)
    
    renderer.render()
    
    window.show()
    
    exit(app.exec())
1 Answers

Unfortunately, you can't. Qt Style Sheets are fundamentally based on CSS 2.1, and only support its basic implementation (see the syntax documentation).

If you want a more customized and advanced behavior, you have only two options:

  • subclass the widget and/or use QProxyStyle;
  • use QML;
Related