zoukankan      html  css  js  c++  java
  • PyQt:个性化登录界面模仿QQ登录

    写在前面

      写了一个登录界面的demo,类似QQ的,写的自己喜欢的样式,贴一下代码,先上效果,如下

    陈述

      PyQt5+Python3.5.2

      login.py是里登录的主界面loginWnd类,Header.py里是标题栏和整个窗口的类,我在login.py里面创建了application对象。(其实也没有必要分成两个文件来写,直接按照我这一篇的处理就ok的     https://www.cnblogs.com/jyroy/p/9461317.html,本人话多

      主要是效果实现为主,没有写登录的槽函数啥的,代码中写了解释

    效果

    代码

      1 #login.py
      2 
      3 #!/usr/bin/env python
      4 # -*- coding:utf-8 -*-
      5 # Author: jyroy
      6 import sys
      7 
      8 from PyQt5.QtCore import QSize
      9 from PyQt5.QtWidgets import QApplication
     10 from PyQt5.QtCore import Qt
     11 from PyQt5.QtWidgets import QComboBox
     12 from PyQt5.QtWidgets import QGridLayout
     13 from PyQt5.QtWidgets import QLineEdit
     14 from PyQt5.QtWidgets import QLabel
     15 from PyQt5.QtGui import QIcon
     16 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit
     17 from Header import TitleBar,FramelessWindow
     18 from qtpy import QtGui
     19 
     20 StyleSheet = """
     21 /*最小化最大化关闭按钮通用默认背景*/
     22 #buttonMinimum,#buttonMaximum,#buttonClose {
     23     border: none;
     24 }
     25 /*悬停*/
     26 #buttonMinimum:hover,#buttonMaximum:hover {
     27 
     28     color: white;
     29 }
     30 #buttonClose:hover {
     31     color: white;
     32 }
     33 /*鼠标按下不放*/
     34 #buttonMinimum:pressed,#buttonMaximum:pressed {
     35 
     36 }
     37 #buttonClose:pressed {
     38     color: white;
     39 
     40 }
     41 """   #标题栏Button的样式
     42 
     43 StyleSheet_2 = """
     44 QComboBox{
     45         height: 20px;
     46         border-radius: 4px;
     47         border: 1px solid rgb(111, 156, 207);
     48         background: white;
     49 }
     50 QComboBox:enabled{
     51         color: grey;
     52 }
     53 QComboBox:!enabled {
     54         color: rgb(80, 80, 80);
     55 }
     56 QComboBox:enabled:hover, QComboBox:enabled:focus {
     57         color: rgb(51, 51, 51);
     58 }
     59 QComboBox::drop-down {
     60         background: transparent;
     61 }
     62 QComboBox::drop-down:hover {
     63         background: lightgrey;
     64 }
     65 
     66 QComboBox QAbstractItemView {
     67         border: 1px solid rgb(111, 156, 207);
     68         background: white;
     69         outline: none;
     70 }
     71 
     72  QLineEdit {
     73         border-radius: 4px;
     74         height: 20px;
     75         border: 1px solid rgb(111, 156, 207);
     76         background: white;
     77 }
     78 QLineEdit:enabled {
     79         color: rgb(84, 84, 84);
     80 }
     81 QLineEdit:enabled:hover, QLineEdit:enabled:focus {
     82         color: rgb(51, 51, 51);
     83 }
     84 QLineEdit:!enabled {
     85         color: rgb(80, 80, 80);
     86 }
     87 
     88 
     89 """   #QComobox和QLineEdite的样式
     90 
     91 StyleSheet_btn = """
     92 QPushButton{
     93     height:30px;
     94     background-color: transparent;
     95     color: grey;
     96     border: 2px solid #555555;
     97     border-radius: 6px;
     98 
     99 }
    100 QPushButton:hover {
    101     background-color: white;
    102     border-radius: 6px;
    103 
    104 }
    105 """  #登录Button的样式
    106 
    107 class loginWnd(QWidget):
    108     '''登录窗口'''
    109     def __init__(self, *args, **kwargs):
    110         super(loginWnd, self).__init__()
    111         self._layout = QVBoxLayout(spacing=0)
    112         self._layout.setContentsMargins(0, 0, 0, 0)
    113         self.setAutoFillBackground(True)
    114         self.setWindowOpacity(0.1)
    115 
    116         self.setLayout(self._layout)
    117 
    118         self._setup_ui()
    119 
    120     def _setup_ui(self):
    121 
    122         self.main_layout = QGridLayout()
    123 
    124         self.main_layout.setAlignment(Qt.AlignCenter)
    125 
    126         name_label = QLabel('用户名')
    127         name_label.setStyleSheet("color:grey;")
    128         passwd_label = QLabel('密码')
    129         passwd_label.setStyleSheet("color:grey;")
    130 
    131         name_box = QComboBox()
    132         name_box.setEditable(True)
    133         passwd_box = QLineEdit()
    134         passwd_box.setEchoMode(QLineEdit.Password)
    135         name_box.setStyleSheet(StyleSheet_2)
    136         passwd_box.setStyleSheet(StyleSheet_2)
    137 
    138         label = QLabel()
    139 
    140         login_btn = QPushButton("登录")
    141         login_btn.setStyleSheet(StyleSheet_btn)
    142 
    143         self.main_layout.addWidget(name_label,0,0,1,1)
    144         self.main_layout.addWidget(passwd_label,1,0,1,1)
    145         self.main_layout.addWidget(name_box,0,1,1,2)
    146         self.main_layout.addWidget(passwd_box,1,1,1, 2)
    147         self.main_layout.addWidget(label,3,0,1,3)
    148         self.main_layout.addWidget(login_btn,4,0,1,3)
    149 
    150         self._layout.addLayout(self.main_layout)
    151 
    152 def main():
    153     ''':return:'''
    154 
    155     app = QApplication(sys.argv)
    156 
    157     mainWnd = FramelessWindow()
    158     mainWnd.setWindowTitle('欢迎窗口login')
    159     mainWnd.setWindowIcon(QIcon('Qt.ico'))
    160     mainWnd.setFixedSize(QSize(500,400))  #因为这里固定了大小,所以窗口的大小没有办法任意调整,想要使resizeWidget函数生效的话要把这里去掉,自己调节布局和窗口大小
    161     mainWnd.setWidget(loginWnd(mainWnd))  # 把自己的窗口添加进来
    162     mainWnd.show()
    163 
    164     app.exec()
    165 
    166 if __name__ == '__main__':
    167     main()
      1 #Header.py
      2 
      3 #!/usr/bin/env python
      4 # -*- coding:utf-8 -*-
      5 # Author: jyroy
      6 
      7 from PyQt5.QtCore import Qt, pyqtSignal, QPoint
      8 from PyQt5.QtGui import QFont, QEnterEvent, QPainter, QColor, QPen
      9 from PyQt5.QtWidgets import QHBoxLayout, QLabel,QSpacerItem, QSizePolicy
     10 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit
     11 from qtpy import QtGui
     12 
     13 StyleSheet = """
     14 /*最小化最大化关闭按钮通用默认背景*/
     15 #buttonMinimum,#buttonMaximum,#buttonClose {
     16     border: none;
     17 }
     18 #buttonClose,#buttonMaximum,#buttonMinimum{
     19     color:grey;
     20 }
     21 /*悬停*/
     22 #buttonMinimum:hover,#buttonMaximum:hover {
     23     color: white;
     24 }
     25 #buttonClose:hover {
     26     color: white;
     27 }
     28 /*鼠标按下不放*/
     29 #buttonMinimum:pressed,#buttonMaximum:pressed {
     30     color:grey;
     31 }
     32 #buttonClose:pressed {
     33     color: white;
     34 
     35 }
     36 """
     37 class TitleBar(QWidget):
     38 
     39     # 窗口最小化信号
     40     windowMinimumed = pyqtSignal()
     41     # 窗口最大化信号
     42     windowMaximumed = pyqtSignal()
     43     # 窗口还原信号
     44     windowNormaled = pyqtSignal()
     45     # 窗口关闭信号
     46     windowClosed = pyqtSignal()
     47     # 窗口移动
     48     windowMoved = pyqtSignal(QPoint)
     49 
     50     def __init__(self, *args, **kwargs):
     51         super(TitleBar, self).__init__(*args, **kwargs)
     52         self.setStyleSheet(StyleSheet)
     53         self.mPos = None
     54         self.iconSize = 20  # 图标的默认大小
     55         # 布局
     56         layout = QHBoxLayout(self, spacing=0)
     57         layout.setContentsMargins(0, 0, 0, 0)
     58         # 窗口图标
     59         self.iconLabel = QLabel(self)
     60 #         self.iconLabel.setScaledContents(True)
     61         layout.addWidget(self.iconLabel)
     62         # 窗口标题
     63         self.titleLabel = QLabel(self)
     64         self.titleLabel.setStyleSheet("color:grey")
     65         self.titleLabel.setMargin(2)
     66         layout.addWidget(self.titleLabel)
     67         # 中间伸缩条
     68         layout.addSpacerItem(QSpacerItem(
     69             40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
     70         # 利用Webdings字体来显示图标
     71         font = self.font() or QFont()
     72         font.setFamily('Webdings')
     73         # 最小化按钮
     74         self.buttonMinimum = QPushButton(
     75             '0', self, clicked=self.windowMinimumed.emit, font=font, objectName='buttonMinimum')
     76         layout.addWidget(self.buttonMinimum)
     77         # 最大化/还原按钮
     78         self.buttonMaximum = QPushButton(
     79             '1', self, clicked=self.showMaximized, font=font, objectName='buttonMaximum')
     80         layout.addWidget(self.buttonMaximum)
     81         # 关闭按钮
     82         self.buttonClose = QPushButton(
     83             'r', self, clicked=self.windowClosed.emit, font=font, objectName='buttonClose')
     84         layout.addWidget(self.buttonClose)
     85         # 初始高度
     86         self.setHeight()
     87 
     88     def showMaximized(self):
     89         if self.buttonMaximum.text() == '1':
     90             # 最大化
     91             self.buttonMaximum.setText('2')
     92             self.windowMaximumed.emit()
     93         else:  # 还原
     94             self.buttonMaximum.setText('1')
     95             self.windowNormaled.emit()
     96 
     97     def setHeight(self, height=38):
     98         """设置标题栏高度"""
     99         self.setMinimumHeight(height)
    100         self.setMaximumHeight(height)
    101         # 设置右边按钮的大小
    102         self.buttonMinimum.setMinimumSize(height, height)
    103         self.buttonMinimum.setMaximumSize(height, height)
    104         self.buttonMaximum.setMinimumSize(height, height)
    105         self.buttonMaximum.setMaximumSize(height, height)
    106         self.buttonClose.setMinimumSize(height, height)
    107         self.buttonClose.setMaximumSize(height, height)
    108 
    109     def setTitle(self, title):
    110         """设置标题"""
    111         self.titleLabel.setText(title)
    112 
    113     def setIcon(self, icon):
    114         """设置图标"""
    115         self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize))
    116 
    117     def setIconSize(self, size):
    118         """设置图标大小"""
    119         self.iconSize = size
    120 
    121     def enterEvent(self, event):
    122         self.setCursor(Qt.ArrowCursor)
    123         super(TitleBar, self).enterEvent(event)
    124 
    125     def mouseDoubleClickEvent(self, event):
    126         super(TitleBar, self).mouseDoubleClickEvent(event)
    127         self.showMaximized()
    128 
    129     def mousePressEvent(self, event):
    130         """鼠标点击事件"""
    131         if event.button() == Qt.LeftButton:
    132             self.mPos = event.pos()
    133         event.accept()
    134 
    135     def mouseReleaseEvent(self, event):
    136         '''鼠标弹起事件'''
    137         self.mPos = None
    138         event.accept()
    139 
    140     def mouseMoveEvent(self, event):
    141         if event.buttons() == Qt.LeftButton and self.mPos:
    142             self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos))
    143         event.accept()
    144 
    145 # 枚举左上右下以及四个定点
    146 Left, Top, Right, Bottom, LeftTop, RightTop, LeftBottom, RightBottom = range(8)
    147 
    148 class FramelessWindow(QWidget):
    149 
    150     # 四周边距
    151     Margins = 5
    152 
    153     def __init__(self, *args, **kwargs):
    154         super(FramelessWindow, self).__init__(*args, **kwargs)
    155         palette1 = QtGui.QPalette()
    156         palette1.setBrush(self.backgroundRole(), QtGui.QBrush(
    157             QtGui.QPixmap('D:pythoncodeqilucontestqtWholeDemo/resource/sky.jpg')))  # 设置背景图片
    158         self.setPalette(palette1)
    159         self.setAutoFillBackground(True)
    160         self.setGeometry(300, 300, 250, 150)
    161         self._pressed = False
    162         self.Direction = None
    163         # 无边框
    164         self.setWindowFlags(Qt.FramelessWindowHint)  # 隐藏边框
    165         # 鼠标跟踪
    166         self.setMouseTracking(True)
    167         # 布局
    168         layout = QVBoxLayout(self, spacing=0)
    169         layout.setContentsMargins(0,0,0,0)
    170         # 标题栏
    171         self.titleBar = TitleBar(self)
    172         layout.addWidget(self.titleBar)
    173         # 信号槽
    174         self.titleBar.windowMinimumed.connect(self.showMinimized)
    175         self.titleBar.windowMaximumed.connect(self.showMaximized)
    176         self.titleBar.windowNormaled.connect(self.showNormal)
    177         self.titleBar.windowClosed.connect(self.close)
    178         self.titleBar.windowMoved.connect(self.move)
    179         self.windowTitleChanged.connect(self.titleBar.setTitle)
    180         self.windowIconChanged.connect(self.titleBar.setIcon)
    181 
    182     def setTitleBarHeight(self, height=38):
    183         """设置标题栏高度"""
    184         self.titleBar.setHeight(height) 
    185 
    186     def setIconSize(self, size):
    187         """设置图标的大小"""
    188         self.titleBar.setIconSize(size)
    189 
    190     def setWidget(self, widget):
    191         """设置自己的控件"""
    192         if hasattr(self, '_widget'):
    193             return
    194         self._widget = widget
    195         # 设置默认背景颜色,否则由于受到父窗口的影响导致透明
    196         self._widget.setAutoFillBackground(True)
    197         self._widget.installEventFilter(self)
    198         self.layout().addWidget(self._widget)
    199 
    200     def move(self, pos):
    201         if self.windowState() == Qt.WindowMaximized or self.windowState() == Qt.WindowFullScreen:
    202             # 最大化或者全屏则不允许移动
    203             return
    204         super(FramelessWindow, self).move(pos)
    205 
    206     def showMaximized(self):
    207         """最大化,要去除上下左右边界,如果不去除则边框地方会有空隙"""
    208         super(FramelessWindow, self).showMaximized()
    209         self.layout().setContentsMargins(0, 0, 0, 0)
    210 
    211     def showNormal(self):
    212         """还原,要保留上下左右边界,否则没有边框无法调整"""
    213         super(FramelessWindow, self).showNormal()
    214         self.layout().setContentsMargins(0, 0, 0, 0)
    215 
    216     def eventFilter(self, obj, event):
    217         """事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式"""
    218         if isinstance(event, QEnterEvent):
    219             self.setCursor(Qt.ArrowCursor)
    220         return super(FramelessWindow, self).eventFilter(obj, event)
    221 
    222     def paintEvent(self, event):
    223         """由于是全透明背景窗口,重绘事件中绘制透明度为1的难以发现的边框,用于调整窗口大小"""
    224         super(FramelessWindow, self).paintEvent(event)
    225         painter = QPainter(self)
    226         painter.setPen(QPen(QColor(255, 255, 255, 1), 2 * self.Margins))
    227         painter.drawRect(self.rect())
    228 
    229     def mousePressEvent(self, event):
    230         """鼠标点击事件"""
    231         super(FramelessWindow, self).mousePressEvent(event)
    232         if event.button() == Qt.LeftButton:
    233             self._mpos = event.pos()
    234             self._pressed = True
    235 
    236     def mouseReleaseEvent(self, event):
    237         '''鼠标弹起事件'''
    238         super(FramelessWindow, self).mouseReleaseEvent(event)
    239         self._pressed = False
    240         self.Direction = None
    241 
    242     def mouseMoveEvent(self, event):
    243         """鼠标移动事件"""
    244         super(FramelessWindow, self).mouseMoveEvent(event)
    245         pos = event.pos()
    246         xPos, yPos = pos.x(), pos.y()
    247         wm, hm = self.width() - self.Margins, self.height() - self.Margins
    248         if self.isMaximized() or self.isFullScreen():
    249             self.Direction = None
    250             self.setCursor(Qt.ArrowCursor)
    251             return
    252         if event.buttons() == Qt.LeftButton and self._pressed:
    253             self._resizeWidget(pos)
    254             return
    255         if xPos <= self.Margins and yPos <= self.Margins:
    256             # 左上角
    257             self.Direction = LeftTop
    258             self.setCursor(Qt.SizeFDiagCursor)
    259         elif wm <= xPos <= self.width() and hm <= yPos <= self.height():
    260             # 右下角
    261             self.Direction = RightBottom
    262             self.setCursor(Qt.SizeFDiagCursor)
    263         elif wm <= xPos and yPos <= self.Margins:
    264             # 右上角
    265             self.Direction = RightTop
    266             self.setCursor(Qt.SizeBDiagCursor)
    267         elif xPos <= self.Margins and hm <= yPos:
    268             # 左下角
    269             self.Direction = LeftBottom
    270             self.setCursor(Qt.SizeBDiagCursor)
    271         elif 0 <= xPos <= self.Margins and self.Margins <= yPos <= hm:
    272             # 左边
    273             self.Direction = Left
    274             self.setCursor(Qt.SizeHorCursor)
    275         elif wm <= xPos <= self.width() and self.Margins <= yPos <= hm:
    276             # 右边
    277             self.Direction = Right
    278             self.setCursor(Qt.SizeHorCursor)
    279         elif self.Margins <= xPos <= wm and 0 <= yPos <= self.Margins:
    280             # 上面
    281             self.Direction = Top
    282             self.setCursor(Qt.SizeVerCursor)
    283         elif self.Margins <= xPos <= wm and hm <= yPos <= self.height():
    284             # 下面
    285             self.Direction = Bottom
    286             self.setCursor(Qt.SizeVerCursor)
    287 
    288     def _resizeWidget(self, pos):
    289         """调整窗口大小"""
    290         if self.Direction == None:
    291             return
    292         mpos = pos - self._mpos
    293         xPos, yPos = mpos.x(), mpos.y()
    294         geometry = self.geometry()
    295         x, y, w, h = geometry.x(), geometry.y(), geometry.width(), geometry.height()
    296         if self.Direction == LeftTop:  # 左上角
    297             if w - xPos > self.minimumWidth():
    298                 x += xPos
    299                 w -= xPos
    300             if h - yPos > self.minimumHeight():
    301                 y += yPos
    302                 h -= yPos
    303         elif self.Direction == RightBottom:  # 右下角
    304             if w + xPos > self.minimumWidth():
    305                 w += xPos
    306                 self._mpos = pos
    307             if h + yPos > self.minimumHeight():
    308                 h += yPos
    309                 self._mpos = pos
    310         elif self.Direction == RightTop:  # 右上角
    311             if h - yPos > self.minimumHeight():
    312                 y += yPos
    313                 h -= yPos
    314             if w + xPos > self.minimumWidth():
    315                 w += xPos
    316                 self._mpos.setX(pos.x())
    317         elif self.Direction == LeftBottom:  # 左下角
    318             if w - xPos > self.minimumWidth():
    319                 x += xPos
    320                 w -= xPos
    321             if h + yPos > self.minimumHeight():
    322                 h += yPos
    323                 self._mpos.setY(pos.y())
    324         elif self.Direction == Left:  # 左边
    325             if w - xPos > self.minimumWidth():
    326                 x += xPos
    327                 w -= xPos
    328             else:
    329                 return
    330         elif self.Direction == Right:  # 右边
    331             if w + xPos > self.minimumWidth():
    332                 w += xPos
    333                 self._mpos = pos
    334             else:
    335                 return
    336         elif self.Direction == Top:  # 上面
    337             if h - yPos > self.minimumHeight():
    338                 y += yPos
    339                 h -= yPos
    340             else:
    341                 return
    342         elif self.Direction == Bottom:  # 下面
    343             if h + yPos > self.minimumHeight():
    344                 h += yPos
    345                 self._mpos = pos
    346             else:
    347                 return
    348         self.setGeometry(x, y, w, h)
  • 相关阅读:
    我对“错排问题”的理解
    洛谷P1144 最短路计数 题解 无权图的最短路计数(广搜)
    洛谷P1714 切蛋糕 题解 单调队列
    洛谷P6040 「ACOI2020」课后期末考试滑溜滑溜补习班 题解 单调队列优化DP
    POJ2559 Largest Rectangle in a Histogram 题解 单调队列/单调栈 (直方图的最大矩形面积)
    洛谷P2947 向右看齐Look Up 题解 单调栈/单调队列
    洛谷P1725 琪露诺 题解 单调队列优化DP入门题
    洛谷P1886 滑动窗口 题解 单调队列
    洛谷P2952 牛线Cow Line 题解 双端队列deque的使用
    多线程交互,访问数据,如果访问到了就不访问了,怎么 避免重读?
  • 原文地址:https://www.cnblogs.com/jyroy/p/9465034.html
Copyright © 2011-2022 走看看