PyQT 单词弹幕桌面生成!

先来看一波效果图

主要功能介绍:

1.用户可以指定桌面滑动速度,单词数目 

2. 鼠标悬浮弹幕停止, 中文释义弹窗显示

3. 点击弹幕, 弹幕永久停止, 再次点击,激活滑动状态

 

下面我们来看看主要代码吧

WORD_LIST = []
TEXT_COLOR = ['#426F42', '#7F00FF', '#7FFF00', '#70DBDB', '#DB7093', '#A68064', '#2F2F4F', '#23238E',
              '#4D4DFF', '#FF6EC7', '#00009C', '#EBC79E', '#CFB53B', '#FF7F00', '#FF2400', '#DB70DB']
LOOP_TIME = 20000
LOOP_COUNT = 0

def load_word_file():
    file = 'danci.md'
    if not os.path.exists(file):
        with open(file, 'w', encoding='utf8') as f:
            pass
    with open(file, 'r', encoding='utf8') as file:
        lines = file.readlines()
        for line in lines:
            if line.strip():
                WORD_LIST.append(line)

class Tip(QListWidget):
    font = QFont('宋体', 20, 50)
    def __init__(self,list_text,parent, x=0, y=0):
       
        try:
            super().__init__(parent)
            self.setGeometry(x, y, 150, 150)
            self.addItems(list_text)
            self.adjustSize()
            self.setStyleSheet("QListWidget{background-color: rgba(51, 62, 80, 0.8);border-radius:10px;color:rgb(189, 192, 197);font-size:20px;} " \
                               "QScrollBar:vertical{width:8px;background:rgba(51, 62, 80, 0.8); background-color:rgba(51, 62, 80, 0.8);}"\
                               "QScrollBar:horizontal{height:8px;background:rgba(51, 62, 80, 0.8);background-color:rgba(51, 62, 80, 0.8);}")
        except Exception as e:
            print(str(e))


class DButton(QPushButton):
    font = QFont('宋体', 20, 50)
    _state = 0
    
    def __init__(self, parent, text, y=0, color=QColor(255, 255, 255)):
        cur_text = text.split('[')[0]
        super().__init__(cur_text, parent)
        self.text = cur_text
        descript = text[(len(self.text)):]
        self.tip = descript.split('')
        self.parent = parent
        self.setCursor(Qt.PointingHandCursor)
        self.setFont(self.font)
        self.setFixedHeight(50)
        self.setposY(y)
        self.adjustSize() # 宽度自适应
        text_color = random.sample(TEXT_COLOR, 1)
        style_sheet = "QPushButton{background-color: rgba(97%,80%,9%,1%);border:none;color:" + text_color[0] + "}"
        self.setStyleSheet(style_sheet)
        self.anim2 = QPropertyAnimation(self, b'pos')
        self.anim2.setDuration(LOOP_TIME)
        start = random.randint(0, 100)
        window_width = QDesktopWidget().screenGeometry().width()
        self.anim2.setStartValue(QPoint(window_width - start, self.posY))
        
        self.anim2.setEndValue(QPoint(0, self.posY))
        self.anim2.setEasingCurve(QEasingCurve.Linear)
        self.anim2.finished.connect(self.end)
        if LOOP_COUNT:
            self.anim2.setLoopCount(LOOP_COUNT)
        self.anim2.start()
        
    def end(self):
        self.deleteLater()
        # self.parent.resume_move()
        self.parent = None
        self = None

        
    def enterEvent(self, event):
        if not self._state: 
            self.anim2.pause()
            self.show_tips()
     
        
    def leaveEvent(self, event):
        # time.sleep(0.5)
        if not self._state:        
            self.anim2.resume()
            self._tip.deleteLater()

    def mouseReleaseEvent(self, event):
        if not self._state: 
            self._state = 1
        else:
            self._state = 0

    def show_tips(self):
        list_text = self.tip
        tip = Tip(list_text, self.parent,self.x() + self.width(), self.y() )
        self._tip = tip
        self._tip.show()

    def setposY(self, y):
        self.posY = y

class DanmuWindow(QWidget):
     _signal = pyqtSignal(str)
     max_height = 0
     def __init__(self, q=Queue()):
        super().__init__()
        
        self._signal.connect(self.mySignal)
        self.max_height = QDesktopWidget().screenGeometry().height() - 100
        
        self.setGeometry(0, 0, QDesktopWidget().screenGeometry().width(),
                         self.max_height)
        
        self.q = q
        self.th = threading.Thread(target=self.start_move)
        self.th.setDaemon(True)  # 守护线程
        self.th.start()

     def mySignal(self, text):
        danmu = DButton(self, text, self.get_random_height(), QColor(255, 255, 255))
        danmu.show()

     def get_random_height(self):
         height = random.randint(0, self.max_height - 300)
         mod = height % 50
         if mod:
             height = height - mod
         return height
        
     def resume_move(self):
         pass
         # self.mySignal(WORD_LIST.pop(0))
         
     def start_move(self):
         while True:
             for i in range(1):
                 if WORD_LIST:
                     self._signal.emit(WORD_LIST.pop(0))
             time.sleep(5)

记住 窗体运行时候 要设置透明,无边框模式

另外为了方便使用 我写了一个桌面程序去运行该项目

效果图如下:

class Ui_Form(QWidget):
    win = None
    th = None
    def __init__(self):
        super(Ui_Form, self).__init__()
        self.setupUi()
        
    def setupUi(self):
        self.setObjectName("Form")
        self.resize(640, 273)
        self.title_widget = QtWidgets.QWidget(self)
        self.title_widget.setObjectName("Title")
        
        self.pushButton = QtWidgets.QPushButton(self)
        self.pushButton.setGeometry(QtCore.QRect(280, 220, 89, 25))
        self.pushButton.setObjectName("pushButton")

        self.label_tip = QtWidgets.QLabel(self)
        self.label_tip.setGeometry(QtCore.QRect(380, 220, 300, 25))
        self.label_tip.setObjectName("label_tip")
        self.label_status = QtWidgets.QLabel(self)
        self.label_status.setGeometry(QtCore.QRect(20, 240, 300, 25))
        self.label_status.setObjectName("label_tip")

        self.pushButton_2 = QtWidgets.QPushButton(self)
        self.pushButton_2.setGeometry(QtCore.QRect(40, 90, 89, 25))
        self.pushButton_2.setObjectName("pushButton_2")
        self.progressBar = QtWidgets.QProgressBar(self)
        self.progressBar.setGeometry(QtCore.QRect(40, 140, 560, 23)) 
        self.progressBar.setObjectName("progressBar")
        self.label_3 = QtWidgets.QLabel(self)
        self.label_3.setGeometry(QtCore.QRect(40, 40, 67, 17))
        self.label_3.setObjectName("label_3")
        self.lineEdit_2 = QtWidgets.QLineEdit(self)
        self.lineEdit_2.setGeometry(QtCore.QRect(110, 40, 113, 21))
        self.lineEdit_2.setCursorPosition(0)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.label = QtWidgets.QLabel(self)
        self.label.setGeometry(QtCore.QRect(260, 40, 67, 17))
        self.label.setObjectName("label")
        self.lineEdit = QtWidgets.QLineEdit(self)
        self.lineEdit.setGeometry(QtCore.QRect(330, 40, 61, 21))
        self.lineEdit.setObjectName("lineEdit")
        self.label_2 = QtWidgets.QLabel(self)
        self.label_2.setGeometry(QtCore.QRect(410, 40, 67, 17))
        self.label_2.setObjectName("label_2")
        self.lineEdit_3 = QtWidgets.QLineEdit(self)
        self.lineEdit_3.setGeometry(QtCore.QRect(480, 40, 61, 21))
        self.lineEdit_3.setObjectName("lineEdit_3")

        self.left_close = QtWidgets.QPushButton(self.title_widget) # 关闭按钮
        self.left_visit = QtWidgets.QPushButton(self.title_widget) # 空白按钮
        self.left_mini = QtWidgets.QPushButton(self.title_widget)  # 最小化按钮
        self.left_close.setFixedSize(15,15) # 设置关闭按钮的大小
        self.left_visit.setFixedSize(15, 15)  # 设置按钮大小
        self.left_mini.setFixedSize(15, 15) # 设置最小化按钮大小
        self.left_close.setGeometry(QtCore.QRect(615, 5, 15, 15))
        self.left_visit.setGeometry(QtCore.QRect(585, 5, 15, 15))
        self.left_mini.setGeometry(QtCore.QRect(555, 5, 15, 15))

        self.add_event()

        self.retranslateUi()
        

        self.setChildStyleSheet()
        self.setWindowIcon(QIcon('hot.ico'))  # 增加icon图标
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint) # 隐藏边框
       
        

        QtCore.QMetaObject.connectSlotsByName(self)
       

    def setChildStyleSheet(self):


        self.setStyleSheet('''QWidget#Form{background:rgba(51, 62, 80, 0.8);} QLabel{color:#fff;font-size:14px;}QLineEdit{border:1px solid gray;}''')
        self.title_widget.setStyleSheet('''QWidget#Title{background:rgba(51, 62, 80, 1);}''')
        self.left_close.setStyleSheet('''QPushButton{background:#F76677;border-radius:5px;color:#fff;text-align:center}QPushButton:hover{background:red;}''')
        self.left_visit.setStyleSheet('''QPushButton{background:#F7D674;border-radius:5px;color:#fff;text-align:center}QPushButton:hover{background:yellow;}''')
        self.left_mini.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;color:#fff;text-align:center}QPushButton:hover{background:green;}''')
        self.pushButton_2.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;color:#fff;text-align:center}QPushButton:hover{background:green;}''')
        self.pushButton.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;color:#fff;text-align:center}QPushButton:hover{background:green;}''')
        self.progressBar.setStyleSheet("QProgressBar{"\
               "border: none;color:#fff; font-size:14px;text-align:center;"\
               "background: rgba(248,248,255,180);"\
               "border-radius: 10px; }"\
               "QProgressBar::chunk:enabled {"\
               "border-radius: 10px; "\
               "background: #6DDF6D; border:none;}")
        self.label_tip.setStyleSheet('''QLabel{font-size:12px; color:gray}''')
        self.label_status.setStyleSheet('''QLabel{font-size:12px; color:gray}''')
        
    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("Form", "单词桌面"))
        self.pushButton.setText(_translate("Form", "启动"))
        self.pushButton_2.setText(_translate("Form", "加载资源"))
        self.label_3.setText(_translate("Form", "单词数目"))
        self.lineEdit_2.setPlaceholderText(_translate("Form", "100"))
        self.label.setText(_translate("Form", "滚动时间"))
        self.lineEdit.setPlaceholderText(_translate("Form", "20"))
        self.label_2.setText(_translate("Form", "循环次数"))
        self.lineEdit_3.setPlaceholderText(_translate("Form", "0"))
        self.progressBar.setProperty("value", 0)

        self.label_tip.setText('记得加载资源哦')
        self.label_status.setText('小贴士: 加载完资源下次就不用再加载啦')

        #self.left_mini.setText(_translate("Form", "-"))
        #self.left_visit.setText(_translate("Form", "□"))
        #self.left_close.setText(_translate("Form", "×"))

    def add_event(self):
        self.left_close.clicked.connect(self.close_window)
        self.left_mini.clicked.connect(self.show_mininized_window)
        self.left_visit.clicked.connect(self.show_restore_window)
        self.pushButton_2.clicked.connect(self.load_resource)
        self.pushButton.clicked.connect(self.start)
    
    def show_mininized_window(self):
        self.showMinimized()
    
    #最大化窗口
    def show_maximized_window(self):
        self.showMaximized()

    #复原窗口
    def show_restore_window(self):
        if self.isMaximized():
            self.showNormal()
        else:
            self.showMaximized()

    #关闭窗口
    def close_window(self):
        self.win.close()
        sys.exit(app.exec_())
        self.close()
        
    def mousePressEvent(self, event):
        if event.button()==QtCore.Qt.LeftButton:
            self.m_flag=True
            self.m_Position=event.globalPos()-self.pos() #获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(QtCore.Qt.OpenHandCursor))  #更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if QtCore.Qt.LeftButton and self.m_flag:  
            self.move(QMouseEvent.globalPos()-self.m_Position)#更改窗口位置
            QMouseEvent.accept()
            
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag=False
        self.setCursor(QCursor(QtCore.Qt.ArrowCursor))

    def load_resource(self):
        total = self.lineEdit_2.text()
        total = total or 100
        
        t = threading.Thread(target=load_resource,args=(int(total), self.progressBar,  self.pushButton_2, self.label_tip), daemon=True)
        t.setDaemon(True)
        #t.daemon=True
        t.start()

    def start(self):
        self.win.close()
        loop = self.lineEdit_3.text()
        loop = loop or 0
        times = self.lineEdit.text()
        times = times or 20
        init_loop(int(times) * 1000, int(loop))
        load_word_file()
        self.win.show()

如果还有什么问题不明白的话:

可以加q:940120528

欢迎互相讨论

 

posted @ 2019-09-02 18:58  绯叶阿卡丽  阅读(612)  评论(0编辑  收藏  举报