我想根据 QMenu 中选中的动作更改每次按下按钮时播放的声音

I want to change the sound that plays every time a button is pressed depending on a checked actiion in a QMenu

我有一个QMainWindow,里面有一个QMenuQLineEdit,还有一个QPushButton

每次单击按钮时,它都会播放声音,然后将文本添加到 QLineEdit。 在我的 QMenu 中,用户必须能够通过选中它来选择播放的声音。

我试图通过在每次检查 QAction 时更改 MainWindow class 中的变量 self.s 来实现此目的,同时取消检查其他 QAction。所以在我的 playsound() 中,我只是把 self.view.s 作为参数。

不过好像只读原作self.view.s,也就是第一声。我更改 self.view.s 的信号不起作用。此外,其他 QActions 并没有像我希望的那样未被选中。

下面是我的代码:

import sys
from functools import partial
from playsound import playsound
from threading import Thread
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.buttons = {}
        self.setWindowTitle("Try")

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        self.lay = QVBoxLayout(central_widget)
        self.lineedit()

        button = {"HEY! ": (0, 0, 0, 0)}

        page = QWidget()
        layout = QGridLayout(page)
        for btnText, pos in button.items():
            self.buttons[btnText] = QPushButton(btnText)
            layout.addWidget(self.buttons[btnText], *pos)

        self.lay.addWidget(page)
        self.music()

    def music(self):
        self.s = 'sound1.mp3'
        
        self.x = 'sound1.mp3'
        self.y = 'sound2.mp3'
        self.z = 'disable.mp3'

    def lineedit(self):
        self.le = QLineEdit()
        self.le.setFixedHeight(35)
        self.lay.addWidget(self.le)

    def set_lineedit(self, text):
        self.le.setText(text)
        self.le.setFocus()

    def line(self):
        return self.le.text()


class Menu:

    def __init__(self, MainWindow):

        super().__init__()

        self.view = MainWindow
        self.menuBar()
        #self.actionSignals()

    def menuBar(self):
        self.menuBar = QMenuBar()
        self.view.setMenuBar(self.menuBar)

        self.menu = QMenu(self.menuBar)
        self.menu.setTitle('Menu')

        self.sounds = QMenu(self.menu)
        self.sounds.setTitle('Select Sound')

        self.sound1 = QAction(self.menuBar)
        self.sound2 = QAction(self.menuBar)
        self.disable = QAction(self.menuBar)

        self.mute = QAction(self.menuBar)
        self.mute.setText('Mute Background')
        self.mute.setCheckable(True)
        self.mute.setChecked(False)

        self.sound1.setText('Sound 1')
        self.sound1.setCheckable(True)
        self.sound1.setChecked(True)
        self.sound2.setText('Sound 2')
        self.sound2.setCheckable(True)
        self.sound2.setChecked(False)
        self.disable.setText('Disable Sound')
        self.disable.setCheckable(True)
        self.disable.setChecked(False)

        self.sounds.addAction(self.sound1)
        self.sounds.addAction(self.sound2)
        self.sounds.addAction(self.disable)


        self.menuBar.addAction(self.menu.menuAction())
        self.menu.addAction(self.mute)
        self.menu.addAction(self.sounds.menuAction())

    def menu_signals(self):
        
        self.sound1.triggered.connect(self.sound_1)
        self.sound2.triggered.connect(self.sound_2)
        self.disable.triggered.connect(self.disabled)

    def sound_1(self, checked):
        
        if checked:
            self.sound2.setChecked(False)
            self.disable.setChecked(False)
            self.view.s = self.view.x

        else:
            self.sound1.setChecked(True)


    def sound_2(self, checked):

        if checked:
            self.sound1.setChecked(False)
            self.disable.setChecked(False)
            self.view.s = self.view.y

        else:
            self.sound2.setChecked(True)

    def disabled(self, checked):
        
        if checked:
            self.sound2.setChecked(False)
            self.sound1.setChecked(False)
            self.view.s = self.view.z

        else:
            self.sound1.setChecked(True)

class Controller:

    def __init__(self, MainWindow):

        self.view = MainWindow
        self.connectSignals()

    def background(self):
        while True:
            playsound('background.mp3')

    def playsound(self):
        playsound(self.view.s, False)

    def buildExpression(self, sub_exp):

        expression = self.view.line() + sub_exp
        self.view.set_lineedit(expression)

    def connectSignals(self):

        for btnText, btn in self.view.buttons.items():
            self.view.buttons[btnText].clicked.connect(self.playsound)
            self.view.buttons[btnText].clicked.connect(partial(self.buildExpression, btnText))

app = QApplication(sys.argv)
w = MainWindow()
x = Controller(w)
Thread(target = x.background, daemon = True).start()
m = Menu(w)
w.show()
app.exec()

我希望能够根据菜单栏中选中的 QAction 更改 playsound() 中的值。选中一个 QAction 时,应取消选中其他 QAction。

这是行动组发挥作用的地方。 QActionGroup allows for mutually exclusive actions. It also provides convenient access to the selected action through the checkedAction 方法。

  1. 创建一个 QActionGroup 对象(例如 self.soundGroup = QActionGroup(self)
  2. 以群组为父项创建您的操作(例如 self.sound1 = QAction(self.soundGroup)
  3. 对于你的每一个动作,将它们对应的声音设置为它们的数据,例如self.sound1.setData('sound1.mp3')
  4. 确保操作组是独占的(我相信这是默认设置,但您可以使用 self.soundGroup.setExclusive(True)
  5. 使用self.soundGroup.checkedAction()代替self.view.s获取选中的动作(选择的声音):playsound(self.soundGroup.checkedAction().data(), False)

您不再需要在 self.view.s 的操作和更新之间进行任何连接。只需删除所有这些。