PyQt:個性化登陸界面模仿QQ登陸

寫在前面

  寫了一個登陸界面的demo,相似QQ的,寫的本身喜歡的樣式,貼一下代碼,先上效果,以下html

陳述

  PyQt5+Python3.5.2python

  login.py是裏登陸的主界面loginWnd類,Header.py裏是標題欄和整個窗口的類,我在login.py裏面建立了application對象。(其實也沒有必要分紅兩個文件來寫,直接按照我這一篇的處理就ok的     https://www.cnblogs.com/jyroy/p/9461317.html,本人話多app

  主要是效果實現爲主,沒有寫登陸的槽函數啥的,代碼中寫了解釋less

效果

 

代碼

  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:\python\code\qilucontest\qt\WholeDemo/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)
相關文章
相關標籤/搜索