Last Updated on 2021-08-23 by Clay
不知道大家是否看膩了一成不變的直角邊框界面?至少,我確定我對於直角邊框的界面感到沒那麼有趣了,看看 Android 的 App 圖示、iOS 的種種邊框,是不是都有著好看的圓角邊框呢?
在 PyQt5 這個框架中,我們當然也可以製作出同樣好看的圓角邊框,以下來看個簡單的範例程式碼。
使用 setStyleSheet() 調整圓角
首先我得澄清,我不確定有沒有更好的實現方法,所以這個方法僅僅只是提供參考。
# coding: utf-8 import sys from PyQt5.Qt import Qt from PyQt5.QtWidgets import * class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Window size self.WIDTH = 300 self.HEIGHT = 300 self.resize(self.WIDTH, self.HEIGHT) # Widget self.centralwidget = QWidget(self) self.centralwidget.resize(self.WIDTH, self.HEIGHT) # Initial self.setWindowFlag(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowOpacity(0.6) radius = 30 self.centralwidget.setStyleSheet( """ background:rgb(255, 255, 255); border-top-left-radius:{0}px; border-bottom-left-radius:{0}px; border-top-right-radius:{0}px; border-bottom-right-radius:{0}px; """.format(radius) ) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
原理非常單純:我不清楚如何漂亮地改動真正的 MainWindow 元件,於是我建立了一個覆蓋在 MainWindow 上的 Widget 元件,然後將 MainWindow 隱藏,就只剩下單純的 Widget 了。
接著再使用 setStyleSheet()
來寫下要將元件改動樣式的 QSS 語法,也就是更改 radius 參數,就能調整 Widget 的形狀。
為什麼不能直接改 MainWindow 元件呢?我們來直接跑一次改 MainWindow 的狀況。
# coding: utf-8 import sys from PyQt5.Qt import Qt from PyQt5.QtWidgets import * class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Window size self.WIDTH = 300 self.HEIGHT = 300 self.resize(self.WIDTH, self.HEIGHT) # Initial self.setWindowFlag(Qt.FramelessWindowHint) self.setWindowOpacity(0.6) radius = 30 self.setStyleSheet( """ background:rgb(255, 255, 255); border-top:1px solid black; border-bottom:1px solid black; border-left:1px solid black; border-right:1px solid black; border-top-left-radius:{0}px; border-bottom-left-radius:{0}px; border-top-right-radius:{0}px; border-bottom-right-radius:{0}px; """.format(radius) ) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
並不是沒有改動到(為了更好地呈現效果,我將圓角設定為黑色),但我們可以發現,這樣邊框仍然存在,反而看起來有些醜。不得已,只好使用 Widget 元件來當作界面。
順帶一提,如果想要使用徹底就是個圓形的界面,也可以將 radius 參數調整為 150。(這是因為我尺寸是 300 x 300 的緣故,比如說你的尺寸如果是 600 x 600,想要是圓形就必須要調整 radius 參數為 300)
圓形的界面就誕生了 XDDD
拖曳界面
想必寫習慣 PyQt5 的大家應該都有注意到,為了美觀,我把標題欄位隱藏掉了。那麼,這下子我們不就沒辦法拖曳界面和關閉程式了嗎?
這裡分享一下我過去寫過的兩篇文章:
第一篇文章紀錄了該如何在隱藏標題欄位後拖曳界面。
第二篇文章則是介紹了如何設置右鍵打開選單 —— 這樣就可以設定離開鍵了。
完整程式碼如下:
# coding: utf-8 import sys from PyQt5.Qt import Qt from PyQt5.QtWidgets import * from PyQt5.QtGui import QCursor class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Window size self.WIDTH = 300 self.HEIGHT = 300 self.resize(self.WIDTH, self.HEIGHT) # Widget self.centralwidget = QWidget(self) self.centralwidget.resize(self.WIDTH, self.HEIGHT) # Menu self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.right_menu) # Initial self.setWindowFlag(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowOpacity(0.6) radius = 150 self.centralwidget.setStyleSheet( """ background:rgb(255, 255, 255); border-top-left-radius:{0}px; border-bottom-left-radius:{0}px; border-top-right-radius:{0}px; border-bottom-right-radius:{0}px; """.format(radius) ) def right_menu(self, pos): menu = QMenu() # Add menu options exit_option = menu.addAction('Exit') # Menu option events exit_option.triggered.connect(lambda: exit()) # Position menu.exec_(self.mapToGlobal(pos)) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.moveFlag = True self.movePosition = event.globalPos() - self.pos() self.setCursor(QCursor(Qt.OpenHandCursor)) event.accept() def mouseMoveEvent(self, event): if Qt.LeftButton and self.moveFlag: self.move(event.globalPos() - self.movePosition) event.accept() def mouseReleaseEvent(self, QMouseEvent): self.moveFlag = False self.setCursor(Qt.CrossCursor) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output: