一:QWidget 繼承的類:
查看一個控件的父類,
(一):可以直接點入到內置文件中查看
它是繼承QObject 還要一個:QPaintDevice 的!
(二):通過保留屬性__base__
注:如果使用mro() ,則是整個的繼承鏈條!
還要注意:它的父類QObject 中所有的功能,它都可以使用!
二:QWidget (所有可視控件的基類):
它其實也是個矩形!
三:QWiget的功能作用:
(一):QWidget 控件之控件的創建:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() #注: 這里括號里放的不是繼承而是指定父控件 9 10 11 #QWidget 類的初始化函數,如果我們不給它指定父控件的話, 12 # 那么它就自己成為了頂層窗口,頂層窗口是不會自己出現的,需要我們自己show() 13 # def __init__(self, parent=None, flags, Qt_WindowFlags=None, Qt_WindowType=None, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__ 14 # pass 15 16 window.show() 17 18 19 20 #3,進入消息循環 21 sys.exit(app.exec_())
當一個控件沒有父控件的時候,它會被包裝成一個框架(有標題欄啊,等等......)
但是,我們可以通過init函數中第二個參數flags 來設置的, 后面再講(待放鏈接)
(二):QWidget控件之大小位置:
關於控件的坐標系統:
API之獲取:
最后一句話:空間顯示完畢之后,具體的位置或尺寸才會正確:
驗證代碼如下:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.move(100,100) 11 window.resize(200,200) 12 13 print(window.geometry()) #輸出: PyQt5.QtCore.QRect(100, 100, 200, 200) 14 15 16 window.show() 17 print(window.geometry()) #輸出: PyQt5.QtCore.QRect(101, 131, 200, 200) 18 19 20 #3,進入消息循環 21 sys.exit(app.exec_())
所以,要獲取控件的尺寸,一定要在控件顯示完畢之后再去獲取!
API之設置:
move 是操控的x,y 也就是pos ,包含框架。
resize 操控的是用戶區域,不包含框架(但是太小的話,也不行)
setGeometry() 也是用戶區域,
但是此時會有問題:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 # window.setGeometry(0,0,150,150) # 這樣不行,需要放在展示后面 11 12 window.show() 13 window.setGeometry(0,0,150,150) 14 15 16 #3,進入消息循環 17 sys.exit(app.exec_())
adjustSize() 根據內容自適應大小

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.move(200,200) 11 window.resize(500,500) 12 13 label = QLabel(window) 14 label.setText("hello world") 15 label.move(100,100) 16 label.setStyleSheet("background-color:cyan;") #為了更清晰看到具體的區域 17 18 def addContent(): 19 new_content = label.text() +"hello world" 20 label.setText(new_content) 21 label.resize(label.width()+100,label.height()) 22 23 24 btn = QPushButton(window) 25 btn.setText("增加內容") 26 btn.move(200,200) 27 btn.clicked.connect(addContent)

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.move(200,200) 11 window.resize(500,500) 12 13 label = QLabel(window) 14 label.setText("hello world") 15 label.move(100,100) 16 label.setStyleSheet("background-color:cyan;") #為了更清晰看到具體的區域 17 18 def addContent(): 19 new_content = label.text() +"hello world" 20 label.setText(new_content) 21 22 btn = QPushButton(window) 23 btn.setText("增加內容") 24 btn.move(200,200) 25 btn.clicked.connect(addContent)
效果:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.move(200,200) 11 window.resize(500,500) 12 13 label = QLabel(window) 14 label.setText("hello world") 15 label.move(100,100) 16 label.setStyleSheet("background-color:cyan;") #為了更清晰看到具體的區域 17 18 def addContent(): 19 new_content = label.text() +"hello world" 20 label.setText(new_content) 21 # label.resize(label.width()+100,label.height()) 笨方法 22 label.adjustSize() 23 24 25 btn = QPushButton(window) 26 btn.setText("增加內容") 27 btn.move(200,200) 28 btn.clicked.connect(addContent) 29 30 31 32 window.show() 33 34 35 #3,進入消息循環 36 sys.exit(app.exec_())
setFixedSize() 設置固定尺寸:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.move(200,200) 11 # window.resize(500,500) # 這不是固定大小,可以拖拽 12 window.setFixedSize(500,500) # 這才是固定大小 13 14 label = QLabel(window) 15 label.setText("hello world") 16 label.move(100,100) 17 18 19 window.show() 20 21 22 #3,進入消息循環 23 sys.exit(app.exec_())
大小位置之案例:
案例一:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.resize(500,500) 11 window.move(300,300) 12 13 14 window.show() 15 16 17 #3,進入消息循環 18 sys.exit(app.exec_())
案例二:
首先我們先看下關於子控件的顯示問題:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 w = QWidget(window) 11 w.resize(100,100) 12 w.setStyleSheet("background-color:red;") 13 14 15 window.show() #顯示子控件時是這樣的,它必須要在頂層窗口的前面, 16 #因為當頂層窗口顯示時,它會遍歷它身上的所有的子控件 17 window.resize(500,500) 18 window.move(300,300) 19 20 #3,進入消息循環 21 sys.exit(app.exec_())
但是如果子控件的代碼放在了頂層窗口的后面,就沒法顯示了,因為已經遍歷完了,不會再遍歷它了。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 11 12 window.show() #顯示子控件時是這樣的,它必須要在頂層窗口的前面, 13 #因為當頂層窗口顯示時,它會遍歷它身上的所有的子控件 14 window.resize(500,500) 15 window.move(300,300) 16 17 w = QWidget(window) 18 w.resize(100,100) 19 w.setStyleSheet("background-color:red;") 20 21 22 #3,進入消息循環 23 sys.exit(app.exec_())
如何解決,要自己手動調用才能顯示子控件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 11 12 window.show() #顯示子控件時是這樣的,它必須要在頂層窗口的前面, 13 #因為當頂層窗口顯示時,它會遍歷它身上的所有的子控件 14 window.resize(500,500) 15 window.move(300,300) 16 17 w = QWidget(window) 18 w.resize(100,100) 19 w.setStyleSheet("background-color:red;") 20 w.show() # 自己手動展示 21 22 #3,進入消息循環 23 sys.exit(app.exec_())
難點是關於九宮格的布局:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.show() 11 12 window.resize(500,500) 13 window.move(300,300) 14 15 16 #總控件的個數 17 widget_count = 9 18 19 #有多少列 20 column_count = 3 21 22 #一個控件的寬度 23 widget_width = window.width()/column_count 24 25 #row_count 是有多少行 26 row_count = (widget_count-1)//column_count +1 27 28 #一個控件的高度 29 widget_height = window.height()/row_count 30 31 for i in range(widget_count): 32 w = QWidget(window) 33 w.resize(widget_width,widget_height) 34 x,y = divmod(i,column_count) 35 w.move(widget_width*y,widget_height*x) 36 w.setStyleSheet("background-color:red;border:1px solid yellow") 37 w.show() 38 39 #3,進入消息循環 40 sys.exit(app.exec_())
效果:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #創建控件 8 window = QWidget() 9 10 window.show() 11 12 window.resize(500,500) 13 window.move(300,300) 14 15 16 #總控件的個數 17 widget_count = 50 18 19 #有多少列 20 column_count = 4 21 22 #一個控件的寬度 23 widget_width = window.width()/column_count 24 25 #row_count 是有多少行 26 row_count = (widget_count-1)//column_count +1 27 28 #一個控件的高度 29 widget_height = window.height()/row_count 30 31 for i in range(widget_count): 32 w = QWidget(window) 33 w.resize(widget_width,widget_height) 34 x,y = divmod(i,column_count) 35 w.move(widget_width*y,widget_height*x) 36 w.setStyleSheet("background-color:red;border:1px solid yellow") 37 w.show() 38 39 #3,進入消息循環 40 sys.exit(app.exec_())
效果:
另:

import math import sys from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QPushButton class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("QT的學習") self.resize(500,500) self.num = 33 self.col = 3 self.set_ui() def set_ui(self): temp = 0 width = self.width()/self.col height = self.height()/math.ceil(self.num / self.col) for rIdx in range(math.ceil(self.num / self.col)): for cIdx in range(self.col): temp += 1 if temp >self.num: break w = QWidget(self) w.resize(width, height) w.move(cIdx*width,rIdx*height) w.setStyleSheet("background-color:red;border:1px solid yellow;") # self.startTimer(1000) # def timerEvent(self, evt): # self.setGeometry(100,100,self.num,self.num) # self.num += 50 if __name__ == '__main__': app =QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
(三):QWidget控件之最大和最小尺寸:
直接上案例(api 比較簡單)

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("最小尺寸和最大尺寸的限定") 14 # window.resize(500,500) 15 window.setMinimumSize(200,200) #當然也可單獨限制高和寬 16 window.setMaximumSize(600,600) 17 18 19 #展示控件 20 window.show() 21 22 #3,進入消息循環 23 sys.exit(app.exec_())
問題?
此時能否通過代碼來修改尺寸呢?
答案也是不行的。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("最小尺寸和最大尺寸的限定") 14 # window.resize(500,500) 15 window.setMinimumSize(200,200) #當然也可單獨限制高和寬 16 window.setMaximumSize(500,500) 17 18 window.resize(1000,1000) #通過代碼也是無法修改的 19 20 #展示控件 21 window.show() 22 23 #3,進入消息循環 24 sys.exit(app.exec_())
(四):QWidget控件之內容邊距:
內容區域:(文本區域)
內容區域默認是整個標簽,可以通過獲取內容區域來查看:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("內容邊距的設定") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("Life is short,I learn Python!") 19 label.resize(300,300) 20 label.setStyleSheet("background-color:cyan;") 21 22 print(label.contentsRect()) 23 24 25 #展示控件 26 window.show() 27 28 29 #3,進入消息循環 30 sys.exit(app.exec_()) 31 ''' 32 輸出: 33 PyQt5.QtCore.QRect(0, 0, 300, 300) 34 '''
再次查看內容區域:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("內容邊距的設定") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("Life is short,I learn Python!") 19 label.resize(300,300) 20 label.setStyleSheet("background-color:cyan;border:1px solid red") 21 22 print(label.contentsRect()) 23 24 25 #展示控件 26 window.show() 27 28 29 #3,進入消息循環 30 sys.exit(app.exec_()) 31 ''' 32 輸出: 33 PyQt5.QtCore.QRect(1, 1, 298, 298) #之所以是因為border 占用了內容區域 34 '''
內容區域是可以進行控制的,可以通過設置內容邊距來實現。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("內容邊距的設定") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("Life is short,I learn Python!") 19 label.resize(300,300) 20 label.setStyleSheet("background-color:cyan;border:1px solid red") 21 22 label.setContentsMargins(100,0,0,0) # 設置內容邊距,四個參數是邊距順時針,從左開始 23 print(label.contentsRect()) 24 25 26 #展示控件 27 window.show() 28 29 30 #3,進入消息循環 31 sys.exit(app.exec_()) 32 ''' 33 輸出: 34 PyQt5.QtCore.QRect(100, 0, 200, 300) 35 '''
默認文本顯示是水平靠左,豎直居中的!
當然,各個邊的內容邊距,我們可以通過getContentsMargins() 來獲得,

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("內容邊距的設定") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("Life is short,I learn Python!") 19 label.resize(300,300) 20 label.setStyleSheet("background-color:cyan;border:1px solid red") 21 22 label.setContentsMargins(100,0,100,0) 23 # print(label.contentsRect()) 24 25 print(label.getContentsMargins()) #打印各個邊內容邊距設置的具體值 26 27 #展示控件 28 window.show() 29 30 31 #3,進入消息循環 32 sys.exit(app.exec_()) 33 ''' 34 輸出: 35 (100, 0, 100, 0) 36 '''
(五):QWidget控件之事件消息:
API之顯示和關閉事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def showEvent(self, QShowEvent): #具體傳過來的事件是什么后面說 16 print("窗口被展示出來") 17 18 def closeEvent(self, QCloseEvent): #點×調用它 19 print("窗口被關閉了") 20 21 if __name__ == '__main__': 22 app =QApplication(sys.argv) 23 24 window = Window() 25 window.show() 26 27 sys.exit(app.exec_())
API之移動事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def moveEvent(self, QMoveEvent): 16 print("窗口被移動了") 17 18 if __name__ == '__main__': 19 app =QApplication(sys.argv) 20 21 window = Window() 22 window.show() 23 24 sys.exit(app.exec_())
API之調整大小事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def resizeEvent(self, QResizeEvent): 16 print("窗口改變了尺寸大小") 17 18 if __name__ == '__main__': 19 app =QApplication(sys.argv) 20 21 window = Window() 22 window.show() 23 24 sys.exit(app.exec_())
這里要注意的是,窗口移動僅僅指的是窗口的左上角坐標改變,
而調整大小是整個形狀大小改變,二者是不同的。
API之鼠標事件:
鼠標事件之進入和離開事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def enterEvent(self, QEvent): 16 print("鼠標進入") 17 18 def leaveEvent(self, QEvent): 19 print("鼠標離開") 20 21 if __name__ == '__main__': 22 app =QApplication(sys.argv) 23 24 window = Window() 25 window.show() 26 27 sys.exit(app.exec_())
它就可以用做當鼠標在不同位置的時候,給我們呈現不同的樣式的應用場景!
例如,鼠標進入給顯示黃色,離開顯示綠色。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def enterEvent(self, QEvent): 16 print("鼠標進入") 17 self.setStyleSheet("background-color:yellow;") 18 19 def leaveEvent(self, QEvent): 20 print("鼠標離開") 21 self.setStyleSheet("background-color:green;") 22 23 if __name__ == '__main__': 24 app =QApplication(sys.argv) 25 26 window = Window() 27 window.show() 28 29 sys.exit(app.exec_())
鼠標事件之左鍵按下和釋放(按下/釋放==單擊)事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def mousePressEvent(self, QMouseEvent): 16 print("鼠標被按下了") 17 18 def mouseReleaseEvent(self, QMouseEvent): 19 print("鼠標被釋放了") 20 21 if __name__ == '__main__': 22 app =QApplication(sys.argv) 23 24 window = Window() 25 window.show() 26 27 sys.exit(app.exec_())
鼠標事件之左鍵雙擊事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def mouseDoubleClickEvent(self, QMouseEvent): 16 print("鼠標被雙擊了") 17 18 19 if __name__ == '__main__': 20 app =QApplication(sys.argv) 21 22 window = Window() 23 window.show() 24 25 sys.exit(app.exec_())
鼠標事件之移動事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def mouseMoveEvent(self, QMouseEvent): 16 print("鼠標移動了") 17 18 if __name__ == '__main__': 19 app =QApplication(sys.argv) 20 21 window = Window() 22 window.show() 23 24 sys.exit(app.exec_())
設置追蹤后,沒有按下也可以出發移動事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 self.setMouseTracking(True) #設置鼠標追蹤 11 12 13 def set_ui(self): 14 pass 15 16 def mouseMoveEvent(self, QMouseEvent): 17 print("鼠標移動了") 18 19 if __name__ == '__main__': 20 app =QApplication(sys.argv) 21 22 window = Window() 23 24 window.show() 25 26 sys.exit(app.exec_())
API之鍵盤事件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("QWidget 之事件的api 之顯示關閉的學習") 8 self.resize(400,400) 9 self.set_ui() 10 self.setMouseTracking(True) #設置鼠標追蹤 11 12 13 def set_ui(self): 14 pass 15 16 def keyPressEvent(self, QKeyEvent): 17 print("鍵盤上某個鍵被按下了") 18 19 def keyReleaseEvent(self, QKeyEvent): 20 print("鍵盤上某個鍵被釋放了") 21 22 23 24 25 if __name__ == '__main__': 26 app =QApplication(sys.argv) 27 28 window = Window() 29 30 window.show() 31 32 sys.exit(app.exec_())
具體哪個按鍵,我們可以對事件進行判斷,這里先不說。
API之焦點事件:
某個控件,獲得了焦點,比如,用戶輸入,輸入到的是獲得焦點的輸入框,而不是另外一個輸入框。
API之拖拽事件:
將文件直接拖拽到當前的窗口中,例如,直接將.py 文件拓展到cmd 命令行中。
API之繪制事件:
我們之所以可以看到控件,就是因為繪制事件。所以,如果,我們想自定義個控件的形狀,就可以在這里完成。
API之改變事件:
API之右鍵菜單事件:
API之輸入法事件:
事件之應用場景:
補充:事件的轉發(傳遞):
此時,假設窗口中有兩個按鈕,二者是父子關系,
假設,現在鼠標點擊觸發了事件,但是兒子中沒有實現相應的方法,這時這個事件不會被立即丟棄,而是去看它的父親中有沒有實現相應的方法,如果實現就發給父親,這就是事件的轉發。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 class Label(QLabel): 12 def mousePressEvent(self, QMouseEvent): 13 print("標簽控件被按下") 14 15 #1,創建app 16 app = QApplication(sys.argv) 17 18 19 #2,控件的操作: 20 #創建控件 21 window = Window() 22 mid_window = (window) 23 mid_window.resize(300,300) 24 mid_window.setStyleSheet("background-color:red;") #此時,它不起作用,因為它這個樣式默認被取消掉了 25 26 label = Label(mid_window) 27 label.setText("我是標簽") 28 label.setStyleSheet("background-color:yellow") 29 30 31 #設置控件 32 window.setWindowTitle("事件轉發") 33 window.resize(500,500) 34 35 36 37 #展示控件 38 window.show() 39 40 #3,進入消息循環 41 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 class Label(QLabel): 12 def mousePressEvent(self, QMouseEvent): 13 print("標簽控件被按下") 14 15 #1,創建app 16 app = QApplication(sys.argv) 17 18 19 #2,控件的操作: 20 #創建控件 21 window = Window() 22 23 mid_window = MidWindow(window) 24 mid_window.resize(300,300) 25 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 26 mid_window.setStyleSheet("background-color:red;") 27 28 label = Label(mid_window) 29 label.setText("我是標簽") 30 label.setStyleSheet("background-color:yellow") 31 label.move(100,100) 32 33 #設置控件 34 window.setWindowTitle("事件轉發") 35 window.resize(500,500) 36 37 38 39 #展示控件 40 window.show() 41 42 #3,進入消息循環 43 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 class Label(QLabel): 12 pass 13 14 #1,創建app 15 app = QApplication(sys.argv) 16 17 18 #2,控件的操作: 19 #創建控件 20 window = Window() 21 22 mid_window = MidWindow(window) 23 mid_window.resize(300,300) 24 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 25 mid_window.setStyleSheet("background-color:red;") 26 27 label = Label(mid_window) 28 label.setText("我是標簽") 29 label.setStyleSheet("background-color:yellow") 30 label.move(100,100) 31 32 #設置控件 33 window.setWindowTitle("事件轉發") 34 window.resize(500,500) 35 36 37 38 #展示控件 39 window.show() 40 41 #3,進入消息循環 42 sys.exit(app.exec_())
這個時候是會將事件轉發給它的父控件的,注意是父控件,不是父對象。
如果將中間控件的方法也給它去掉之后,那么會繼續轉發到上層父控件!

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 12 class Label(QLabel): 13 def mousePressEvent(self, QMouseEvent): 14 print("標簽窗口-按下") 15 16 #1,創建app 17 app = QApplication(sys.argv) 18 19 20 #2,控件的操作: 21 #創建控件 22 window = Window() 23 24 mid_window = MidWindow(window) 25 mid_window.resize(300,300) 26 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 27 mid_window.setStyleSheet("background-color:red;") 28 29 label = QLabel(mid_window) # 注意,這行是QLabel 30 label.setText("我是標簽") 31 label.setStyleSheet("background-color:yellow") 32 label.move(100,100) 33 34 btn = QPushButton(mid_window) 35 btn.setText("我是按鈕") 36 btn.setStyleSheet("background-color:yellow;") 37 btn.move(50,50) 38 39 40 41 #設置控件 42 window.setWindowTitle("事件轉發") 43 window.resize(500,500) 44 45 46 47 #展示控件 48 window.show() 49 50 #3,進入消息循環 51 sys.exit(app.exec_())
上面這段代碼要說明的是:
當我們點擊按鈕時候,它是不會觸發中間窗口的,但是點擊標簽時它是會觸發中間窗口。
這說明了按鈕的QPushButton () 內部是有方法來處理相應的點擊的,但是標簽QLabel是沒有相應的方法來處理的。
這也正說明了QPushButton 就是用來被點擊的,而QLabel 的天生的才能只是用來展示內容的。
而且就算是有方法存在也不行,必須對事件對象作出處理,否則還是會往上傳。如下代碼:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 12 class Label(QLabel): 13 def mousePressEvent(self, QMouseEvent): 14 # print("標簽窗口-按下") 15 pass # 此時雖然有這個方法,但是並為對QMouseEvent 對象作出處理 16 17 #1,創建app 18 app = QApplication(sys.argv) 19 20 21 #2,控件的操作: 22 #創建控件 23 window = Window() 24 25 mid_window = MidWindow(window) 26 mid_window.resize(300,300) 27 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 28 mid_window.setStyleSheet("background-color:red;") 29 30 label = Label(mid_window) 31 label.setText("我是標簽") 32 label.setStyleSheet("background-color:yellow") 33 label.move(100,100) 34 35 btn = QPushButton(mid_window) 36 btn.setText("我是按鈕") 37 btn.setStyleSheet("background-color:yellow;") 38 btn.move(50,50) 39 40 41 42 #設置控件 43 window.setWindowTitle("事件轉發") 44 window.resize(500,500) 45 46 47 48 #展示控件 49 window.show() 50 51 #3,進入消息循環 52 sys.exit(app.exec_())
此時如果點擊標簽,還是會觸發中間窗口的。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 12 class Label(QLabel): 13 # def mousePressEvent(self, QMouseEvent): 14 # print("標簽窗口-按下") 15 def mousePressEvent(self, event): 16 print("標簽窗口-按下") 17 event.accept() # 這代表的是告訴操作系統, 18 # 我們已經收到了這個事件對象,不需要再次向上轉發了 19 #1,創建app 20 app = QApplication(sys.argv) 21 22 23 #2,控件的操作: 24 #創建控件 25 window = Window() 26 27 mid_window = MidWindow(window) 28 mid_window.resize(300,300) 29 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 30 mid_window.setStyleSheet("background-color:red;") 31 32 label = Label(mid_window) 33 label.setText("我是標簽") 34 label.setStyleSheet("background-color:yellow") 35 label.move(100,100) 36 37 btn = QPushButton(mid_window) 38 btn.setText("我是按鈕") 39 btn.setStyleSheet("background-color:yellow;") 40 btn.move(50,50) 41 42 43 44 #設置控件 45 window.setWindowTitle("事件轉發") 46 window.resize(500,500) 47 48 49 50 #展示控件 51 window.show() 52 53 #3,進入消息循環 54 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 12 class Label(QLabel): 13 # def mousePressEvent(self, QMouseEvent): 14 # print("標簽窗口-按下") 15 def mousePressEvent(self, event): 16 print("標簽窗口-按下") 17 print(event.isAccepted()) # 它用來查看事件對象是否被接受了 18 #1,創建app 19 app = QApplication(sys.argv) 20 21 22 #2,控件的操作: 23 #創建控件 24 window = Window() 25 26 mid_window = MidWindow(window) 27 mid_window.resize(300,300) 28 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 29 mid_window.setStyleSheet("background-color:red;") 30 31 label = Label(mid_window) 32 label.setText("我是標簽") 33 label.setStyleSheet("background-color:yellow") 34 label.move(100,100) 35 36 btn = QPushButton(mid_window) 37 btn.setText("我是按鈕") 38 btn.setStyleSheet("background-color:yellow;") 39 btn.move(50,50) 40 41 42 43 #設置控件 44 window.setWindowTitle("事件轉發") 45 window.resize(500,500) 46 47 48 49 #展示控件 50 window.show() 51 52 #3,進入消息循環 53 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, QMouseEvent): 6 print("頂層窗口-按下") 7 class MidWindow(QWidget): 8 def mousePressEvent(self, QMouseEvent): 9 print("中間窗口-按下") 10 11 12 class Label(QLabel): 13 # def mousePressEvent(self, QMouseEvent): 14 # print("標簽窗口-按下") 15 def mousePressEvent(self, event): 16 print("標簽窗口-按下") 17 event.ignore() 18 print(event.isAccepted()) 19 20 #1,創建app 21 app = QApplication(sys.argv) 22 23 24 #2,控件的操作: 25 #創建控件 26 window = Window() 27 28 mid_window = MidWindow(window) 29 mid_window.resize(300,300) 30 mid_window.setAttribute(Qt.WA_StyledBackground,True) #這樣能是下方的qss生效 31 mid_window.setStyleSheet("background-color:red;") 32 33 label = Label(mid_window) 34 label.setText("我是標簽") 35 label.setStyleSheet("background-color:yellow") 36 label.move(100,100) 37 38 btn = QPushButton(mid_window) 39 btn.setText("我是按鈕") 40 btn.setStyleSheet("background-color:yellow;") 41 btn.move(50,50) 42 43 44 45 #設置控件 46 window.setWindowTitle("事件轉發") 47 window.resize(500,500) 48 49 50 51 #展示控件 52 window.show() 53 54 #3,進入消息循環 55 sys.exit(app.exec_()) 56 ''' 57 輸出: 58 標簽窗口-按下 (虛假的,它不代表事件對象被處理了,后面將它忽略了) 59 False 60 中間窗口-按下 61 '''
其實,我們是可以利用event.ignore() 來實現,整個父控件都去處理它這個信號的,相當於加了個標識!。
事件消息之案例:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class MyLabel(QLabel): 6 def enterEvent(self, *args, **kwargs): 7 self.setText("歡迎光臨") 8 print("鼠標進入") 9 def leaveEvent(self, *args, **kwargs): 10 self.setText("謝謝惠顧") 11 print("鼠標離開") 12 13 14 #1,創建app 15 app = QApplication(sys.argv) 16 17 18 #2,控件的操作: 19 #創建控件 20 window = QWidget() 21 22 23 #設置控件 24 window.setWindowTitle("事件的案例1") 25 window.resize(500,500) 26 27 label = MyLabel(window) 28 label.setStyleSheet("background-color:cyan") 29 label.move(200,200) 30 label.resize(100,100) 31 32 33 34 #展示控件 35 window.show() 36 37 #3,進入消息循環 38 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class MyLabel(QLabel): 6 def enterEvent(self, *args, **kwargs): 7 self.setText("歡迎光臨") 8 print("鼠標進入") 9 def leaveEvent(self, *args, **kwargs): 10 self.setText("謝謝惠顧") 11 print("鼠標離開") 12 13 # def keyPressEvent(self, QKeyEvent): 14 # 15 def keyPressEvent(self, event): 16 # event.key() == Qt.Key_Tab #所有的普通都可以這樣對比 17 #鍵分為 普通鍵和修飾鍵 ctrl alt fn 等鍵 18 if event.key() == Qt.Key_Tab: 19 print("點擊了Tab鍵") 20 21 22 #1,創建app 23 app = QApplication(sys.argv) 24 25 26 #2,控件的操作: 27 #創建控件 28 window = QWidget() 29 30 31 #設置控件 32 window.setWindowTitle("事件的案例1") 33 window.resize(500,500) 34 35 label = MyLabel(window) 36 label.setStyleSheet("background-color:cyan") 37 label.move(200,200) 38 label.resize(100,100) 39 40 41 42 #展示控件 43 window.show() 44 45 #3,進入消息循環 46 sys.exit(app.exec_())
這時不行,因為用戶按下按鍵,但是控件有多個,所以我們要設置將焦點給標簽,這樣才能捕獲到按鍵。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class MyLabel(QLabel): 6 def enterEvent(self, *args, **kwargs): 7 self.setText("歡迎光臨") 8 print("鼠標進入") 9 def leaveEvent(self, *args, **kwargs): 10 self.setText("謝謝惠顧") 11 print("鼠標離開") 12 13 # def keyPressEvent(self, QKeyEvent): 14 # 15 def keyPressEvent(self, event): 16 # event.key() == Qt.Key_Tab #所有的普通都可以這樣對比 17 #鍵分為 普通鍵和修飾鍵 ctrl alt fn 等鍵 18 if event.key() == Qt.Key_Tab: 19 print("點擊了Tab鍵") 20 21 22 #1,創建app 23 app = QApplication(sys.argv) 24 25 26 #2,控件的操作: 27 #創建控件 28 window = QWidget() 29 30 31 #設置控件 32 window.setWindowTitle("事件的案例1") 33 window.resize(500,500) 34 35 label = MyLabel(window) 36 label.setStyleSheet("background-color:cyan") 37 label.move(200,200) 38 label.resize(100,100) 39 label.grabKeyboard() # 讓label 捕獲鍵盤 40 41 42 #展示控件 43 window.show() 44 45 #3,進入消息循環 46 sys.exit(app.exec_())
下面看組合鍵,它就涉及到了修飾鍵了。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class MyLabel(QLabel): 6 def enterEvent(self, *args, **kwargs): 7 self.setText("歡迎光臨") 8 print("鼠標進入") 9 def leaveEvent(self, *args, **kwargs): 10 self.setText("謝謝惠顧") 11 print("鼠標離開") 12 13 # def keyPressEvent(self, QKeyEvent): 14 # 15 def keyPressEvent(self, event): 16 # event.key() == Qt.Key_Tab #所有的普通都可以這樣對比 17 #鍵分為 普通鍵和修飾鍵 ctrl alt fn 等鍵 18 # if event.key() == Qt.Key_Tab: 19 # print("點擊了Tab鍵") 20 if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_S: #modifiers() 是獲取修飾鍵的 21 print("用戶點擊了 Ctrl + S ") 22 23 24 #1,創建app 25 app = QApplication(sys.argv) 26 27 28 #2,控件的操作: 29 #創建控件 30 window = QWidget() 31 32 33 #設置控件 34 window.setWindowTitle("事件的案例1") 35 window.resize(500,500) 36 37 label = MyLabel(window) 38 label.setStyleSheet("background-color:cyan") 39 label.move(200,200) 40 label.resize(100,100) 41 label.grabKeyboard() # 讓label 捕獲鍵盤 42 43 44 #展示控件 45 window.show() 46 47 #3,進入消息循環 48 sys.exit(app.exec_())
如果有多個修飾鍵:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class MyLabel(QLabel): 6 def enterEvent(self, *args, **kwargs): 7 self.setText("歡迎光臨") 8 print("鼠標進入") 9 def leaveEvent(self, *args, **kwargs): 10 self.setText("謝謝惠顧") 11 print("鼠標離開") 12 13 # def keyPressEvent(self, QKeyEvent): 14 # 15 def keyPressEvent(self, event): 16 # event.key() == Qt.Key_Tab #所有的普通都可以這樣對比 17 #鍵分為 普通鍵和修飾鍵 ctrl alt fn 等鍵 18 # if event.key() == Qt.Key_Tab: 19 # print("點擊了Tab鍵") 20 if event.modifiers() == Qt.ControlModifier | Qt.ShiftModifier and event.key() == Qt.Key_A: #modifiers() 是獲取修飾鍵的 21 print("用戶點擊了 Ctrl + Shift+ A ") 22 23 24 #1,創建app 25 app = QApplication(sys.argv) 26 27 28 #2,控件的操作: 29 #創建控件 30 window = QWidget() 31 32 33 #設置控件 34 window.setWindowTitle("事件的案例1") 35 window.resize(500,500) 36 37 label = MyLabel(window) 38 label.setStyleSheet("background-color:cyan") 39 label.move(200,200) 40 label.resize(100,100) 41 label.grabKeyboard() # 讓label 捕獲鍵盤 42 43 44 #展示控件 45 window.show() 46 47 #3,進入消息循環 48 sys.exit(app.exec_())
多個修飾鍵要用按位或 | 來寫。
簡單了解按位或:
案例三:
一般情況下,用戶區是不支持拖拽的,只有標題欄那個地方可以拖拽。
它解決如下需求:
其實這里涉及到三個事件,鼠標按下,鼠標移動,鼠標松開,
這里涉及的計算問題如下:
具體計算向量的時候應該以全局的坐標為准,因為桌面不會變。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("窗口移動的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 pass 14 15 def mousePressEvent(self, event): 16 # print("鼠標按下") 17 QMouseEvent 18 #確定兩個點,鼠標第一次按下的點,和控件窗口的原始點 19 self.mouse_x = event.globalX() 20 self.mouse_y = event.globalY() 21 self.contrl_window_x = self.x() # 控件窗口的全局坐標 22 self.contrl_window_y = self.y() 23 24 25 26 def mouseMoveEvent(self, event): 27 # print("鼠標移動") 28 #計算移動向量 29 move_x = event.globalX() - self.mouse_x 30 move_y = event.globalY() - self.mouse_y 31 print(move_x,move_y) 32 #我們將這個移動向量作用到控件窗口的原始點就行了 33 self.move(self.contrl_window_x+move_x,self.contrl_window_y+move_y) 34 35 36 def mouseReleaseEvent(self, QMouseEvent): 37 print("鼠標松開") 38 39 40 if __name__ == '__main__': 41 app =QApplication(sys.argv) 42 43 window = Window() 44 window.show() 45 46 sys.exit(app.exec_())
此時一定要避免鼠標跟蹤,如果有鼠標跟蹤的話,會立馬崩潰。這時因為設置鼠標跟蹤的話,會立馬執行mouseMoveEvent() 方法,但是它的邏輯里需要先執行的是鼠標按下的操作,所以會崩。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("窗口移動的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 self.move_flag = False 12 13 14 def set_ui(self): 15 pass 16 17 def mousePressEvent(self, event): 18 self.move_flag = True 19 # print("鼠標按下") 20 QMouseEvent 21 #確定兩個點,鼠標第一次按下的點,和控件窗口的原始點 22 self.mouse_x = event.globalX() 23 self.mouse_y = event.globalY() 24 self.contrl_window_x = self.x() # 控件窗口的全局坐標 25 self.contrl_window_y = self.y() 26 27 def mouseMoveEvent(self, event): 28 if self.move_flag: 29 # print("鼠標移動") 30 #計算移動向量 31 move_x = event.globalX() - self.mouse_x 32 move_y = event.globalY() - self.mouse_y 33 print(move_x,move_y) 34 #我們將這個移動向量作用到控件窗口的原始點就行了 35 self.move(self.contrl_window_x+move_x,self.contrl_window_y+move_y) 36 37 def mouseReleaseEvent(self, QMouseEvent): 38 print("鼠標松開") 39 self.move_flag = False 40 41 42 if __name__ == '__main__': 43 app =QApplication(sys.argv) 44 45 window = Window() 46 window.setMouseTracking(True) 47 window.show() 48 49 sys.exit(app.exec_())
這時有鼠標跟蹤也沒關系了,點擊鼠標,給移動標記為True ,松開鼠標,移動標記為False .
此時,還有點小問題,就是如果這時候,我們通過鼠標的右鍵也是可以移動窗口的。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("窗口移動的學習") 8 self.resize(400,400) 9 self.set_ui() 10 11 self.move_flag = False 12 13 14 def set_ui(self): 15 pass 16 17 def mousePressEvent(self, event): 18 if event.button() == Qt.LeftButton: 19 self.move_flag = True 20 # print("鼠標按下") 21 QMouseEvent 22 #確定兩個點,鼠標第一次按下的點,和控件窗口的原始點 23 self.mouse_x = event.globalX() 24 self.mouse_y = event.globalY() 25 self.contrl_window_x = self.x() # 控件窗口的全局坐標 26 self.contrl_window_y = self.y() 27 28 def mouseMoveEvent(self, event): 29 if self.move_flag: 30 # print("鼠標移動") 31 #計算移動向量 32 move_x = event.globalX() - self.mouse_x 33 move_y = event.globalY() - self.mouse_y 34 print(move_x,move_y) 35 #我們將這個移動向量作用到控件窗口的原始點就行了 36 self.move(self.contrl_window_x+move_x,self.contrl_window_y+move_y) 37 38 def mouseReleaseEvent(self, QMouseEvent): 39 print("鼠標松開") 40 self.move_flag = False 41 42 43 if __name__ == '__main__': 44 app =QApplication(sys.argv) 45 46 window = Window() 47 window.setMouseTracking(True) 48 window.show() 49 50 sys.exit(app.exec_())
(六):QWidget控件之鼠標相關:
API 之設置鼠標形狀:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 window.setCursor(Qt.BusyCursor) #轉圈圈的樣式 17 18 19 20 #展示控件 21 window.show() 22 23 #3,進入消息循環 24 sys.exit(app.exec_())
其他的效果都可以嘗試。
也可以自定義圖標。
下面看如何自定義:
先看,鼠標變化它是對應到具體的控件的,它只有進入到相應的控件才會變化。
所以,我們在上面先創建個對象。
那么QCursor 對象如何創建,我們點進去,它需要一個QPixMap對象,
所以我們再構造一個QPixMap對象。它的構造方法是將圖片的路徑傳入即可。
圖片如下圖:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 # window.setCursor(Qt.BusyCursor) #轉圈圈的樣式 17 18 pixmap = QPixmap("d:/icon.png") 19 cursor = QCursor(pixmap) 20 window.setCursor(cursor) 21 22 #展示控件 23 window.show() 24 25 #3,進入消息循環 26 sys.exit(app.exec_())
而且圖片的大小本身都是可以調節的,可以通過pixmap 中的scaled() 進行縮放。
但是要注意,scaled() 是將縮放后的圖片通過返回值的形式給出的,

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 # window.setCursor(Qt.BusyCursor) #轉圈圈的樣式 17 18 pixmap = QPixmap("d:/icon.png") 19 new_pixmap = pixmap.scaled(50,50) #改變圖片的尺寸 #注意它是以返回值的形式給出 20 21 cursor = QCursor(new_pixmap) 22 window.setCursor(cursor) 23 24 #展示控件 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
關於鼠標的熱點位置:
可以修改為0,0, 這就是圖片的左上角成為熱點。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 # window.setCursor(Qt.BusyCursor) #轉圈圈的樣式 17 18 pixmap = QPixmap("d:/icon.png") 19 new_pixmap = pixmap.scaled(50,50) #改變圖片的尺寸 #注意它是以返回值的形式給出 20 21 cursor = QCursor(new_pixmap,0,0) # 將熱點修改為0,0 22 window.setCursor(cursor) 23 24 #展示控件 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
API 之設置重置形狀:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 # window.setCursor(Qt.BusyCursor) #轉圈圈的樣式 17 18 pixmap = QPixmap("d:/icon.png") 19 new_pixmap = pixmap.scaled(50,50) #改變圖片的尺寸 #注意它是以返回值的形式給出 20 21 cursor = QCursor(new_pixmap,0,0) # 將熱點修改為0,0 22 window.setCursor(cursor) 23 24 25 window.unsetCursor() # 重置鼠標形狀,使上面的設置失效 26 27 #展示控件 28 window.show() 29 30 #3,進入消息循環 31 sys.exit(app.exec_())
API 之獲取鼠標對象:
獲取鼠標對象,之后我們就可以獲取它的圖片,它的位置,等等。。。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("鼠標操作") 14 window.resize(500,500) 15 16 current_cursor = window.cursor() #獲取鼠標對象 17 18 print(current_cursor.pos()) #獲取鼠標的位置 PyQt5.QtCore.QPoint(748, 260) 19 # 它是相對於整個電腦屏幕的 20 21 #為了驗證這一點,我們通過下的驗證 22 current_cursor.setPos(0,0) # 這時鼠標的位置在 屏幕的左上角 23 24 25 26 #展示控件 27 window.show() 28 29 #3,進入消息循環 30 sys.exit(app.exec_())
它里面的pos() 方法獲取的位置是相對於整個屏幕的左上角而言的!
API 之鼠標跟蹤:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class MyWindow(QWidget): 5 def mouseMoveEvent(self, event): 6 print("鼠標移動了") 7 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 #2,控件的操作: 13 #創建控件 14 window = MyWindow() 15 16 window.setMouseTracking(True) #設置跟蹤 17 print(window.hasMouseTracking()) #查看鼠標是否處於跟蹤狀態 18 19 20 21 #設置控件 22 window.setWindowTitle("鼠標操作") 23 window.resize(500,500) 24 25 26 #展示控件 27 window.show() 28 29 #3,進入消息循環 30 sys.exit(app.exec_())
下面看下傳來的參數event中的東西:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class MyWindow(QWidget): 5 6 # def mouseMoveEvent(self, QMouseEvent): 7 # pass 8 def mouseMoveEvent(self, event): 9 # print("鼠標移動了",event.globalPos()) # globalPos() 是整個屏幕為准 10 print("鼠標移動了",event.localPos()) # globalPos() 是控件本身為准 11 12 13 #1,創建app 14 app = QApplication(sys.argv) 15 16 #2,控件的操作: 17 #創建控件 18 window = MyWindow() 19 20 window.setMouseTracking(True) #設置跟蹤 21 print(window.hasMouseTracking()) #查看鼠標是否處於跟蹤狀態 22 23 24 25 #設置控件 26 window.setWindowTitle("鼠標操作") 27 window.resize(500,500) 28 29 30 #展示控件 31 window.show() 32 33 #3,進入消息循環 34 sys.exit(app.exec_())
鼠標相關的案例:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def mouseMoveEvent(self, event): 7 print("鼠標移動",event.localPos()) 8 label = self.findChild(QLabel) 9 # label.move(300,300) 10 # label.move(event.localPos()) # 這樣直接放是不行的 11 # print(event.localPos()) #PyQt5.QtCore.QPointF 12 # QPointF 里面有x() y() 13 label.move(event.localPos().x(),event.localPos().y()) 14 15 16 #1,創建app 17 app = QApplication(sys.argv) 18 19 20 #2,控件的操作: 21 #創建控件 22 window = Window() 23 24 25 #設置控件 26 window.setWindowTitle("鼠標相關的案例") 27 window.resize(500,500) 28 window.setMouseTracking(True) #設置鼠標跟蹤,這樣鼠標一進去就會調用它的方法 29 #mouseMoveEvent() 了 30 31 32 #自定義鼠標 33 pixmap = QPixmap("d:/icon.png").scaled(50,50) 34 cursor = QCursor(pixmap) 35 window.setCursor(cursor) 36 37 label = QLabel(window) 38 label.setText("Life is short,I learn Python!") 39 label.move(100,100) 40 label.setStyleSheet("background-color:cyan;") 41 42 43 44 #展示控件 45 window.show() 46 47 #3,進入消息循環 48 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def __init__(self): 7 super().__init__() 8 #設置控件 9 self.setWindowTitle("鼠標相關的案例") 10 self.resize(500,500) 11 self.setMouseTracking(True) 12 self.setMyCursor() 13 self.setLabel() 14 15 16 def setMyCursor(self): 17 pixmap = QPixmap("d:/icon.png").scaled(50,50) 18 cursor = QCursor(pixmap) 19 self.setCursor(cursor) 20 def setLabel(self): 21 self.label = QLabel(self) 22 self.label.setText("Life is short,I learn Python!") 23 self.label.move(100,100) 24 self.label.setStyleSheet("background-color:cyan;") 25 26 27 def mouseMoveEvent(self, event): 28 print("鼠標移動",event.localPos()) 29 self.label.move(event.localPos().x(),event.localPos().y()) 30 31 32 #1,創建app 33 app = QApplication(sys.argv) 34 35 36 window = Window() 37 38 39 #展示控件 40 window.show() 41 42 #3,進入消息循環 43 sys.exit(app.exec_())
(七):QWidget控件之父子關系:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("父子關系的學習") 14 window.resize(500,500) 15 16 label1 = QLabel(window) 17 # label1.setParent(window) 也可以設置父親 18 label1.setText("標簽1") 19 20 label2 = QLabel(window) 21 label2.setText("標簽2") 22 label2.move(100,100) 23 24 label3 = QLabel(window) 25 label3.setText("標簽3") 26 label3.move(200,200) 27 28 print(window.childAt(101,105)) # 窗口 window 查看101,105 處是否有控件 輸出:<PyQt5.QtWidgets.QLabel object at 0x0000021076265A68> 29 30 print(window.childAt(300,300)) # 窗口 window 查看300,300 處是否有控件 輸出:None 31 32 33 #展示控件 34 window.show() 35 36 #3,進入消息循環 37 sys.exit(app.exec_())


1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("父子關系的學習") 14 window.resize(500,500) 15 16 label1 = QLabel(window) 17 # label1.setParent(window) 也可以設置父親 18 label1.setText("標簽1") 19 20 label2 = QLabel(window) 21 label2.setText("標簽2") 22 label2.move(100,100) 23 24 label3 = QLabel(window) 25 label3.setText("標簽3") 26 label3.move(200,200) 27 28 print(window.childrenRect()) # 查看所有子控件的矩形區域 輸出:PyQt5.QtCore.QRect(0, 0, 300, 230) 29 30 #展示控件 31 window.show() 32 33 #3,進入消息循環 34 sys.exit(app.exec_())
父子關系的案例:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Label(QLabel): 5 def mousePressEvent(self, QMouseEvent): 6 self.setStyleSheet("background-color:red;") 7 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 13 #2,控件的操作: 14 #創建控件 15 window = QWidget() 16 17 18 #設置控件 19 window.setWindowTitle("父子關系案例") 20 window.resize(500,500) 21 22 for i in range(10): 23 label = Label(window) 24 label.setText("標簽"+str(i)) 25 label.move(30*i ,30*i) 26 27 28 #展示控件 29 window.show() 30 31 #3,進入消息循環 32 sys.exit(app.exec_())
下面是不通過自定義類照樣實現這個功能:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, event): 6 local_x = event.x() 7 local_y = event.y() 8 sub_widget = self.childAt(local_x,local_y) 9 if sub_widget: # 排除sub_widget 是None 10 sub_widget.setStyleSheet("background-color:red;") 11 12 #1,創建app 13 app = QApplication(sys.argv) 14 15 16 #2,控件的操作: 17 #創建控件 18 window = Window() 19 20 21 #設置控件 22 window.setWindowTitle("父子關系案例") 23 window.resize(500,500) 24 25 for i in range(10): 26 label = QLabel(window) 27 label.setText("標簽"+str(i)) 28 label.move(30*i ,30*i) 29 30 31 #展示控件 32 window.show() 33 34 #3,進入消息循環 35 sys.exit(app.exec_())
(八):QWidget控件之層級控制:
它主要的作用就是調整z軸順序:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("層級控制") 14 window.resize(500,500) 15 16 17 label1 = QLabel(window) 18 label1.setText("標簽1") 19 label1.resize(200,200) 20 label1.setStyleSheet("background-color:red;") 21 22 label2 = QLabel(window) 23 label2.setText("標簽2") 24 label2.resize(200,200) 25 label2.setStyleSheet("background-color:green;") 26 label2.move(100,100) 27 28 #展示控件 29 window.show() 30 31 #3,進入消息循環 32 sys.exit(app.exec_())
效果是:
現在如果想讓早出現的紅色在上面:
一共有三種方法:
1,將紅色的升上去
2,將綠色的降下去
3,將綠色放在紅色下面

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("層級控制") 14 window.resize(500,500) 15 16 17 label1 = QLabel(window) 18 label1.setText("標簽1") 19 label1.resize(200,200) 20 label1.setStyleSheet("background-color:red;") 21 22 label2 = QLabel(window) 23 label2.setText("標簽2") 24 label2.resize(200,200) 25 label2.setStyleSheet("background-color:green;") 26 label2.move(100,100) 27 28 label1.raise_() # 讓label1 升到最高 29 30 #展示控件 31 window.show() 32 33 #3,進入消息循環 34 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("層級控制") 14 window.resize(500,500) 15 16 17 label1 = QLabel(window) 18 label1.setText("標簽1") 19 label1.resize(200,200) 20 label1.setStyleSheet("background-color:red;") 21 22 label2 = QLabel(window) 23 label2.setText("標簽2") 24 label2.resize(200,200) 25 label2.setStyleSheet("background-color:green;") 26 label2.move(100,100) 27 28 label2.lower() # 將label2 降到最下層 29 30 31 #展示控件 32 window.show() 33 34 #3,進入消息循環 35 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("層級控制") 14 window.resize(500,500) 15 16 17 label1 = QLabel(window) 18 label1.setText("標簽1") 19 label1.resize(200,200) 20 label1.setStyleSheet("background-color:red;") 21 22 label2 = QLabel(window) 23 label2.setText("標簽2") 24 label2.resize(200,200) 25 label2.setStyleSheet("background-color:green;") 26 label2.move(100,100) 27 28 label2.stackUnder(label1) # 將label2 放在label1 的下面 29 30 #展示控件 31 window.show() 32 33 #3,進入消息循環 34 sys.exit(app.exec_())
現在需求是點擊誰,讓誰跑到上面:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class MyLabel(QLabel): 5 def mousePressEvent(self, QMouseEvent): 6 self.raise_() 7 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 13 #2,控件的操作: 14 #創建控件 15 window = QWidget() 16 17 18 #設置控件 19 window.setWindowTitle("層級控制") 20 window.resize(500,500) 21 22 23 label1 = MyLabel(window) 24 label1.setText("標簽1") 25 label1.resize(200,200) 26 label1.setStyleSheet("background-color:red;") 27 28 label2 = MyLabel(window) 29 label2.setText("標簽2") 30 label2.resize(200,200) 31 label2.setStyleSheet("background-color:green;") 32 label2.move(100,100) 33 34 label2.stackUnder(label1) # 將label2 放在label1 的下面 35 36 #展示控件 37 window.show() 38 39 #3,進入消息循環 40 sys.exit(app.exec_())
(九):QWidget控件之頂層窗口相關:
如果一個控件沒有父控件,那么它就是頂層窗口。
API之圖標:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 icon = QIcon("d:/icon.png") 17 window.setWindowIcon(icon) #設置圖標 18 19 print(window.windowIcon()) #獲取圖標 20 21 22 23 #展示控件 24 window.show() 25 26 #3,進入消息循環 27 sys.exit(app.exec_())
API之標題:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 window.setWindowTitle(" ") #設置標題 17 print(window.windowTitle()) #獲取標題 18 19 20 21 #展示控件 22 window.show() 23 24 #3,進入消息循環 25 sys.exit(app.exec_())
API之不透明度:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 window.setWindowOpacity(0.5) # 設置為半透明 17 print(window.windowOpacity()) # 獲取不透明度 18 19 20 #展示控件 21 window.show() 22 23 #3,進入消息循環 24 sys.exit(app.exec_())
API之窗口狀態:
無狀態是正常的狀態。是默認的狀態,

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 print(window.windowState() == Qt.WindowNoState) # True 說明默認是無狀態 17 18 window.setWindowState(Qt.WindowMinimized) #最小化 19 window.setWindowState(Qt.WindowMaximized) #最大化 有標題欄 20 window.setWindowState(Qt.WindowFullScreen) #最小化 標題欄都沒了 #這時要通過任務管理器結束進程 21 22 23 24 #展示控件 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
活動窗口:是當有多個窗口時,讓活躍的窗口處在最頂層。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 print(window.windowState() == Qt.WindowNoState) # True 說明默認是無狀態 17 18 window.setWindowState(Qt.WindowMinimized) #最小化 19 window.setWindowState(Qt.WindowMaximized) #最大化 有標題欄 20 # window.setWindowState(Qt.WindowFullScreen) #最小化 標題欄都沒了 #這時要通過任務管理器結束進程 21 22 window2 = QWidget() 23 24 window2.show() 25 26 27 #展示控件 28 window.show() 29 window2.setWindowState(Qt.WindowActive) 30 31 #3,進入消息循環 32 sys.exit(app.exec_())
API之最大化和最小化:
我們可以通過窗口狀態來設置最大和最小,但是一般常用的是用這些:
showFull showMax showMin

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("頂層窗口相關操作") 14 window.resize(500,500) 15 16 17 #展示控件 18 # window.show() 19 window.showMaximized() #展示最大,這時上面的window.show() 也可以不用要 20 # window.showFullScreen() 21 # window.showMinimized() 22 23 24 #3,進入消息循環 25 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def mousePressEvent(self, QMouseEvent): 7 if self.isMaximized(): 8 self.showNormal() 9 else: 10 self.showMaximized() 11 12 #1,創建app 13 app = QApplication(sys.argv) 14 15 16 #2,控件的操作: 17 #創建控件 18 window = Window() 19 20 21 #設置控件 22 window.setWindowTitle("頂層窗口相關操作") 23 window.resize(500,500) 24 25 26 #展示控件 27 window.show() 28 29 30 31 #3,進入消息循環 32 sys.exit(app.exec_())
API之窗口標志:
可以通過它設置窗口的外觀。
這里如果是我們只要求有一個最大化的按鈕,這又該如何去搞呢?
這主要是通過頂層窗口外觀標志來設置:
頂層窗口的案例:
第一個需求是:去掉標題欄

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget(flags=Qt.FramelessWindowHint) 10 # def __init__(self, parent=None, flags, Qt_WindowFlags=None, Qt_WindowType=None, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__ 11 # pass 12 # 在創建窗口的時候就可以對外觀標志進行設置了, 13 14 15 #設置控件 16 window.setWindowTitle("頂層窗口操作案例") 17 window.resize(500,500) 18 19 20 21 22 23 #展示控件 24 window.show() 25 26 #3,進入消息循環 27 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 window.setWindowFlags(Qt.FramelessWindowHint) #通過方法設置flags 11 12 13 #設置控件 14 window.setWindowTitle("頂層窗口操作案例") 15 window.resize(500,500) 16 17 18 19 20 21 #展示控件 22 window.show() 23 24 #3,進入消息循環 25 sys.exit(app.exec_())
第二個需求:讓窗口變為半透明,

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget(flags=Qt.FramelessWindowHint) 10 window.setWindowOpacity(0.5) 11 12 13 14 #設置控件 15 window.setWindowTitle("頂層窗口操作案例") 16 window.resize(500,500) 17 18 19 #展示控件 20 window.show() 21 22 #3,進入消息循環 23 sys.exit(app.exec_())
第三個需求:自定制標題欄,

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget(flags=Qt.FramelessWindowHint) 10 window.setWindowOpacity(0.9) 11 12 13 14 #設置控件 15 window.setWindowTitle("頂層窗口操作案例") 16 window.resize(500,500) 17 18 19 20 #添加三個子控件 - 窗口的右上角 21 close_btn = QPushButton(window) 22 close_btn.setText("關閉") #暫時以文本呈現 23 close_btn.resize(40,25) 24 close_btn_width = close_btn.width() 25 window_width = window.width() 26 close_btn_x = window_width - close_btn_width 27 close_btn_y = 0 28 close_btn.move(close_btn_x,close_btn_y) 29 30 max_btn = QPushButton(window) 31 max_btn.setText("最大") 32 max_btn.resize(40,25) 33 max_btn_x = close_btn_x -max_btn.width() 34 max_btn_y = 0 35 max_btn.move(max_btn_x,max_btn_y) 36 37 mini_btn = QPushButton(window) 38 mini_btn.setText("最小") 39 mini_btn.resize(40,25) 40 mini_btn_x = max_btn_x -mini_btn.width() 41 mini_btn_y = 0 42 mini_btn.move(mini_btn_x,mini_btn_y) 43 44 45 46 #展示控件 47 window.show() 48 49 #3,進入消息循環 50 sys.exit(app.exec_())
繼續第三個操作,實現三個按鈕的功能:
監聽按鈕有兩個思路,一個是按信號和槽,一個是監聽事件,修改它的方法。
信號會更好一點,它是事件的高級封裝,一般能用信號和槽的都用信號和槽。
按鈕按下會發出信號pressed。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget(flags=Qt.FramelessWindowHint) 10 window.setWindowOpacity(0.9) 11 12 13 14 #設置控件 15 window.setWindowTitle("頂層窗口操作案例") 16 window.resize(500,500) 17 18 19 20 #添加三個子控件 - 窗口的右上角 21 close_btn = QPushButton(window) 22 close_btn.setText("關閉") #暫時以文本呈現 23 close_btn.resize(40,25) 24 close_btn_width = close_btn.width() 25 window_width = window.width() 26 close_btn_x = window_width - close_btn_width 27 close_btn_y = 0 28 close_btn.move(close_btn_x,close_btn_y) 29 30 max_btn = QPushButton(window) 31 max_btn.setText("最大") 32 max_btn.resize(40,25) 33 max_btn_x = close_btn_x -max_btn.width() 34 max_btn_y = 0 35 max_btn.move(max_btn_x,max_btn_y) 36 37 mini_btn = QPushButton(window) 38 mini_btn.setText("最小") 39 mini_btn.resize(40,25) 40 mini_btn_x = max_btn_x -mini_btn.width() 41 mini_btn_y = 0 42 mini_btn.move(mini_btn_x,mini_btn_y) 43 44 def close_window_slot(): 45 window.close() 46 47 def max_normal_window_slot(): # 最大化或者正常 48 if window.isMaximized(): 49 window.showNormal() 50 max_btn.setText("最大") 51 else: 52 window.showMaximized() 53 max_btn.setText("恢復") 54 55 def mini_window_slot(): 56 window.showMinimized() 57 58 close_btn.pressed.connect(close_window_slot) 59 max_btn.pressed.connect(max_normal_window_slot) 60 mini_btn.pressed.connect(mini_window_slot) 61 62 63 64 65 #展示控件 66 window.show() 67 68 #3,進入消息循環 69 sys.exit(app.exec_())
下面在繼續做之前,先做個重構,重構指的就是重新改變代碼的結構,一般都是 指封裝起來,這樣更方便修改維護和繼續開發,
如下重構:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def __init__(self,*args,**kwargs): 7 super().__init__(*args,**kwargs) 8 self.setWindowOpacity(0.9) 9 self.setWindowTitle("頂層窗口操作案例") 10 self.resize(500,500) 11 self.setup_ui() 12 13 14 def setup_ui(self): 15 self.btn_width = 40 16 self.btn_height = 25 17 self.top_margin = 0 18 self.add_close_max_mini_contrl() 19 20 def add_close_max_mini_contrl(self): 21 #添加三個子控件 - 窗口的右上角 22 self.close_btn = QPushButton(self) 23 self.close_btn.setText("關閉") #暫時以文本呈現 24 self.close_btn.resize(self.btn_width,self.btn_height) 25 close_btn_width = self.close_btn.width() 26 window_width = self.width() 27 close_btn_x = window_width - close_btn_width 28 close_btn_y = self.top_margin 29 self.close_btn.move(close_btn_x,close_btn_y) 30 31 self.max_btn = QPushButton(self) 32 self.max_btn.setText("最大") 33 self.max_btn.resize(self.btn_width,self.btn_height) 34 max_btn_x = close_btn_x -self.max_btn.width() 35 max_btn_y = self.top_margin 36 self.max_btn.move(max_btn_x,max_btn_y) 37 38 self.mini_btn = QPushButton(self) 39 self.mini_btn.setText("最小") 40 self.mini_btn.resize(self.btn_width,self.btn_height) 41 mini_btn_x = max_btn_x -self.mini_btn.width() 42 mini_btn_y = self.top_margin 43 self.mini_btn.move(mini_btn_x,mini_btn_y) 44 #1,創建app 45 app = QApplication(sys.argv) 46 47 #2,控件的操作: 48 49 window = Window(flags=Qt.FramelessWindowHint) 50 51 def close_window_slot(): 52 window.close() 53 def max_normal_window_slot(): # 最大化或者正常 54 if window.isMaximized(): 55 window.showNormal() 56 window.max_btn.setText("最大") 57 else: 58 window.showMaximized() 59 window.max_btn.setText("恢復") 60 def mini_window_slot(): 61 window.showMinimized() 62 63 window.close_btn.pressed.connect(close_window_slot) 64 window.max_btn.pressed.connect(max_normal_window_slot) 65 window.mini_btn.pressed.connect(mini_window_slot) 66 67 68 #展示控件 69 window.show() 70 71 #3,進入消息循環 72 sys.exit(app.exec_())
下面繼續開發,但是要先解決bug ,因為這時按鈕不會隨着窗口的變大而改變位置。
要解決它。
分兩步:監聽窗口大小的變化,然后重新計算下按鈕的位置。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def __init__(self,*args,**kwargs): 7 super().__init__(*args,**kwargs) 8 self.setWindowOpacity(0.9) 9 self.setWindowTitle("頂層窗口操作案例") 10 self.resize(500,500) 11 self.setup_ui() 12 13 14 def setup_ui(self): 15 self.btn_width = 40 16 self.btn_height = 25 17 self.top_margin = 0 18 self.add_close_max_mini_contrl() 19 20 def add_close_max_mini_contrl(self): 21 #添加三個子控件 - 窗口的右上角 22 self.close_btn = QPushButton(self) 23 self.close_btn.setText("關閉") #暫時以文本呈現 24 self.close_btn.resize(self.btn_width,self.btn_height) 25 26 self.max_btn = QPushButton(self) 27 self.max_btn.setText("最大") 28 self.max_btn.resize(self.btn_width,self.btn_height) 29 30 self.mini_btn = QPushButton(self) 31 self.mini_btn.setText("最小") 32 self.mini_btn.resize(self.btn_width,self.btn_height) 33 34 def resizeEvent(self, QResizeEvent): 35 print("窗口大小發生變化") 36 close_btn_width = self.close_btn.width() 37 window_width = self.width() 38 close_btn_x = window_width - close_btn_width 39 close_btn_y = self.top_margin 40 self.close_btn.move(close_btn_x,close_btn_y) 41 42 max_btn_x = close_btn_x -self.max_btn.width() 43 max_btn_y = self.top_margin 44 self.max_btn.move(max_btn_x,max_btn_y) 45 46 mini_btn_x = max_btn_x -self.mini_btn.width() 47 mini_btn_y = self.top_margin 48 self.mini_btn.move(mini_btn_x,mini_btn_y) 49 50 #1,創建app 51 app = QApplication(sys.argv) 52 53 #2,控件的操作: 54 55 window = Window(flags=Qt.FramelessWindowHint) 56 57 def close_window_slot(): 58 window.close() 59 def max_normal_window_slot(): # 最大化或者正常 60 if window.isMaximized(): 61 window.showNormal() 62 window.max_btn.setText("最大") 63 else: 64 window.showMaximized() 65 window.max_btn.setText("恢復") 66 def mini_window_slot(): 67 window.showMinimized() 68 69 window.close_btn.pressed.connect(close_window_slot) 70 window.max_btn.pressed.connect(max_normal_window_slot) 71 window.mini_btn.pressed.connect(mini_window_slot) 72 73 74 #展示控件 75 window.show() 76 77 #3,進入消息循環 78 sys.exit(app.exec_())
第四個需求:支持拖拽用戶去移動:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 5 class Window(QWidget): 6 def __init__(self,*args,**kwargs): 7 super().__init__(*args,**kwargs) 8 self.setWindowOpacity(0.5) 9 self.setWindowTitle("頂層窗口操作案例") 10 self.resize(500,500) 11 self.setup_ui() 12 self.move_flags = False # 主要是為了防止,鼠標追蹤導致出現問題 13 # self.setMouseTracking(True) 14 def setup_ui(self): 15 self.btn_width = 40 16 self.btn_height = 25 17 self.top_margin = 0 18 self.add_close_max_mini_contrl() 19 def add_close_max_mini_contrl(self): 20 #添加三個子控件 - 窗口的右上角 21 self.close_btn = QPushButton(self) 22 self.close_btn.setText("關閉") #暫時以文本呈現 23 self.close_btn.resize(self.btn_width,self.btn_height) 24 25 self.max_btn = QPushButton(self) 26 self.max_btn.setText("最大") 27 self.max_btn.resize(self.btn_width,self.btn_height) 28 29 self.mini_btn = QPushButton(self) 30 self.mini_btn.setText("最小") 31 self.mini_btn.resize(self.btn_width,self.btn_height) 32 def resizeEvent(self, QResizeEvent): 33 print("窗口大小發生變化") 34 close_btn_width = self.close_btn.width() 35 window_width = self.width() 36 close_btn_x = window_width - close_btn_width 37 close_btn_y = self.top_margin 38 self.close_btn.move(close_btn_x,close_btn_y) 39 40 max_btn_x = close_btn_x -self.max_btn.width() 41 max_btn_y = self.top_margin 42 self.max_btn.move(max_btn_x,max_btn_y) 43 44 mini_btn_x = max_btn_x -self.mini_btn.width() 45 mini_btn_y = self.top_margin 46 self.mini_btn.move(mini_btn_x,mini_btn_y) 47 def mousePressEvent(self, event): 48 if event.button() == Qt.LeftButton: 49 self.move_flags = True 50 self.mouse_x = event.globalX() 51 self.mouse_y = event.globalY() 52 53 self.window_x = self.x() 54 self.window_y = self.y() 55 def mouseMoveEvent(self, event): 56 if self.move_flags: 57 self.move_x = event.globalX() -self.mouse_x 58 self.move_y = event.globalY() -self.mouse_y 59 self.move(self.window_x + self.move_x,self.window_y +self.move_y) 60 def mouseReleaseEvent(self, event): 61 self.move_flags = False 62 63 #1,創建app 64 app = QApplication(sys.argv) 65 66 #2,控件的操作: 67 68 window = Window(flags=Qt.FramelessWindowHint) 69 70 def close_window_slot(): 71 window.close() 72 def max_normal_window_slot(): # 最大化或者正常 73 if window.isMaximized(): 74 window.showNormal() 75 window.max_btn.setText("最大") 76 else: 77 window.showMaximized() 78 window.max_btn.setText("恢復") 79 def mini_window_slot(): 80 window.showMinimized() 81 82 window.close_btn.pressed.connect(close_window_slot) 83 window.max_btn.pressed.connect(max_normal_window_slot) 84 window.mini_btn.pressed.connect(mini_window_slot) 85 86 87 #展示控件 88 window.show() 89 90 #3,進入消息循環 91 sys.exit(app.exec_())
至於里面的圖標,可以自己替代!
(十):QWidget控件之交互狀態:
API之是否可用:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("交互狀態") 14 window.resize(500,500) 15 16 17 btn = QPushButton(window) 18 btn.setText("按鈕") 19 btn.pressed.connect(lambda :print("點擊按鈕")) 20 btn.setEnabled(False) #將它設置為不可用 21 print(btn.isEnabled()) # 查看它是否可用 22 23 24 #展示控件 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
API之是否顯示/隱藏:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def paintEvent(self, event): #窗口繪制事件 6 print("窗口被繪制了") 7 return super().paintEvent(event) 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 #2,控件的操作: 13 #創建控件 14 window = Window() 15 16 #設置控件 17 window.setWindowTitle("交互狀態") 18 window.resize(500,500) 19 20 #展示控件 21 window.show() # 如果此時沒有window.show()就不會觸發paintEvent() 了 22 23 #3,進入消息循環 24 sys.exit(app.exec_())
其實show() 並不是最底層的函數,它只是調用 了下面的函數,setVisible(bool)

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def paintEvent(self, event): #窗口繪制事件 6 print("窗口被繪制了") 7 return super().paintEvent(event) 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 #2,控件的操作: 13 #創建控件 14 window = Window() 15 16 #設置控件 17 window.setWindowTitle("交互狀態") 18 window.resize(500,500) 19 20 #展示控件 21 # window.show() 22 window.setVisible(True) # 其實是window.show()調的它 23 24 #3,進入消息循環 25 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def paintEvent(self, event): #窗口繪制事件 6 print("窗口被繪制了") 7 return super().paintEvent(event) 8 9 #1,創建app 10 app = QApplication(sys.argv) 11 12 #2,控件的操作: 13 #創建控件 14 window = Window() 15 16 #設置控件 17 window.setWindowTitle("交互狀態") 18 window.resize(500,500) 19 20 #展示控件 21 # window.show() 22 # window.setVisible(True) 23 window.setHidden(False) #它也可以繪制window 24 25 26 #3,進入消息循環 27 sys.exit(app.exec_())
而且,繪制的時候肯定是先繪制頂層窗口,然后再繪制里面的子控件。下面來驗證這一點:
肯定要監聽子控件的繪制事件了,所以就要重寫它的類的繪制方法了。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def paintEvent(self, event): #窗口繪制事件 6 print("窗口被繪制了") 7 return super().paintEvent(event) 8 9 class Btn(QPushButton): 10 def paintEvent(self, event): 11 print("里面控件被繪制了") 12 return super().paintEvent(event) 13 14 15 #1,創建app 16 app = QApplication(sys.argv) 17 18 #2,控件的操作: 19 #創建控件 20 window = Window() 21 22 #設置控件 23 window.setWindowTitle("交互狀態") 24 window.resize(500,500) 25 26 btn = Btn(window) 27 btn.setText("按鈕") 28 29 #展示控件 30 # window.show() 31 # window.setVisible(True) 32 window.setHidden(False) #它也可以繪制window 33 34 #3,進入消息循環 35 sys.exit(app.exec_()) 36 37 ''' 38 輸出: 39 窗口被繪制了 40 里面控件被繪制了 41 '''
現在的要求是點擊按鈕之后,將其隱藏:
這里指的隱藏是當重新繪制時,不繪制按鈕而已。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def paintEvent(self, event): #窗口繪制事件 6 print("窗口被繪制了") 7 return super().paintEvent(event) 8 9 class Btn(QPushButton): 10 def paintEvent(self, event): 11 print("里面控件被繪制了") 12 return super().paintEvent(event) 13 14 15 #1,創建app 16 app = QApplication(sys.argv) 17 18 #2,控件的操作: 19 #創建控件 20 window = Window() 21 22 #設置控件 23 window.setWindowTitle("交互狀態") 24 window.resize(500,500) 25 26 btn = Btn(window) 27 btn.setText("按鈕") 28 btn.pressed.connect(lambda :btn.setVisible(False)) #點擊之后,就會把它給隱藏了, 29 # 后面的繪制就不會顯示它了,但是這個對象還是存在的 30 31 #展示控件 32 # window.show() 33 # window.setVisible(True) 34 window.setHidden(False) #它也可以繪制window 35 36 #3,進入消息循環 37 sys.exit(app.exec_())
注意事項:
有時候給setVisable 傳True 也不一定能繪制成功,因為繪制都是按照先父控件,后子控件來的,所以,如果直接繪制子控件,這肯定是不行的。
如下證明:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("交換狀態") 14 window.resize(500,500) 15 16 btn = QPushButton(window) 17 btn.setText("按鈕") 18 19 btn.setVisible(True) #就算給子控件設置了 TRUE ,因為它的父控件沒有被繪制,所以 它也沒被繪制 20 21 22 #展示控件 23 # window.show() 24 25 #3,進入消息循環 26 sys.exit(app.exec_())
isVisable 和 isHidden 的區別:
isVisible 和 isHidden的區別:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.move(100,100) 16 btn.setText("按鈕") 17 18 window.show() #此時: 輸出: False / True 19 20 print(btn.isHidden()) #是否被設置隱藏 21 print(btn.isVisible()) #到此是否可見 22 23 24 #展示控件 25 26 #3,進入消息循環 27 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.move(100,100) 16 btn.setText("按鈕") 17 18 19 20 print(btn.isHidden()) #是否被設置隱藏 21 print(btn.isVisible()) #到此是否可見 22 23 window.show() #此時: 輸出: False / False 24 25 #展示控件 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
它強調的是如果父控件顯示(不管是否真的顯示父控件),它是否跟着顯示。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.move(100,100) 16 btn.setText("按鈕") 17 18 # window.show() 19 20 #它這句話的意思是 如果 父控件顯示的時候,子控件是否被顯示 21 print(btn.isVisibleTo(window)) #就算是父控件不顯示也不影響它 ,它只是如果父控件顯示,它就顯示 22 23 24 #展示控件 25 26 #3,進入消息循環 27 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.move(100,100) 16 btn.setText("按鈕") 17 18 # window.show() 19 20 btn.setVisible(False) # 如果加上它的話,下面的打印就要是False 了 21 22 #它這句話的意思是 如果 父控件顯示的時候,子控件是否被顯示 23 print(btn.isVisibleTo(window)) #就算是父控件不顯示也不影響它 ,它只是如果父控件顯示,它就顯示 24 25 26 #展示控件 27 28 #3,進入消息循環 29 sys.exit(app.exec_())
API之是否編輯:
被編輯的時候顯示文件名字帶* 。
【*】 設置標題的時候,* 會被隱藏,直到設置setWindowModified(True) ,它會 被顯示。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態[*]") 12 window.resize(500,500) 13 14 15 window.show() 16 17 #3,進入消息循環 18 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態[*]") 12 window.resize(500,500) 13 window.setWindowModified(True) # 此時* 就會被顯示了,但是[] 不會被顯示的 14 15 16 window.show() 17 18 #3,進入消息循環 19 sys.exit(app.exec_())
而且[* ] 可以放在字符串的任意位置,都是可以的。
而且,中括號內部只能放* ,其他符號都是不行的。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態[$]") 12 window.resize(500,500) 13 window.setWindowModified(True) # 此時* 就會被顯示了,但是[] 不會被顯示的 14 15 16 window.show() 17 18 #3,進入消息循環 19 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態[*]") 12 window.resize(500,500) 13 window.setWindowModified(True) 14 print(window.isWindowModified()) # 查看是否被被編輯的狀態 15 16 window.show() 17 18 #3,進入消息循環 19 sys.exit(app.exec_())
API之是否活躍窗口:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 window2 = QWidget() 15 window2.show() 16 17 window.show() 18 19 print(window2.isActiveWindow()) # False 20 print(window.isActiveWindow()) # True 21 22 23 #3,進入消息循環 24 sys.exit(app.exec_())
是否,某一個窗口在最上面,它 就是處於活躍狀態呢?
不一定,如下代碼(它只是顯示在最上面)

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 window2 = QWidget() 15 window2.show() 16 17 window.show() 18 19 window2.raise_() #將window2 提到最外層 ,但是它仍然不是出於活躍的狀態 20 21 print(window2.isActiveWindow()) # False 22 print(window.isActiveWindow()) # True 23 24 25 #3,進入消息循環 26 sys.exit(app.exec_())
API之關閉:
它其實是調用之前的setVisable() 方法。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.setText("按鈕") 16 17 #隱藏這個按鈕的四種方法 18 # btn.setVisible(False) 19 # btn.setHidden(True) 20 # btn.hide() 21 btn.close() 22 23 window.show() 24 25 #3,進入消息循環 26 sys.exit(app.exec_())
一般情況下,它們四個都只是隱藏,而不釋放控件。
需要注意的是,close() 是可以通過設置,隱藏的時候將它釋放的

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 #2,控件的操作: 7 #創建控件 8 window = QWidget() 9 10 #設置控件 11 window.setWindowTitle("交互狀態") 12 window.resize(500,500) 13 14 btn = QPushButton(window) 15 btn.setText("按鈕") 16 btn.destroyed.connect(lambda :print("按鈕被釋放了")) 17 18 #隱藏這個按鈕的四種方法 19 # btn.setVisible(False) 20 # btn.setHidden(True) 21 # btn.hide() 22 btn.setAttribute(Qt.WA_DeleteOnClose,True) # 這再調用close()就會釋放按鈕了 23 btn.close() 24 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
這里只需要記住,它只是結合close() 來用的,對於其他的三個隱藏方法,一般不可用。
交互狀態的案例:
首先:創建文本框和按鈕和標簽:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 18 lineEdit = QLineEdit(self) 19 lineEdit.setText("文本框") 20 lineEdit.move(50,100) 21 22 btn = QPushButton(self) 23 btn.setText("登錄") 24 btn.move(50,150) 25 26 27 28 if __name__ == '__main__': 29 app =QApplication(sys.argv) 30 31 window = Window() 32 33 window.show() 34 35 sys.exit(app.exec_())
繼續:標簽被隱藏,文本框和按鈕被顯示,按鈕顯示不可用。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 label.hide() #異常標簽 18 19 lineEdit = QLineEdit(self) 20 lineEdit.setText("文本框") 21 lineEdit.move(50,100) 22 23 btn = QPushButton(self) 24 btn.setText("登錄") 25 btn.move(50,150) 26 btn.setEnabled(False) #設置它不可用 27 28 29 if __name__ == '__main__': 30 app =QApplication(sys.argv) 31 32 window = Window() 33 34 window.show() 35 36 sys.exit(app.exec_())
繼續:
這里使用textChanged信號。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 label.hide() #異常標簽 18 19 lineEdit = QLineEdit(self) 20 # lineEdit.setText("文本框") 21 lineEdit.move(50,100) 22 23 btn = QPushButton(self) 24 btn.setText("登錄") 25 btn.move(50,150) 26 btn.setEnabled(False) #設置它不可用 27 28 def textChanged_slot(arg): 29 print("文本框內容改變了",arg) 30 31 lineEdit.textChanged.connect(textChanged_slot) 32 #而且此時,會給我們傳遞出一個參數,這個參數 33 # 就是每次改變之后文本框內剩余的內容,我們可以用槽函數來接收 34 if __name__ == '__main__': 35 app =QApplication(sys.argv) 36 37 window = Window() 38 39 window.show() 40 sys.exit(app.exec_())
通過它就能實現有內容登錄窗口可用,沒內容則不可用。如下:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 label.hide() #異常標簽 18 19 lineEdit = QLineEdit(self) 20 # lineEdit.setText("文本框") 21 lineEdit.move(50,100) 22 23 btn = QPushButton(self) 24 btn.setText("登錄") 25 btn.move(50,150) 26 btn.setEnabled(False) #設置它不可用 27 28 def textChanged_slot(arg): 29 print("文本框內容改變了",arg) 30 if len(arg): 31 btn.setEnabled(True) 32 else: 33 btn.setEnabled(False) 34 35 lineEdit.textChanged.connect(textChanged_slot) 36 #而且此時,會給我們傳遞出一個參數,這個參數 37 # 就是每次改變之后文本框內剩余的內容,我們可以用槽函數來接收 38 if __name__ == '__main__': 39 app =QApplication(sys.argv) 40 41 window = Window() 42 43 window.show() 44 sys.exit(app.exec_())
這里的判斷可以被優化:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 label.hide() #異常標簽 18 19 lineEdit = QLineEdit(self) 20 # lineEdit.setText("文本框") 21 lineEdit.move(50,100) 22 23 btn = QPushButton(self) 24 btn.setText("登錄") 25 btn.move(50,150) 26 btn.setEnabled(False) #設置它不可用 27 28 def textChanged_slot(arg): 29 print("文本框內容改變了",arg) 30 # if len(arg): 31 # btn.setEnabled(True) 32 # else: 33 # btn.setEnabled(False) 34 btn.setEnabled(len(arg)) 35 36 lineEdit.textChanged.connect(textChanged_slot) 37 #而且此時,會給我們傳遞出一個參數,這個參數 38 # 就是每次改變之后文本框內剩余的內容,我們可以用槽函數來接收 39 if __name__ == '__main__': 40 app =QApplication(sys.argv) 41 42 window = Window() 43 44 window.show() 45 sys.exit(app.exec_())
繼續:
當輸入的內容為Zcb 的時候,已經隱藏的標簽顯示登錄成功。
這分兩步:
1,獲取文本框的內容。
2,判定是否是Zcb

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def __init__(self): 6 super().__init__() 7 self.setWindowTitle("交互狀態的的案例") 8 self.resize(400,400) 9 self.set_ui() 10 11 12 def set_ui(self): 13 #添加三個子控件 14 label = QLabel(self) 15 label.setText("標簽") 16 label.move(50,50) 17 label.hide() #隱藏標簽 18 19 20 lineEdit = QLineEdit(self) 21 # lineEdit.setText("文本框") 22 lineEdit.move(50,100) 23 24 btn = QPushButton(self) 25 btn.setText("登錄") 26 btn.move(50,150) 27 btn.setEnabled(False) #設置它不可用 28 29 def textChanged_slot(arg): 30 print("文本框內容改變了",arg) 31 # if len(arg): 32 # btn.setEnabled(True) 33 # else: 34 # btn.setEnabled(False) 35 btn.setEnabled(len(arg)) 36 37 lineEdit.textChanged.connect(textChanged_slot) 38 39 def check_slot(): 40 #1,獲取文本框的內容 41 content = lineEdit.text() 42 #2,判斷 43 label.show() 44 if content == "Zcb": 45 label.setText("登錄成功!") 46 else: 47 label.setText("登錄失敗!") 48 49 label.adjustSize() # 注:它一定要放在設置文本的后面。 50 51 btn.pressed.connect(check_slot) #用信號clicked 也可以 52 53 if __name__ == '__main__': 54 app =QApplication(sys.argv) 55 56 window = Window() 57 58 window.show() 59 sys.exit(app.exec_())
(十一):QWidget控件之信息提示:
API之狀態提示:
它一般是在窗口的下方的一個橫條。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 #當鼠標停留在窗口控件之后,在狀態欄展示提示信息,但是前提是要有狀態欄 17 window.setStatusTip("這時窗口") 18 19 20 21 #展示控件 22 window.show() 23 24 #3,進入消息循環 25 sys.exit(app.exec_())
我們這里換個控件類別,換成個組合控件。換QWidget 為 QMainWindow .
所有組合控件,就是有很多常用的部分,例如,菜單欄,編輯區域,有狀態欄。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 #當鼠標停留在窗口控件之后,在狀態欄展示提示信息,但是前提是要有狀態欄 17 window.setStatusTip("這是窗口") 18 19 20 21 #展示控件 22 window.show() 23 24 #3,進入消息循環 25 sys.exit(app.exec_())
所謂的懶加載指的是,當用的時候才會加載上去。
這時就可以看到當鼠標放上去的時候的提示信息了。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 #當鼠標停留在窗口控件之后,在狀態欄展示提示信息,但是前提是要有狀態欄 17 window.setStatusTip("這是窗口") 18 19 20 #展示控件 21 window.show() 22 23 #3,進入消息循環 24 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 #當鼠標停留在窗口控件之后,在狀態欄展示提示信息,但是前提是要有狀態欄 17 window.setStatusTip("這是窗口") 18 19 print(window.statusTip()) #獲取提示信息 20 21 #展示控件 22 window.show() 23 24 #3,進入消息循環 25 sys.exit(app.exec_())

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 #當鼠標停留在窗口控件之后,在狀態欄展示提示信息,但是前提是要有狀態欄 17 window.setStatusTip("這是窗口") 18 19 label = QLabel(window) 20 label.setText("hello world") 21 label.setStatusTip("這是標簽") 22 23 24 #展示控件 25 window.show() 26 27 #3,進入消息循環 28 sys.exit(app.exec_())
API之工具提示:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("hello world") 19 label.setToolTip("這是個標簽") #將鼠標停在上面的時候,在旁邊會有提示 20 print(label.toolTip()) #獲取工具提示 21 22 #展示控件 23 window.show() 24 25 #3,進入消息循環 26 sys.exit(app.exec_())
注意:工具提示的展示 時間是有限的,具體時長我們可以控制。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 12 #設置控件 13 window.setWindowTitle("信息提示") 14 window.resize(500,500) 15 16 17 label = QLabel(window) 18 label.setText("hello world") 19 label.setToolTip("這是個標簽") #將鼠標停在上面的時候,在旁邊會有提示 20 print(label.toolTip()) #獲取工具提示 21 22 label.setToolTipDuration(2000) # 顯示2s 23 24 25 #展示控件 26 window.show() 27 28 #3,進入消息循環 29 sys.exit(app.exec_())
API之這是啥提示:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 9 window = QMainWindow() #組合控件 10 window.statusBar() 11 window.setWindowFlags(Qt.WindowContextHelpButtonHint) #換個帶問號的窗口樣式 12 13 14 #設置控件 15 window.setWindowTitle("信息提示") 16 window.resize(500,500) 17 18 19 label = QLabel(window) 20 label.setText("hello world") 21 22 label.setToolTipDuration(2000) # 顯示2s 23 label.setWhatsThis("這是啥,這是幫助信息") #它的使用方法是:先點? ,然后再帶這個標簽 24 print(label.whatsThis()) 25 26 #展示控件 27 window.show() 28 29 #3,進入消息循環 30 sys.exit(app.exec_())
(十二):QWidget控件之焦點控制:
單個控件的角度:
API 之 setFocus():

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("焦點控制") 14 window.resize(500,500) 15 16 lineEdit1 = QLineEdit(window) 17 lineEdit1.move(50,50) 18 19 lineEdit2 = QLineEdit(window) 20 lineEdit2.move(100,100) 21 lineEdit2.setFocus() #先讓第二個獲取焦點 22 23 24 lineEdit3 = QLineEdit(window) 25 lineEdit3.move(150,150) 26 27 #展示控件 28 window.show() 29 30 #3,進入消息循環 31 sys.exit(app.exec_())
API 之 setFocusPolicy(Policy) :
設置策略,(獲取焦點的策略)
API之clearFocus() :
清除焦點,此時tab 和點擊都不行了,只能通過setFocus()代碼來實現。
父控件的角度:
如何獲取當前窗口中,所有子控件中獲取焦點的那個控件:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 #1,創建app 4 app = QApplication(sys.argv) 5 6 7 #2,控件的操作: 8 #創建控件 9 window = QWidget() 10 11 12 #設置控件 13 window.setWindowTitle("焦點控制") 14 window.resize(500,500) 15 16 lineEdit1 = QLineEdit(window) 17 lineEdit1.move(50,50) 18 19 lineEdit2 = QLineEdit(window) 20 lineEdit2.move(100,100) 21 22 lineEdit3 = QLineEdit(window) 23 lineEdit3.move(150,150) 24 25 # print(window.focusWidget()) # 獲取當前窗口的獲取焦點的子控件,此時不行 為None 26 27 28 #展示控件 29 window.show() 30 31 print(window.focusWidget()) # 獲取當前窗口的獲取焦點的子控件,此時也不行 None 32 33 #這說明因為獲取焦點是后面的事情, 34 35 #3,進入消息循環 36 sys.exit(app.exec_())
這時是不行的,它說明焦點是后面獲取的。
下面驗證上述觀點:

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, event): 6 print(self.focusWidget()) #點擊時獲取它的子控件中獲取焦點的那個 7 8 #1,創建app 9 app = QApplication(sys.argv) 10 11 12 #2,控件的操作: 13 #創建控件 14 window = Window() 15 16 17 #設置控件 18 window.setWindowTitle("焦點控制") 19 window.resize(500,500) 20 21 lineEdit1 = QLineEdit(window) 22 lineEdit1.move(50,50) 23 24 lineEdit2 = QLineEdit(window) 25 lineEdit2.move(100,100) 26 27 lineEdit3 = QLineEdit(window) 28 lineEdit3.move(150,150) 29 30 31 #展示控件 32 window.show() 33 34 35 36 #3,進入消息循環 37 sys.exit(app.exec_())
同時它也說明,焦點是在show() 的后面加上去的。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, event): 6 # self.focusNextChild() #在子控件中切換焦點 7 # self.focusPreviousChild() #反序 8 self.focusNextPrevChild(True) #True 是前面的Next false 是后面的Prev 9 10 #1,創建app 11 app = QApplication(sys.argv) 12 13 14 #2,控件的操作: 15 #創建控件 16 window = Window() 17 18 19 #設置控件 20 window.setWindowTitle("焦點控制") 21 window.resize(500,500) 22 23 lineEdit1 = QLineEdit(window) 24 lineEdit1.move(50,50) 25 26 lineEdit2 = QLineEdit(window) 27 lineEdit2.move(100,100) 28 29 lineEdit3 = QLineEdit(window) 30 lineEdit3.move(150,150) 31 32 33 #展示控件 34 window.show() 35 36 37 38 #3,進入消息循環 39 sys.exit(app.exec_())
它是個靜態方法,用類對象去調用。

1 from PyQt5.Qt import * #剛開始學習可以這樣一下導入 2 import sys 3 4 class Window(QWidget): 5 def mousePressEvent(self, event): 6 # self.focusNextChild() #在子控件中切換焦點 7 # self.focusPreviousChild() #反序 8 self.focusNextPrevChild(True) #True 是前面的Next false 是后面的Prev 9 10 #1,創建app 11 app = QApplication(sys.argv) 12 13 14 #2,控件的操作: 15 #創建控件 16 window = Window() 17 18 19 #設置控件 20 window.setWindowTitle("焦點控制") 21 window.resize(500,500) 22 23 lineEdit1 = QLineEdit(window) 24 lineEdit1.move(50,50) 25 26 lineEdit2 = QLineEdit(window) 27 lineEdit2.move(100,100) 28 29 lineEdit3 = QLineEdit(window) 30 lineEdit3.move(150,150) 31 32 33 Window.setTabOrder(lineEdit1,lineEdit3) 34 Window.setTabOrder(lineEdit3,lineEdit2) 35 #tab 切換 1 3 2 36 37 38 #展示控件 39 window.show() 40 41 42 43 #3,進入消息循環 44 sys.exit(app.exec_())
(十二):QWidget控件之其他:
后面說。
四:QWidget 信號:
總結:
QWidget結束,見下一個QAbstractButton:https://www.cnblogs.com/zach0812/p/11360978.html