RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1545476
Accepted
DaYa
DaYa
Asked:2023-10-12 23:30:09 +0000 UTC2023-10-12 23:30:09 +0000 UTC 2023-10-12 23:30:09 +0000 UTC

钢琴键盘、图形用户界面

  • 772

我正在尝试用Python实现钢琴键盘。
上网查了一下,没有发现什么值得的,要么太复杂,要么太原始,但我只需要一个漂亮的钢琴键盘,每个键都有响应。

决定在没有数据库的情况下自己完成所有事情,我转向Tkinter。
我不想写每个键,所以我在循环中生成它们。

出现了一个问题:我不明白如何让它看起来像钢琴键盘;如果我移动黑键,它们只会交替, E和F
之间不会有空格。

最终目标:用Python制作一个看起来像钢琴键盘的钢琴键盘。

主要.py:

from tkinter import *


root = Tk()
root.geometry('900x500')
root.resizable(width = False, height = False)

def black_clicked(black_buttons):
    print(black_buttons)  

for black_buttons in range(6):
    btn = Button(text = f'{black_buttons}', bg = 'black', command=lambda black_buttons = black_buttons: black_clicked(black_buttons))
    btn.grid(column = black_buttons, row=0)

for white_buttons in range(8):
    btn = Button(text = f'{white_buttons}', bg ='white')
    btn.grid(column = white_buttons, row=1)

root.mainloop()
python
  • 1 1 个回答
  • 57 Views

1 个回答

  • Voted
  1. Best Answer
    S. Nick
    2023-10-13T23:27:12Z2023-10-13T23:27:12Z

    如果您突然决定转向PyQt,那么作为一种选择,它可能看起来像这样:

    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
            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)
    
            self.setSizePolicy(
                QtWidgets.QSizePolicy.Preferred,
                QtWidgets.QSizePolicy.Expanding
            )
            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)
            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)
                        col = keyPos * 3 + 2
                        vSpan = 1
                        hSpan = 2
                        blackKeys.append(keyButton)
                    else:
                        keyPos = WhiteIdx.index(k)
                        col = keyPos * 3
                        vSpan = 2
                        hSpan = 3
                    col += octave * 21
                    layout.addWidget(keyButton, 0, col, vSpan, hSpan)
    
                efSpacer = QtWidgets.QWidget()
                efSpacer.setMinimumWidth(25)
                layout.addWidget(efSpacer, 0, octave * 21 + 8, 1, 2)
                efSpacer.lower()
                baSpacer = QtWidgets.QWidget()
                baSpacer.setMinimumWidth(25)
                layout.addWidget(baSpacer, 0, octave * 21 + 20, 1, 2)
                baSpacer.lower()
    
            octave += 1
            lastButton = KeyButton((octaveStart + octave) * 12)
            lastButton.setMinimumWidth(32)
            lastButton.triggered.connect(self.keyTriggered)
            layout.addWidget(lastButton, 0, octave * 21, 2, 3)
    
            for keyButton in blackKeys:
                keyButton.raise_() 
            
            for col in range(layout.columnCount()):
                if col % 3 == 1:
                    layout.setColumnStretch(col, 4)
                else:
                    layout.setColumnStretch(col, 3)
            
            self.setStyleSheet('''
                KeyButton {
                    border: 1px outset palette(dark);
                    border-radius: 2px;
                    background: white;
                }
                KeyButton:pressed {
                    border-style: inset;
                }
                KeyButton[isBlack=true] {
                    color: palette(light);
                    background: black;
                }
                KeyButton[isBlack=true]:pressed {
                    background: rgb(50, 50, 50);
                }
            ''')
    
        def keyTriggered(self, key, pressed):
            octave, keyIdx = divmod(key, 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_())
    

    在此输入图像描述

    • 3

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5