簡體   English   中英

如何在彼此之上添加 pyqt5 按鈕?

[英]How can I add pyqt5 buttons on top of each other?

我正在嘗試在 pyqt 中創建一個基本的 25 鍵鍵盤,我已經布置了 15 個白鍵,但正在努力添加剩余的 10 個黑鍵,

這就是我制作鑰匙的方式

from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication([])

top_win = QWidget() 
set_color(top_win, Qt.cyan)
top_win.setAutoFillBackground(True)
top_win.show() 
top_win.resize(1920,1080)
top_win.setWindowTitle("Synth-01") 
top_vlayout = QVBoxLayout()
top_win.setLayout(top_vlayout)

keyboard = QWidget()
keyboard.setMaximumWidth(1410)
top_vlayout.addWidget(keyboard)

keyboard_layout = QHBoxLayout()
keyboard.setAutoFillBackground(True)
keyboard.setLayout(keyboard_layout)

for i in range(15):
    name = "key_" + str(i)
    name = QPushButton()
    name.setMaximumWidth(94)
    name.setMaximumHeight(349)
    keyboard_layout.addWidget(name)

在此處輸入圖片說明

我現在想像這樣在中間添加黑鍵在此處輸入圖片說明

在這種情況下,最好將 QGraphicsScene 與 QGraphicsItem 一起使用,對於這種情況,我將使用 svg:

from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg 

class PianoKey(QtWidgets.QGraphicsRectItem):
    def __init__(self, black=False, rect = QtCore.QRectF(), parent=None):
        super(PianoKey, self).__init__(rect, parent)
        self.m_pressed = False
        self.m_selectedBrush = QtGui.QBrush()
        self.m_brush = QtGui.QBrush(QtCore.Qt.black) if black else QtGui.QBrush(QtCore.Qt.white) 
        self.m_black = black

    def setPressedBrush(self, brush):
        self.m_selectedBrush = brush

    def paint(self, painter, option, widget):
        rendered = QtSvg.QSvgRenderer("key.svg")
        black_pen = QtGui.QPen(QtCore.Qt.black, 1)
        gray_pen = QtGui.QPen(QtGui.QBrush(QtCore.Qt.gray), 1, 
            QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
        if self.m_pressed:
            if self.m_selectedBrush.style() != QtCore.Qt.NoBrush:
                painter.setBrush(self.m_selectedBrush)
            else:
                painter.setBrush(QtWidgets.QApplication.palette().highlight())
        else: 
            painter.setBrush(self.m_brush);
        painter.setPen(black_pen)
        painter.drawRoundedRect(self.rect(), 15, 15, QtCore.Qt.RelativeSize)
        if self.m_black:
            rendered.render(painter, self.rect())
        else:
            points = [
                QtCore.QPointF(self.rect().left()+1.5, self.rect().bottom()-1),
                QtCore.QPointF(self.rect().right()-1, self.rect().bottom()-1),
                QtCore.QPointF(self.rect().right()-1, self.rect().top()+1)
            ]
            painter.setPen(gray_pen)
            painter.drawPolyline(QtGui.QPolygonF(points))

    def mousePressEvent(self, event):
        self.m_pressed = True
        self.update()
        super(PianoKey, self).mousePressEvent(event)
        event.accept()

    def mouseReleaseEvent(self, event):
        self.m_pressed = False
        self.update()
        super(PianoKey, self).mouseReleaseEvent(event)

KEYWIDTH, KEYHEIGHT = 18, 72

class PianoKeyBoard(QtWidgets.QGraphicsView):
    def __init__(self, num_octaves=2,  parent=None):
        super(PianoKeyBoard, self).__init__(parent)
        self.initialize()
        self.m_numOctaves = num_octaves
        scene = QtWidgets.QGraphicsScene(QtCore.QRectF(0, 0, KEYWIDTH * self.m_numOctaves * 7, KEYHEIGHT), self)
        self.setScene(scene)
        numkeys = self.m_numOctaves * 12

        for i in range(numkeys):
            octave = i//12*7
            j = i % 12
            if j >= 5: j += 1
            if j % 2 == 0:
                x = (octave + j/2)*KEYWIDTH
                key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH, KEYHEIGHT), black=False)
            else:
                x = (octave + j//2) * KEYWIDTH  + KEYWIDTH * 6//10 + 1
                key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH * 8//10 - 1, KEYHEIGHT * 6//10 ), black=True)
                key.setZValue(1)
            key.setPressedBrush(QtWidgets.QApplication.palette().highlight())
            self.scene().addItem(key)

    def initialize(self):
        self.setAttribute(QtCore.Qt.WA_InputMethodEnabled, False)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
        self.setViewportUpdateMode(QtWidgets.QGraphicsView.MinimalViewportUpdate)
        self.setRenderHints(QtGui.QPainter.Antialiasing|
            QtGui.QPainter.TextAntialiasing | 
            QtGui.QPainter.SmoothPixmapTransform)
        self.setOptimizationFlag(QtWidgets.QGraphicsView.DontClipPainter, True)
        self.setOptimizationFlag(QtWidgets.QGraphicsView.DontSavePainterState, True)
        self.setOptimizationFlag(QtWidgets.QGraphicsView.DontAdjustForAntialiasing, True)
        self.setBackgroundBrush(QtWidgets.QApplication.palette().base())

    def resizeEvent(self, event):
        super(PianoKeyBoard, self).resizeEvent(event)
        self.fitInView(self.scene().sceneRect(), QtCore.Qt.KeepAspectRatio)

    def sizeHint(self):
        return self.mapFromScene(self.sceneRect()).boundingRect().size()

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    app.setStyle('fusion')
    w = QtWidgets.QWidget()
    lay = QtWidgets.QVBoxLayout(w)
    lay.addWidget(QtWidgets.QLabel("Piano Keyboard", alignment=QtCore.Qt.AlignCenter))
    lay.addWidget(PianoKeyBoard())
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

在此處輸入圖片說明

完整的代碼 + key.svg 可以在這個鏈接上找到

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM