如何解决是否可以使用 PYQT5 中的元素创建一个类
我正在尝试创建一个 GUI 键盘。我正在使用 QPushButton 来复制密钥。我还没有专注于将它链接到 MIDI。但是,我想知道是否可以使用 QPushButton 的属性创建一个类。我的意思是像 QPushButton.move/resize/setStyleSheet 这样的函数。
就目前而言,我的代码很长(如下所示)。这是由于不断重复代码来制作每个按钮。但是,我注意到诸如大小、样式表和位置(仅在 y 轴上)等属性是相同的,主要区别在于黑白键之间的 x 轴和 y 轴。如果我要创建一个类,我将如何创建具有各种属性的对象?
再一次,如果我的逻辑有缺陷或我犯了任何错误,请随时告诉我。
import sys
from PyQt5.QtWidgets import QMainWindow,QApplication,QWidget,QPushButton,QAction,QLineEdit,QMessageBox,QLabel \,QDialog
from PyQt5.QtGui import QIcon,QHideEvent,QFont,QPixmap
from PyQt5.QtCore import pyqtSlot,QObject,QSize
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'Piano '
self.left = 620
self.top =250
self.width = 1920
self.height = 1080
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)
self.setFixedWidth(self.width)
self.setFixedHeight(self.height)
self.setStyleSheet("background-color:lightgrey")
self.setWindowIcon(QIcon('img.png'))
# Create a button in the window
self.button1 = QPushButton('C',self)
self.button1.move(10,650)
self.button1.setFont(QFont('Arial',14))
self.button1.resize(100,400)
self.button1.setStyleSheet("background-color:white; border :1px solid ;") #Black Not Working
self.button2 = QPushButton('D',self)
self.button2.move(110,650)
self.button2.setFont(QFont('Arial',14))
self.button2.resize(100,400)
self.button2.setStyleSheet("background-color:white; border :1px solid ;")
self.button3 = QPushButton('E',self)
self.button3.move(210,650)
self.button3.setFont(QFont('Arial',14))
self.button3.resize(100,400)
self.button3.setStyleSheet("background-color:white; border :1px solid ;")
self.button4 = QPushButton('F',self)
self.button4.move(310,650)
self.button4.setFont(QFont('Arial',14))
self.button4.resize(100,400)
self.button4.setStyleSheet("background-color:white; border :1px solid ;")
self.button5 = QPushButton('G',self)
self.button5.move(410,650)
self.button5.setFont(QFont('Arial',14))
self.button5.resize(100,400)
self.button5.setStyleSheet("background-color:white; border :1px solid ;")
self.button6 = QPushButton('A',self)
self.button6.move(510,650)
self.button6.setFont(QFont('Arial',14))
self.button6.resize(100,400)
self.button6.setStyleSheet("background-color:white; border :1px solid ;")
self.button7 = QPushButton('B',self)
self.button7.move(610,650)
self.button7.setFont(QFont('Arial',14))
self.button7.resize(100,400)
self.button7.setStyleSheet("background-color:white; border :1px solid ;")
self.button8 = QPushButton('C2',self)
self.button8.move(710,650)
self.button8.setFont(QFont('Arial',14))
self.button8.resize(100,400)
self.button8.setStyleSheet("background-color:white; border :1px solid ;")
self.button2 = QPushButton('D2',self)
self.button2.move(810,400)
self.button2.setStyleSheet("background-color:white; border :1px solid ;")
self.button3 = QPushButton('E2',self)
self.button3.move(910,400)
self.button3.setStyleSheet("background-color:white; border :1px solid ;")
self.button4 = QPushButton('F2',self)
self.button4.move(1010,400)
self.button4.setStyleSheet("background-color:white; border :1px solid ;")
self.button5 = QPushButton('G2',self)
self.button5.move(1110,400)
self.button5.setStyleSheet("background-color:white; border :1px solid ;")
self.button6 = QPushButton('A2',self)
self.button6.move(1210,400)
self.button6.setStyleSheet("background-color:white; border :1px solid ;")
self.button7 = QPushButton('B2',self)
self.button7.move(1310,400)
self.button7.setStyleSheet("background-color:white; border :1px solid ;")
self.button8 = QPushButton('C3',self)
self.button8.move(1410,400)
self.button8.setStyleSheet("background-color:white; border :1px solid ;")
self.button1up = QPushButton('C#',self)
self.button1up.move(85,650)
self.button1up.setFont(QFont('Arial',14))
self.button1up.resize(50,300)
self.button1up.setStyleSheet("background-color:black; border :1px solid ;")
self.button2up = QPushButton('D#',self)
self.button2up.move(185,650)
self.button2up.setFont(QFont('Arial',14))
self.button2up.resize(50,300)
self.button2up.setStyleSheet("background-color:black; border :1px solid ;")
self.button3up = QPushButton('F#',self)
self.button3up.move(385,650)
self.button3up.setFont(QFont('Arial',14))
self.button3up.resize(50,300)
self.button3up.setStyleSheet("background-color:black; border :1px solid ;")
self.button4up = QPushButton('G#',self)
self.button4up.move(485,650)
self.button4up.setFont(QFont('Arial',14))
self.button4up.resize(50,300)
self.button4up.setStyleSheet("background-color:black; border :1px solid ;")
self.button5up = QPushButton('A#',self)
self.button5up.move(585,650)
self.button5up.setFont(QFont('Arial',14))
self.button5up.resize(50,300)
self.button5up.setStyleSheet("background-color:black; border :1px solid ;")
self.button6up = QPushButton(self)
self.button6up.move(785,650)
self.button6up.setFont(QFont('Arial',14))
self.button6up.resize(50,300)
self.button6up.setStyleSheet("background-color:black; border :1px solid ;")
self.button7up = QPushButton(self)
self.button7up.move(885,650)
self.button7up.setFont(QFont('Arial',14))
self.button7up.resize(50,300)
self.button7up.setStyleSheet("background-color:black; border :1px solid ;")
self.button8up = QPushButton(self)
self.button8up.move(1085,650)
self.button8up.setFont(QFont('Arial',14))
self.button8up.resize(50,300)
self.button8up.setStyleSheet("background-color:black; border :1px solid ;")
self.button9up = QPushButton(self)
self.button9up.move(1185,650)
self.button9up.setFont(QFont('Arial',14))
self.button9up.resize(50,300)
self.button9up.setStyleSheet("background-color:black; border :1px solid ;")
self.button10up = QPushButton(self)
self.button10up.move(1285,650)
self.button10up.setFont(QFont('Arial',14))
self.button10up.resize(50,300)
self.button10up.setStyleSheet("background-color:black; border :1px solid ;")
# connect button to function on_click
self.button1.clicked.connect(self.b1)
self.show()
@pyqtSlot()
def b1(self):
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
解决方法
第一个逻辑解决方案是为每个键创建一个数据列表,如下所示:
KeyMap = (
# key name,x,y,width,height,color
('C',10,650,100,400,'white'),# ...
('C#',85,50,300,'black'),)
然后循环遍历列表:
baseStyle = 'background-color: {}; border :1px solid;'
for key,color in KeyMap:
button = QPushButton('key',self)
button.setGeometry(x,height)
button.setFont(QFont('Arial',14))
button.setStyleSheet(baseStyle.format(color)
不幸的是,虽然上面的方法对于简单的例子可能很好用,但我可以根据经验告诉你,它不适用于这种情况(类似钢琴的键盘),主要是因为以下两个原因:
- 固定几何图形很少是一个好主意,如果您出于任何原因需要调整键盘大小(包括使其适合屏幕,特别是如果它很小),它会使所有东西都更难手工编写;
- 您可能需要将键盘扩展到更多八度或想要更改键的宽度和高度之间的比例;
我有过尝试创建 UI 键盘的经验,我最终得到了一个完全自定义的小部件(基于 QGraphicsView),但对于简单的情况,以下可能适合您的需求。
诀窍是使用 Qt 网格布局,它有一个有趣的“功能”,即允许项目在放置在其“单元格”之间时重叠。
以下代码为每个白键使用 2 行(一个用于顶部的白键和黑键,一个位于底部的用于白键)和 3 列用于每个白键:而白键使用所有三列,而黑键使用第三列前一个白键,以及下一个白键;想象一张这样的桌子:
+---+---+---+---+---+---+---+---+---+
| · | · | | · | · |
| · | C | | D | · |
| · | sharp | | sharp | · |
| · | · | | · | · |
+ · · · +---+---+ · +---+---+ · · · +
| · · | · · | · · |
| · C · | · D · | · E · |
| · · | · · | · · |
+---+---+---+---+---+---+---+---+---+
然后您可以为按键创建一个基本类(包括按键触发的信号和释放),并使用简单的列表轻松获取按键是白色还是黑色并放置/相应地设置样式。
可选参数显然是针对八度范围和八度开始(因为您可能要使用 MIDI,这很重要,因为您会自动获得键值)。
from PyQt5 import QtCore,QtWidgets
BlackIdx = 1,3,-1,6,8,10
WhiteIdx = 0,2,4,5,7,9,11
KeyNames = 'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'
class KeyButton(QtWidgets.QPushButton):
triggered = QtCore.pyqtSignal(int,bool)
def __init__(self,key,isBlack=False):
super().__init__()
self.key = key
# this will be used by the stylesheet
self.setProperty('isBlack',isBlack)
octave,keyIdx = divmod(key,12)
self.setText('{}{}'.format(KeyNames[keyIdx],octave))
self.setMinimumWidth(25)
self.setMinimumSize(25,80 if isBlack else 120)
# ensure that the key expands vertically
self.setSizePolicy(QtWidgets.QSizePolicy.Preferred,QtWidgets.QSizePolicy.Expanding)
# connect the pressed and released (not clicked!) signals to our custom one
self.pressed.connect(lambda: self.triggered.emit(key,True))
self.released.connect(lambda: self.triggered.emit(key,False))
class Keyboard(QtWidgets.QWidget):
def __init__(self,octaves=2,octaveStart=3):
super().__init__()
layout = QtWidgets.QGridLayout(self)
# the ratio between key heights: white keys are 1/3 longer than black ones
layout.setRowStretch(0,2)
layout.setRowStretch(1,1)
layout.setSpacing(0)
blackKeys = []
for octave in range(octaves):
for k in range(12):
isBlack = k in BlackIdx
keyButton = KeyButton(k + (octaveStart + octave) * 12,isBlack)
keyButton.triggered.connect(self.keyTriggered)
if isBlack:
keyPos = BlackIdx.index(k)
# column based on the index of the key list,plus 2 "cells"
col = keyPos * 3 + 2
# only one row in the layout
vSpan = 1
# only two columns
hSpan = 2
blackKeys.append(keyButton)
else:
keyPos = WhiteIdx.index(k)
col = keyPos * 3
# two rows
vSpan = 2
# three columns
hSpan = 3
col += octave * 21
layout.addWidget(keyButton,col,vSpan,hSpan)
# "blank" spacers between E-F and B-C,to keep the spacings homogeneous
efSpacer = QtWidgets.QWidget()
efSpacer.setMinimumWidth(25)
layout.addWidget(efSpacer,octave * 21 + 8,1,2)
efSpacer.lower()
baSpacer = QtWidgets.QWidget()
baSpacer.setMinimumWidth(25)
layout.addWidget(baSpacer,octave * 21 + 20,2)
baSpacer.lower()
# the last C note,with a minimum width a bit bigger
octave += 1
lastButton = KeyButton((octaveStart + octave) * 12)
lastButton.setMinimumWidth(32)
lastButton.triggered.connect(self.keyTriggered)
layout.addWidget(lastButton,octave * 21,3)
# raise all black keys on top of everything else
for keyButton in blackKeys:
keyButton.raise_()
# set the stretch of layout cells,if it's in the middle,it's bigger
for col in range(layout.columnCount()):
if col % 3 == 1:
layout.setColumnStretch(col,4)
else:
layout.setColumnStretch(col,3)
self.setStyleSheet('''
KeyButton {
color: rgb(50,50);
border: 1px outset rgb(128,128,128);
border-radius: 2px;
background: white;
}
KeyButton:pressed {
border-style: inset;
}
KeyButton[isBlack=true] {
color: rgb(250,250,250);
background: black;
}
KeyButton[isBlack=true]:pressed {
background: rgb(50,50);
}
''')
def keyTriggered(self,pressed):
octave,12)
keyName = '{}{}'.format(KeyNames[keyIdx],octave)
state = 'pressed' if pressed else 'released'
print('Key {} ({}) {}'.format(key,keyName,state))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
keyboard = Keyboard()
keyboard.show()
sys.exit(app.exec_())
PS:我用几年前制作的键盘创建了一个要点。请注意,这段代码已经很旧了,当时我仍然有点缺乏经验(您可能需要更改 import
语句,因为它针对的是 Qt.py 模块,它允许透明地集成 PyQt4 /5 和 PySide):
https://gist.github.com/MaurizioB/43a053575f17eae371a9d7394e66a46e
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。