是否可以使用 PYQT5 中的元素创建一个类

如何解决是否可以使用 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,这很重要,因为您会自动获得键值)。

nice keyboard

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 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res