偵測與控制視窗
這篇教學如何在 PyQt6 偵測視窗的位置、尺寸與縮放行為,並透過對應的方法,進一步控制視窗的尺寸和位置,最後還會介紹視窗相對應的事件,當視窗事件發生時,就能進行對應的動作。
快速導覽:
因為 Google Colab 不支援 PyQt6,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda )。
偵測視窗
在 PyQt6 裡建立最底層的視窗 Widget 元件之後,只要套用對應的偵測方法,就可以偵測視窗的屬性,下方列出常用的偵測方法:
方法 | 說明 |
---|---|
x() | 視窗在螢幕裡的 x 座標。 |
y() | 視窗在螢幕裡的 y 座標。 |
width() | 視窗的寬度。 |
height() | 視窗的高度。 |
windowTitle() | 視窗的標題。 |
以下方的程式碼執行後,會開啟一個空白的視窗,並使用 QLabel 印出視窗的相關資訊。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
label = QtWidgets.QLabel(Form)
label.setGeometry(10,10,200,200)
label.setText(f'''
x: {Form.x()}
y: {Form.y()}
w: {Form.width()}
h: {Form.height()}
t: {Form.windowTitle()}
''')
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.setMouseTracking(True)
self.ui()
def ui(self):
self.label = QtWidgets.QLabel(self)
self.label.setGeometry(10,10,200,200)
self.label.setStyleSheet('font-size:20px;')
self.label.setText(f'''
x: {self.x()}
y: {self.y()}
w: {self.width()}
h: {self.height()}
t: {self.windowTitle()}
''')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
控制視窗
在 PyQt6 裡建立最底層的視窗 Widget 元件之後,只要套用對應的控制方法,就可以控制與設定視窗,下方列出常用的控制方法:
方法 | 參數 | 說明 |
---|---|---|
setWindowTitle() | str | 視窗標題。 |
resize() | width(int), height(int) | 改變視窗尺寸。 |
move() | x(int), y(int) | 設定視窗位置。 |
setGeometry() | x(int), y(int), width(int), height(int) | 設定視窗位置與尺寸。 |
setFixedWidth() | hwidth(int) | 固定視窗寬度。 |
setFixedHeight() | height(int) | 固定視窗高度。 |
setFixedSize() | width(int), height(int) | 固定視窗尺寸。 |
showMinimized() | 視窗最小化。 | |
showMaximized() | 視窗最大化。 | |
showFullscreen() | 視窗全螢幕。 | |
showNormal() | 視窗恢復原本尺寸。 |
下方的例子執行後,會建立三顆按鈕,並將三顆按鈕的點擊行為綁定 lambda 匿名函式,使得點擊按鈕時會進行最大化視窗、恢復視窗以及移動視窗的效果。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
btn1 = QtWidgets.QPushButton(Form)
btn1.setGeometry(10,10,100,30)
btn1.setText('最大化')
btn1.clicked.connect(lambda: Form.showMaximized()) # 最大化
btn2 = QtWidgets.QPushButton(Form)
btn2.setGeometry(110,10,100,30)
btn2.setText('恢復大小')
btn2.clicked.connect(lambda: Form.showNormal()) # 恢復原本大小
btn3 = QtWidgets.QPushButton(Form)
btn3.setGeometry(10,50,100,30)
btn3.setText('移動視窗')
btn3.clicked.connect(lambda: Form.move(100, 100)) # 移動到 (100, 100)
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.setMouseTracking(True)
self.ui()
def ui(self):
self.btn1 = QtWidgets.QPushButton(self)
self.btn1.setGeometry(10,10,100,30)
self.btn1.setText('最大化')
self.btn1.clicked.connect(lambda: self.showMaximized()) # 最大化
self.btn2 = QtWidgets.QPushButton(self)
self.btn2.setGeometry(110,10,100,30)
self.btn2.setText('恢復大小')
self.btn2.clicked.connect(lambda: self.showNormal()) # 恢復原本大小
self.btn3 = QtWidgets.QPushButton(self)
self.btn3.setGeometry(10,50,100,30)
self.btn3.setText('移動視窗')
self.btn3.clicked.connect(lambda: self.move(100, 100)) # 移動到 (100, 100)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
視窗置中、取得螢幕資訊
在控制視窗位置與尺寸時,有時需要獲取電腦螢幕的資訊,使用 QtWidgets.QApplication.screens()
之後,就能透過下列的方法取得電腦螢幕的尺寸 ( 用法和 PyQt5 相同,但方法名稱不同 )。
方法 | 說明 |
---|---|
width() | 電腦螢幕的寬度。 |
height() | 電腦螢幕的高度。 |
下方的程式碼執行後,會根據電腦螢幕的尺寸,以及視窗的尺寸,換算出視窗置中的座標 ( 座標必須為整數 ),進而讓視窗置中顯示。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
screen = QtWidgets.QApplication.screens()
screen_size = screen[0].size()
screen_w = screen_size.width() # 電腦螢幕寬度
screen_h = screen_size.height() # 電腦螢幕高度
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
Form_w = Form.width() # 視窗寬度
Form_h = Form.height() # 視窗高度
new_x = int((screen_w - Form_w)/2) # 計算後的 x 座標
new_y = int((screen_h - Form_h)/2) # 計算後的 y 座標
Form.move(new_x, new_y) # 移動視窗
Form.show()
sys.exit(app.exec())
class 寫法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QKeySequence, QShortcut
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.setMouseTracking(True)
self.screen()
self.windowMove()
def screen(self):
screen = QtWidgets.QApplication.screens()
screen_size = screen[0].size()
self.screen_w = screen_size.width() # 電腦螢幕寬度
self.screen_h = screen_size.height() # 電腦螢幕高度
def windowMove(self):
Form_w = self.width() # 視窗寬度
Form_h = self.height() # 視窗高度
new_x = int((self.screen_w - Form_w)/2) # 計算後的 x 座標
new_y = int((self.screen_h - Form_h)/2) # 計算後的 y 座標
self.move(new_x, new_y) # 移動視窗
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
視窗事件
下方列出常用的視窗事件,可以在視窗顯示、關閉、移動、縮放或焦點改變時觸發。
事件 | 說明 |
---|---|
showEvent | 開啟視窗。 |
closeEvent | 關閉視窗。 |
moveEvent | 移動視窗。 |
resizeEvent | 視窗尺寸改變。 |
focusInEvent | 視窗為焦點 ( 需要先使用 setFocus() 方法 )。 |
focusOutEvent | 視窗失去焦點,使用者操作其他視窗 ( 需要先使用 setFocus() 方法 )。 |
下方的程式碼執行後,用滑鼠改變視窗大小或位置,就能看見後台印出對應的事件內容。
from PyQt6 import QtWidgets
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
Form.setWindowTitle('oxxo.studio')
Form.resize(300, 200)
def close(self):
print('close!!')
def move(self):
print('move...')
def resize(self):
print('resize')
def show(self):
print('show')
def focusIn(self):
print('focus in')
def focusOut(self):
print('focus out')
Form.closeEvent = close
Form.moveEvent = move
Form.resizeEvent = resize
Form.showEvent = show
Form.setFocus()
Form.focusInEvent = focusIn
Form.focusOutEvent = focusOut
Form.show()
sys.exit(app.exec())
class 的寫法:
from PyQt6 import QtWidgets
from PyQt6.QtGui import QKeySequence, QShortcut
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('oxxo.studio')
self.resize(300, 200)
self.setMouseTracking(True)
self.setFocus()
def closeEvent(self, event):
print('close!!')
def moveEvent(self, event):
print('move...')
def resizeEvent(self, event):
print('resize')
def showEvent(self, event):
print('show')
def focusInEvent(self, event):
print('focus in')
def focusOutEvent(self, event):
print('focus out')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Form = MyWidget()
Form.show()
sys.exit(app.exec())
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~