Last Updated on 2021-05-17 by Clay
最近在研究如何使用 Flutter 開發手機 App。在研究的過程中,我發現將『元件漸層渲染』可以做出很漂亮的界面(相關的心得筆記可以參考《Flutter 中將元件渲染成不同顏色》這篇)。
於是我就開始思考:以 Python 開發桌面應用程式的 PyQt5 能不能做到這件事呢?
一查之下,果不其然,是可以的,而且也是渲染地相當漂亮。那麼,以下我就簡單筆記我如何完成一個元件的漸層渲染。
Qlineargradient
其實若不談實現非常深奧的渲染方式,好比說漩渦式的中心渲染——我還真的看過這種渲染方式,而且相當漂亮——簡單地設定點到點的渲染在將元件設定 setStyleSheet 時設定 qlineargradient 即可。
比如說這是一個按鈕:
我在 StyleSheet 進行這樣的設定:
x1, y1, x2, y2 的設定其實非常簡單,指得就是從元件的『右上角』為原點,往下伸展最長的位置為 1 、往右伸展最常的位置亦為 1。
所以這裡我設定的是兩個顏色渲染的位置,從元件的左邊中心渲染到右邊中心。
下面的 rgb 設定就是我渲染的兩個顏色。
Output:
是不是非常單純呢?
範例程式碼
以下是我簡單測試改變顏色的程式碼,也許大家可以直接參考,分成兩個檔案,首先是界面 gradient.py:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'gradient.ui' # # Created by: PyQt5 UI code generator 5.13.0 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(834, 299) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(230, 30, 331, 111)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.pushButton.setFont(font) self.pushButton.setStyleSheet("") self.pushButton.setObjectName("pushButton") self.horizontalSlider = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider.setGeometry(QtCore.QRect(100, 200, 160, 22)) self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider.setObjectName("horizontalSlider") self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(300, 200, 51, 22)) self.lineEdit.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit.setObjectName("lineEdit") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(280, 200, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label.setFont(font) self.label.setObjectName("label") self.color_1 = QtWidgets.QLabel(self.centralwidget) self.color_1.setGeometry(QtCore.QRect(10, 200, 80, 80)) self.color_1.setText("") self.color_1.setObjectName("color_1") self.horizontalSlider_2 = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider_2.setGeometry(QtCore.QRect(100, 230, 160, 22)) self.horizontalSlider_2.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_2.setObjectName("horizontalSlider_2") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(280, 230, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_3.setFont(font) self.label_3.setObjectName("label_3") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(300, 230, 51, 22)) self.lineEdit_2.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit_2.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit_2.setObjectName("lineEdit_2") self.horizontalSlider_3 = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider_3.setGeometry(QtCore.QRect(100, 260, 160, 22)) self.horizontalSlider_3.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_3.setObjectName("horizontalSlider_3") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(280, 260, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_4.setFont(font) self.label_4.setObjectName("label_4") self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_3.setGeometry(QtCore.QRect(300, 260, 51, 22)) self.lineEdit_3.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit_3.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit_3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit_3.setObjectName("lineEdit_3") self.label_5 = QtWidgets.QLabel(self.centralwidget) self.label_5.setGeometry(QtCore.QRect(740, 230, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_5.setFont(font) self.label_5.setObjectName("label_5") self.color_2 = QtWidgets.QLabel(self.centralwidget) self.color_2.setGeometry(QtCore.QRect(470, 200, 80, 80)) self.color_2.setText("") self.color_2.setObjectName("color_2") self.horizontalSlider_5 = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider_5.setGeometry(QtCore.QRect(560, 230, 160, 22)) self.horizontalSlider_5.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_5.setObjectName("horizontalSlider_5") self.horizontalSlider_6 = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider_6.setGeometry(QtCore.QRect(560, 260, 160, 22)) self.horizontalSlider_6.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_6.setObjectName("horizontalSlider_6") self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_4.setGeometry(QtCore.QRect(760, 260, 51, 22)) self.lineEdit_4.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit_4.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit_4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit_4.setObjectName("lineEdit_4") self.horizontalSlider_4 = QtWidgets.QSlider(self.centralwidget) self.horizontalSlider_4.setGeometry(QtCore.QRect(560, 200, 160, 22)) self.horizontalSlider_4.setOrientation(QtCore.Qt.Horizontal) self.horizontalSlider_4.setObjectName("horizontalSlider_4") self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_5.setGeometry(QtCore.QRect(760, 230, 51, 22)) self.lineEdit_5.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit_5.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit_5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit_5.setObjectName("lineEdit_5") self.label_7 = QtWidgets.QLabel(self.centralwidget) self.label_7.setGeometry(QtCore.QRect(740, 200, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_7.setFont(font) self.label_7.setObjectName("label_7") self.label_8 = QtWidgets.QLabel(self.centralwidget) self.label_8.setGeometry(QtCore.QRect(740, 260, 16, 22)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(12) font.setBold(True) font.setWeight(75) self.label_8.setFont(font) self.label_8.setObjectName("label_8") self.lineEdit_6 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_6.setGeometry(QtCore.QRect(760, 200, 51, 22)) self.lineEdit_6.setLayoutDirection(QtCore.Qt.LeftToRight) self.lineEdit_6.setLocale(QtCore.QLocale(QtCore.QLocale.Chinese, QtCore.QLocale.Taiwan)) self.lineEdit_6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.lineEdit_6.setObjectName("lineEdit_6") self.line = QtWidgets.QFrame(self.centralwidget) self.line.setGeometry(QtCore.QRect(400, 200, 20, 81)) self.line.setFrameShape(QtWidgets.QFrame.VLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "TEST BUTTON")) self.lineEdit.setText(_translate("MainWindow", "0")) self.label.setText(_translate("MainWindow", "R")) self.label_3.setText(_translate("MainWindow", "G")) self.lineEdit_2.setText(_translate("MainWindow", "0")) self.label_4.setText(_translate("MainWindow", "B")) self.lineEdit_3.setText(_translate("MainWindow", "0")) self.label_5.setText(_translate("MainWindow", "G")) self.lineEdit_4.setText(_translate("MainWindow", "0")) self.lineEdit_5.setText(_translate("MainWindow", "0")) self.label_7.setText(_translate("MainWindow", "R")) self.label_8.setText(_translate("MainWindow", "B")) self.lineEdit_6.setText(_translate("MainWindow", "0"))
這個是從 Qt Designer 拉好的界面通過 PyUIC 直接轉換而成的。
然後是程式功能:
# -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import * from gradient import Ui_MainWindow class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Display color self.ui.color_1.setStyleSheet('background-color: rgb(0, 0, 0);') self.ui.color_2.setStyleSheet('background-color: rgb(0, 0, 0);') # HorizontalSlider self.ui.horizontalSlider.setMaximum(255) self.ui.horizontalSlider_2.setMaximum(255) self.ui.horizontalSlider_3.setMaximum(255) self.ui.horizontalSlider_4.setMaximum(255) self.ui.horizontalSlider_5.setMaximum(255) self.ui.horizontalSlider_6.setMaximum(255) self.ui.horizontalSlider.valueChanged.connect(lambda: self.color_value('R1')) self.ui.horizontalSlider_2.valueChanged.connect(lambda: self.color_value('G1')) self.ui.horizontalSlider_3.valueChanged.connect(lambda: self.color_value('B1')) self.ui.horizontalSlider_4.valueChanged.connect(lambda: self.color_value('R2')) self.ui.horizontalSlider_5.valueChanged.connect(lambda: self.color_value('G2')) self.ui.horizontalSlider_6.valueChanged.connect(lambda: self.color_value('B2')) def color_value(self, color): if color == 'R1': self.ui.lineEdit.setText(str(self.ui.horizontalSlider.value())) elif color == 'G1': self.ui.lineEdit_2.setText(str(self.ui.horizontalSlider_2.value())) elif color == 'B1': self.ui.lineEdit_3.setText(str(self.ui.horizontalSlider_3.value())) elif color == 'R2': self.ui.lineEdit_4.setText(str(self.ui.horizontalSlider_4.value())) elif color == 'G2': self.ui.lineEdit_5.setText(str(self.ui.horizontalSlider_5.value())) elif color == 'B2': self.ui.lineEdit_6.setText(str(self.ui.horizontalSlider_6.value())) self.color_change() def color_change(self): self.newR1 = int(self.ui.lineEdit.text()) self.newG1 = int(self.ui.lineEdit_2.text()) self.newB1 = int(self.ui.lineEdit_3.text()) self.ui.color_1.setStyleSheet('background-color: rgb({}, {}, {});'.format( self.newR1, self.newG1, self.newB1 )) self.newR2 = int(self.ui.lineEdit_4.text()) self.newG2 = int(self.ui.lineEdit_5.text()) self.newB2 = int(self.ui.lineEdit_6.text()) self.ui.color_2.setStyleSheet('background-color: rgb({}, {}, {});'.format( self.newR2, self.newG2, self.newB2 )) self.gradient_color_button() def gradient_color_button(self): self.ui.pushButton.setStyleSheet('background-color: ' 'qlineargradient(' 'spread:' 'pad, x1:0, y1:0.5, x2:1, y2:0.5,' 'stop:0 rgb({}, {}, {}),' 'stop:1 rgb({}, {}, {}));'.format(self.newR1, self.newG1, self.newB1, self.newR2, self.newG2, self.newB2)) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
大家可以任意選取自己想要的顏色,試試看效果如何吧。
更多相關的教學可以在 https://www.learnpyqt.com/widgets/gradient/ 這個網站中看到,我最近發現了這個網站教導了許多有趣的界面應用,比方說將音樂視覺化的功能,都非常好玩,誠心推薦。