PyQt桌面弹幕笔记


说明:此篇文章用来记录开发桌面弹幕单词软件的笔记

笔记一:单独的弹幕,没字体背景

from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QFont, QMouseEvent
from PyQt5.QtCore import QTimer, Qt, QEvent, pyqtSignal, QRect
# import utils
import sys

class WordLabel(QLabel):
    onEnter = pyqtSignal()
    onLeave = pyqtSignal()
    onMousePress = pyqtSignal(QMouseEvent)
    onMouseMove = pyqtSignal(QMouseEvent)
    onMouseRelease = pyqtSignal(QMouseEvent)

    def __init__(self, *argv, **kw):
        super().__init__(*argv, **kw)

        self.installEventFilter(self)

    def enterEvent(self, e):
        self.onEnter.emit()

    def leaveEvent(self, e):
        self.onLeave.emit()

    def mousePressEvent(self, e):
        self.onMousePress.emit(e)

    def mouseMoveEvent(self, e):
        self.onMouseMove.emit(e)

    def mouseReleaseEvent(self, e):
        self.onMouseRelease.emit(e)

class Danmaku(QWidget):
    onModified = pyqtSignal(str)

    def __init__(self, word, paraphrase, y, show_paraphrase = None, color = None):
        super().__init__()
        self._word = word
        self._paraphrase = paraphrase
        self._stop_move = False
        self._show_detail = False

        self.modified = False
        # self._show_paraphrase = show_paraphrase \
        #     if show_paraphrase is not None else \
        #     utils.get_setting("danmaku_default_show_paraphrase")
        # self._color = color if color is not None else \
        #     utils.get_setting("danmaku_default_color")
        self._cleared = False

        self.setWindowFlags(
            self.windowFlags() |
            Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint |
            Qt.ToolTip |
            Qt.X11BypassWindowManagerHint  # for gnome
        )
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.initUI()
        self.initPosition(y)

        # self.installEventFilter(self)

    # def eventFilter(self, o, e):
    #     # due to flag `X11BypassWindowManagerHint`, event `WindowDeactivate` doesn't work
    #     if e.type() == QEvent.WindowDeactivate:
    #         self._show_detail = False
    #         self._stop_move = False
    #         self.setWindowOpacity(0.5)
    #         self._continenter.hide()
    #         return False

    #     return super().eventFilter(o, e)

    @property
    def show_paraphrase(self):
        return self._show_paraphrase

    @show_paraphrase.setter
    def show_paraphrase(self, value):
        self._show_paraphrase = value
        self.modified = True
        self.onModified.emit('show_paraphrase')

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value
        self.modified = True
        self.onModified.emit('color')

    @property
    def cleared(self):
        return self._cleared

    @cleared.setter
    def cleared(self, value):
        self._cleared = value
        self.modified = True
        self.onModified.emit('cleared')

    def setWordQss(self):
        pass
        # bg_color, font_color = utils.COLORS[self.color]
        # self._word_label.setStyleSheet(f"QLabel{{background-color:rgb({bg_color}); color:rgb({font_color}); padding:5; border-radius:6px}}")

    def initUI(self):
        # self.setWindowOpacity(utils.get_setting("danmaku_transparency"))

        word = WordLabel(self._word)
        # if self.show_paraphrase:
        #     word.setText(word.text() + " " + self._paraphrase.splitlines()[0])

        word.onEnter.connect(self.enterWordEvent)
        word.onLeave.connect(self.leaveWordEvent)
        word.onMousePress.connect(self.mousePressWordEvent)
        word.onMouseMove.connect(self.mouseMoveWordEvent)
        word.onMouseRelease.connect(self.mouseReleaseWordEvent)

        self._word_label = word

        head = QHBoxLayout()
        head.addWidget(word)
        head.addStretch(1)
        word.setFont(QFont("Consolas", 18))

        body = QVBoxLayout()
        body.addLayout(head)
        self.setLayout(body)

        self.setWordQss()

        continenter = QWidget(self)
        continenter.setObjectName("continenter")
        continenter.setStyleSheet("#continenter{background-color:white; padding:5; border-radius:6px}")
        continenter.hide()
        self._continenter = continenter

        body.addStretch(1)
        body.addWidget(continenter)

        detail = QVBoxLayout()
        continenter.setLayout(detail)

        paraphrase = QLabel(self._paraphrase)
        paraphrase.setFont(QFont("Consolas", 15))
        paraphrase.setStyleSheet("QLabel{color:black;}")
        paraphrase.setWordWrap(True)
        paraphrase.setMaximumWidth(300)

        detail.addWidget(paraphrase)

        rbtns = QHBoxLayout()
        # for name, (color, _) in utils.COLORS.items():
        #     rbtn = QRadioButton(None)
        #     qss = f"""
        #     QRadioButton::indicator {{ width:13px; height:13px; background-color:rgb({color}); border: 2px solid rgb({color}); }}
        #     QRadioButton::indicator:checked {{ border: 2px solid black; }}
        #     """
        #     rbtn.setStyleSheet(qss)
        #     rbtn.setChecked(name == self.color)
        #     rbtn.toggled.connect(self.clickColor)
        #     rbtn.color = name

        #     rbtns.addWidget(rbtn)

        detail.addLayout(rbtns)

        btns = QHBoxLayout()

        clear = QPushButton("Clear")
        clear.setStyleSheet("QPushButton{color:black;}")
        clear.clicked.connect(self.clickClear)
        btns.addWidget(clear)

        # switch_paraphrase = QPushButton("Hide Paraphrase" if self.show_paraphrase else "Show Paraphrase")
        # switch_paraphrase.setStyleSheet("QPushButton{color:black;}")
        # switch_paraphrase.clicked.connect(self.clickSwitch)
        # btns.addWidget(switch_paraphrase)
        # self._switch_paraphrase = switch_paraphrase

        detail.addLayout(btns)
        self._clear = clear

        self.show()

    def clickColor(self, e):
        if e:
            sender = self.sender()
            self.color = sender.color
            self.setWordQss()

    def clickClear(self):
        self.cleared = not self.cleared
        self._clear.setText("Redo" if self.cleared else "Clear")

    def clickSwitch(self):
        self.show_paraphrase = not self.show_paraphrase
        if self.show_paraphrase:
            self._word_label.setText(self._word + " " + self._paraphrase.splitlines()[0])
        else:
            self._word_label.setText(self._word)

        self._switch_paraphrase.setText("Hide Paraphrase" if self.show_paraphrase else "Show Paraphrase")

    def enterWordEvent(self):
        self.setWindowOpacity(1)

    def leaveWordEvent(self):
        pass
        # if not self._show_detail:
        #     self.setWindowOpacity(utils.get_setting("danmaku_transparency"))

    def mousePressWordEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._press_point = e.globalPos() - self.pos()
            self._press_start = e.globalPos()
            e.accept()

    def mouseMoveWordEvent(self, e):
        if e.buttons() & Qt.LeftButton:
            self.move(e.globalPos() - self._press_point)
            e.accept()

    def mouseReleaseWordEvent(self, e):
        if e.button() != Qt.LeftButton:
            return
        if (e.globalPos() - self._press_start).manhattanLength() < 10:
            self._show_detail = not self._show_detail
            if self._show_detail:
                self._stop_move = True
                self._continenter.show()
            else:
                self._stop_move = False
                self._continenter.hide()
                self.adjustSize()

    def initPosition(self, y):
        self._timer = QTimer(self)
        self._timer.setTimerType(Qt.PreciseTimer)
        self._timer.timeout.connect(self.update)
        # speed = utils.get_setting("danmaku_speed")
        speed = 0.1
        delta = 1
        while round(delta / speed) < 17:
            delta += 1

        self._timer.start(round(delta / speed))
        self._delta = delta

        w = QDesktopWidget().availableGeometry().width()
        self.move(w, y)

    def update(self):
        if self._stop_move: return
        x = self.x() - self._delta
        self.move(x, self.y())
        if x < -self.width():
            self._timer.stop()
            self.close()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Danmaku('good',"好的",2)
    w.show()
    sys.exit(app.exec_())

在这里插入图片描述

笔记二:字幕有字体背景且更容易点击单词

from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon, QFont, QMouseEvent
from PyQt5.QtCore import QTimer, Qt, QEvent, pyqtSignal, QRect
import utils
import sys

class WordLabel(QLabel):
    onEnter = pyqtSignal()
    onLeave = pyqtSignal()
    onMousePress = pyqtSignal(QMouseEvent)
    onMouseMove = pyqtSignal(QMouseEvent)
    onMouseRelease = pyqtSignal(QMouseEvent)

    def __init__(self, *argv, **kw):
        super().__init__(*argv, **kw)

        self.installEventFilter(self)

    def enterEvent(self, e):
        self.onEnter.emit()

    def leaveEvent(self, e):
        self.onLeave.emit()

    def mousePressEvent(self, e):
        self.onMousePress.emit(e)

    def mouseMoveEvent(self, e):
        self.onMouseMove.emit(e)

    def mouseReleaseEvent(self, e):
        self.onMouseRelease.emit(e)

class Danmaku(QWidget):
    onModified = pyqtSignal(str)

    def __init__(self, word, paraphrase, y, show_paraphrase = None, color = None):
        super().__init__()
        self._word = word
        self._paraphrase = paraphrase
        self._stop_move = False
        self._show_detail = False

        self.modified = False
        # self._show_paraphrase = show_paraphrase \
        #     if show_paraphrase is not None else \
        #     utils.get_setting("danmaku_default_show_paraphrase")
        self._color = color if color is not None else \
            utils.get_setting("danmaku_default_color")
        self._cleared = False

        self.setWindowFlags(
            self.windowFlags() |
            Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint |
            Qt.ToolTip |
            Qt.X11BypassWindowManagerHint  # for gnome
        )
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.initUI()
        self.initPosition(y)

        # self.installEventFilter(self)

    # def eventFilter(self, o, e):
    #     # due to flag `X11BypassWindowManagerHint`, event `WindowDeactivate` doesn't work
    #     if e.type() == QEvent.WindowDeactivate:
    #         self._show_detail = False
    #         self._stop_move = False
    #         self.setWindowOpacity(0.5)
    #         self._continenter.hide()
    #         return False

    #     return super().eventFilter(o, e)

    @property
    def show_paraphrase(self):
        return self._show_paraphrase

    @show_paraphrase.setter
    def show_paraphrase(self, value):
        self._show_paraphrase = value
        self.modified = True
        self.onModified.emit('show_paraphrase')

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value
        self.modified = True
        self.onModified.emit('color')

    @property
    def cleared(self):
        return self._cleared

    @cleared.setter
    def cleared(self, value):
        self._cleared = value
        self.modified = True
        self.onModified.emit('cleared')

    def setWordQss(self):
        pass
        bg_color, font_color = utils.COLORS[self.color]
        self._word_label.setStyleSheet(f"QLabel{{background-color:rgb({bg_color}); color:rgb({font_color}); padding:5; border-radius:6px}}")

    def initUI(self):
        # self.setWindowOpacity(utils.get_setting("danmaku_transparency"))

        word = WordLabel(self._word)
        # if self.show_paraphrase:
        #     word.setText(word.text() + " " + self._paraphrase.splitlines()[0])

        word.onEnter.connect(self.enterWordEvent)
        word.onLeave.connect(self.leaveWordEvent)
        word.onMousePress.connect(self.mousePressWordEvent)
        word.onMouseMove.connect(self.mouseMoveWordEvent)
        word.onMouseRelease.connect(self.mouseReleaseWordEvent)

        self._word_label = word

        head = QHBoxLayout()
        head.addWidget(word)
        head.addStretch(1)
        word.setFont(QFont("Consolas", 18))

        body = QVBoxLayout()
        body.addLayout(head)
        self.setLayout(body)

        self.setWordQss()

        continenter = QWidget(self)
        continenter.setObjectName("continenter")
        continenter.setStyleSheet("#continenter{background-color:white; padding:5; border-radius:6px}")
        continenter.hide()
        self._continenter = continenter

        body.addStretch(1)
        body.addWidget(continenter)

        detail = QVBoxLayout()
        continenter.setLayout(detail)

        paraphrase = QLabel(self._paraphrase)
        paraphrase.setFont(QFont("Consolas", 15))
        paraphrase.setStyleSheet("QLabel{color:black;}")
        paraphrase.setWordWrap(True)
        paraphrase.setMaximumWidth(300)

        detail.addWidget(paraphrase)

        rbtns = QHBoxLayout()
        # for name, (color, _) in utils.COLORS.items():
        #     rbtn = QRadioButton(None)
        #     qss = f"""
        #     QRadioButton::indicator {{ width:13px; height:13px; background-color:rgb({color}); border: 2px solid rgb({color}); }}
        #     QRadioButton::indicator:checked {{ border: 2px solid black; }}
        #     """
        #     rbtn.setStyleSheet(qss)
        #     rbtn.setChecked(name == self.color)
        #     rbtn.toggled.connect(self.clickColor)
        #     rbtn.color = name

        #     rbtns.addWidget(rbtn)

        detail.addLayout(rbtns)

        btns = QHBoxLayout()

        clear = QPushButton("Clear")
        clear.setStyleSheet("QPushButton{color:black;}")
        clear.clicked.connect(self.clickClear)
        btns.addWidget(clear)

        # switch_paraphrase = QPushButton("Hide Paraphrase" if self.show_paraphrase else "Show Paraphrase")
        # switch_paraphrase.setStyleSheet("QPushButton{color:black;}")
        # switch_paraphrase.clicked.connect(self.clickSwitch)
        # btns.addWidget(switch_paraphrase)
        # self._switch_paraphrase = switch_paraphrase

        detail.addLayout(btns)
        self._clear = clear

        self.show()

    def clickColor(self, e):
        if e:
            sender = self.sender()
            self.color = sender.color
            self.setWordQss()

    def clickClear(self):
        self.cleared = not self.cleared
        self._clear.setText("Redo" if self.cleared else "Clear")

    def clickSwitch(self):
        self.show_paraphrase = not self.show_paraphrase
        if self.show_paraphrase:
            self._word_label.setText(self._word + " " + self._paraphrase.splitlines()[0])
        else:
            self._word_label.setText(self._word)

        self._switch_paraphrase.setText("Hide Paraphrase" if self.show_paraphrase else "Show Paraphrase")

    def enterWordEvent(self):
        self.setWindowOpacity(1)

    def leaveWordEvent(self):
        pass
        # if not self._show_detail:
        #     self.setWindowOpacity(utils.get_setting("danmaku_transparency"))

    def mousePressWordEvent(self, e):
        if e.button() == Qt.LeftButton:
            self._press_point = e.globalPos() - self.pos()
            self._press_start = e.globalPos()
            e.accept()

    def mouseMoveWordEvent(self, e):
        if e.buttons() & Qt.LeftButton:
            self.move(e.globalPos() - self._press_point)
            e.accept()

    def mouseReleaseWordEvent(self, e):
        if e.button() != Qt.LeftButton:
            return
        if (e.globalPos() - self._press_start).manhattanLength() < 10:
            self._show_detail = not self._show_detail
            if self._show_detail:
                self._stop_move = True
                self._continenter.show()
            else:
                self._stop_move = False
                self._continenter.hide()
                self.adjustSize()

    def initPosition(self, y):
        self._timer = QTimer(self)
        self._timer.setTimerType(Qt.PreciseTimer)
        self._timer.timeout.connect(self.update)
        # speed = utils.get_setting("danmaku_speed")
        speed = 0.1
        delta = 1
        while round(delta / speed) < 17:
            delta += 1

        self._timer.start(round(delta / speed))
        self._delta = delta

        w = QDesktopWidget().availableGeometry().width()
        self.move(w, y)

    def update(self):
        if self._stop_move: return
        x = self.x() - self._delta
        self.move(x, self.y())
        if x < -self.width():
            self._timer.stop()
            self.close()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Danmaku('good',"好的",2)
    w.show()
    sys.exit(app.exec_())

在这里插入图片描述

笔记三:PyQt窗口贴别隐藏

import sys,random
from PyQt5.QtGui import QPalette,QColor
from PyQt5.QtWidgets import QWidget,QVBoxLayout,QPushButton,\
    QDesktopWidget,QApplication
from PyQt5.QtCore import Qt,QRect,QEvent,QPoint
from PyQt5.Qt import QCursor,QPropertyAnimation

SCREEN_WEIGHT = 1920
SCREEN_HEIGHT = 1080
WINDOW_WEIGHT = 300
WINDOW_HEIGHT = 600
class Ui_Form(QWidget):
    def __init__(self):
        self.moved = False
        super(Ui_Form,self).__init__()
        self.setupUi()
        self.resize(WINDOW_WEIGHT, WINDOW_HEIGHT)
        self.show()
    def setupUi(self):
        self.setWindowFlags(Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint
                            | Qt.Tool) # 去掉标题栏
        self.widget = QWidget()
        self.Layout = QVBoxLayout(self.widget)
        self.Layout.setContentsMargins(0,0,0,0)
        self.setLayout(self.Layout)
        self.setWindowFlag(Qt.Tool)
        self.main_widget = QWidget()
        self.Layout.addWidget(self.main_widget)
        self.paint = QPushButton(self.main_widget)
        self.paint.setText("改变颜色")
        self.paint.move(QPoint(120,200))
        self.paint.clicked.connect(self.Painting)
        self.exit = QPushButton(self.main_widget)
        self.exit.setText("  退出  ")
        self.exit.move(QPoint(120,400))
        self.exit.clicked.connect(lambda:exit(0))
        self.setStyleSheet('''
                QPushButton {
                color: rgb(137, 221, 255);
                background-color: rgb(37, 121, 255);
                border-style:none;
                border:1px solid #3f3f3f;
                padding:5px;
                min-height:20px;
                border-radius:15px;
            }
            ''')
    def Painting(self):
        color = random.choice(["CCFFFF","CC6699","CC99FF","99CCFF"])
        palette1 = QPalette()
        palette1.setColor(self.backgroundRole(),
                          QColor("#{}".format(color))) # 改变窗体颜色
        self.setPalette(palette1)
    def enterEvent(self, event):
        self.hide_or_show('show', event)
    def leaveEvent(self, event):
        self.hide_or_show('hide', event)
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.dragPosition = event.globalPos() - self.frameGeometry(
            ).topLeft()
            QApplication.postEvent(self, QEvent(174))
            event.accept()
    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            try:
                self.move(event.globalPos() - self.dragPosition)
                event.accept()
            except:pass
    #def mouseReleaseEvent(self, event):
        #self.moved = True
        #self.hide_or_show('show', event)
    def hide_or_show(self, mode, event):
        pos = self.frameGeometry().topLeft()
        if mode == 'show' and self.moved:
            if pos.x() + WINDOW_WEIGHT >= SCREEN_WEIGHT:  # 右侧显示
                self.startAnimation(SCREEN_WEIGHT - WINDOW_WEIGHT + 2, pos.y())
                event.accept()
                self.moved = False
            elif pos.x() <= 0:  # 左侧显示
                self.startAnimation(0,pos.y())
                event.accept()
                self.moved = False
            elif pos.y() <= 0: # 顶层显示
                self.startAnimation(pos.x(),0)
                event.accept()
                self.moved = False
        elif mode == 'hide':
            if pos.x() + WINDOW_WEIGHT >= SCREEN_WEIGHT:  # 右侧隐藏
                self.startAnimation(SCREEN_WEIGHT - 2,pos.y())
                event.accept()
                self.moved = True
            elif pos.x() <= 2:  # 左侧隐藏
                self.startAnimation(2 - WINDOW_WEIGHT,pos.y())
                event.accept()
                self.moved = True
            elif pos.y() <= 2: # 顶层隐藏
                self.startAnimation(pos.x(),2 - WINDOW_HEIGHT)
                event.accept()
                self.moved = True
    def startAnimation(self,width,height):
        animation = QPropertyAnimation(self,b"geometry",self)
        startpos = self.geometry()
        animation.setDuration(200)
        newpos = QRect(width,height,startpos.width(),startpos.height())
        animation.setEndValue(newpos)
        animation.start()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = Ui_Form()
    sys.exit(app.exec_())

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值