PyQt自定义标题栏(界面美化,附C++和Python源码)

  • Post author:
  • Post category:python




1. 简述

这几天给老师做项目用到了PyQt5,说一些自己的想法,用python写qt界面我觉得如果懂C++和Qt是最好的,因为PyQt5没有相应的官方文档,我做项目时都是对照着Qt的C++文档做的,而且二者基本差别不大,只是一些小细节有略微不同而已,当然不懂Qt直接做也可以,但是这难免很费劲。

废话就说这些,下面就稍微说下Qt界面美化,后面附有C++和python的代码链接,下面是效果图:

在这里插入图片描述



2.代码说明

做这个自定义的标题栏,主要实现以下几个功能:

  1. 关闭,最小化,复原三个按钮的基本功能;
  2. 双击标题栏窗口最大化或者缩小;
  3. 鼠标点击拖动窗口;
  4. 显示标题和图标



(1)主窗口

先说一下主界面的代码,主要就是两行:

	self.setWindowFlags(Qt.FramelessWindowHint)		#隐藏主窗口边界
	self.lay.setSpacing(0);							#去除控件间的距离
	self.lay.setContentsMargins(0, 0, 0, 0)

这里的self就是主窗口QMainWindow,lay就是一个QVBoxLayout的布局,使用参数Qt.FramelessWindowHint可以让主窗口不现实边框,只显示客户区,我们就可以自己绘制标题栏的内容。

下面两行设为0是为了取消控件之间的间距,不这样的话很难设置空间的布局,会使得窗口很丑。

主窗口还有一个就是SetStyleSheet就是设置界面的样式,这个后面再说。



(2)标题栏

标题栏主要包含五个空间两个label:图标label、标题label,三个按钮:最小化按钮、复原按钮和关闭按钮。三个按钮分别通过connect链接下面几个槽即可。另外代码中的self.win是主窗口的引用,如果使用self.window()获取的有些时候无法准确的获取到对应的值而使得功能失效,我这里选择用一个变量保存来进行操作,当然也可以通过另外两种方式:

  1. 通过信号槽将鼠标事件发送出去
  2. 通过实践过滤器eventFliter在主窗口中为标题栏Widget安装事件进一步处理。

我这里有个小问题,因为self.win是用来存放主界面的,因此标题栏窗口不能独立的存在,如果强行将主窗口设为None创建的话,窗口能显示但是最大化等功能不能执行,这个可以自行修改,这到不难,判断下win是否为None,是的话对本窗口操作即可。

	#最小化窗口
	def ShowMininizedWindow(self):
        self.win.showMinimized()
	
	#最大化窗口
    def ShowMaximizedWindow(self):
        self.win.showMaximized()

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

	#关闭窗口
    def CloseWindow(self):
        self.win.close()

事件触发,鼠标单击、双击和移动的事件。

	def mouseDoubleClickEvent(self, event):
        self.ShowRestoreWindow()
        return QWidget().mouseDoubleClickEvent(event)

    def mousePressEvent(self, event):
        self.isPressed = True
        self.startPos = event.globalPos()	#记录鼠标点击的位置
        return QWidget().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        self.isPressed = False
        return QWidget().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.isPressed:
            if self.win.isMaximized:
                self.win.showNormal()
                
			#计算窗口应该移动的距离
            movePos = event.globalPos() - self.startPos
            self.startPos = event.globalPos()
            self.win.move(self.win.pos() + movePos)

        return QWidget().mouseMoveEvent(event)



(3)完整代码

代码中的图标,等一下参数是我自己定义的,可以在最后的源代码中查看。

	import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from default import *

class TitleBar(QWidget):
    def __init__(self, parent):
        super(TitleBar, self).__init__()
        self.win = parent
        self.InitializeWindow()

    def InitializeWindow(self):
        self.isPressed = False
        self.setFixedHeight(TITLE_BAR_HEIGHT)
        self.InitializeViews()
        pass

    def InitializeViews(self):
        self.iconLabel = QLabel(self)
        self.titleLabel = QLabel(self)

        self.minButton = QPushButton(self)
        self.restoreButton = QPushButton(self)
        self.closeButton = QPushButton(self)

        self.minButton.setFixedSize(TITLE_BUTTON_SIZE, TITLE_BUTTON_SIZE);
        self.restoreButton.setFixedSize(TITLE_BUTTON_SIZE, TITLE_BUTTON_SIZE);
        self.closeButton.setFixedSize(TITLE_BUTTON_SIZE, TITLE_BUTTON_SIZE);

        self.iconLabel.setFixedSize(TITLE_LABEL_SIZE, TITLE_LABEL_SIZE);
        self.titleLabel.setFixedHeight(TITLE_LABEL_SIZE);

        self.iconLabel.setAlignment(Qt.AlignCenter);
        self.titleLabel.setAlignment(Qt.AlignCenter);

        self.minButton.setIcon(QIcon(TITLE_MIN_ICON));
        self.restoreButton.setIcon(QIcon(TITLE_RESTORE_ICON));
        self.closeButton.setIcon(QIcon(TITLE_CLS_ICON));

        self.minButton.clicked.connect(self.ShowMininizedWindow)
        self.restoreButton.clicked.connect(self.ShowRestoreWindow)
        self.closeButton.clicked.connect(self.CloseWindow)

        self.lay = QHBoxLayout(self)
        self.setLayout(self.lay)

        self.lay.setSpacing(0)
        self.lay.setContentsMargins(0, 0, 0, 0)

        self.lay.addWidget(self.iconLabel)
        self.lay.addWidget(self.titleLabel)
        self.lay.addWidget(self.minButton)
        self.lay.addWidget(self.restoreButton)
        self.lay.addWidget(self.closeButton)

    def ShowMininizedWindow(self):
        self.win.showMinimized()

    def ShowMaximizedWindow(self):
        self.window.showMaximized()

    def ShowRestoreWindow(self):
        if self.win.isMaximized():
            self.win.showNormal()
        else:
            self.win.showMaximized()

    def CloseWindow(self):
        self.win.close()

    def SetTitle(self, str):
        self.titleLabel.setText(str)

    def SetIcon(self, pix):
        self.iconLabel.setPixmap(pix.scaled(self.iconLabel.size() - QSize(TITLE_ICON_MAG, TITLE_ICON_MAG)))

    def mouseDoubleClickEvent(self, event):
        self.ShowRestoreWindow()
        return QWidget().mouseDoubleClickEvent(event)

    def mousePressEvent(self, event):
        self.isPressed = True
        self.startPos = event.globalPos()
        return QWidget().mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        self.isPressed = False
        return QWidget().mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self.isPressed:
            if self.win.isMaximized:
                self.win.showNormal()

            movePos = event.globalPos() - self.startPos
            self.startPos = event.globalPos()
            self.win.move(self.win.pos() + movePos)

        return QWidget().mouseMoveEvent(event)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = TitleBar(None)
    win.show()
    sys.exit(app.exec_())
    pass



(4)美化(QSS)

Qss是Qt的界面样式,直接挪用Qt的就可以,官方参考地址:

QSS Help


颜色是从Visual Studio中取的。

QWidget
{
    background-color:#313034;
    color:#f1f1f1;
    font-size:12px;
    border:2px solid #423f48;
    font: "Tlwg Typo";
    margin:0px;

}

QMainWindow
{
}

QPushButton
{
    border:none;
    width:35px;
}

QPushButton:hover
{
    background-color:#423f48;
}

QPushButton:pressed
{
    background-color:#444444;
}

QLabel
{
    background-color:#2A292B;
    border:none;
}



3.源代码链接

里面有C++的和Python的代码,C++的使用Visual Studio+Qt写的。


源代码链接



版权声明:本文为GrayOnDream原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。