【问题标题】:PySide2 - Binding model to viewPySide2 - 绑定模型以查看
【发布时间】:2019-09-15 23:26:42
【问题描述】:

希望有人可以帮助我,因为我找不到任何可以在线使用的东西。

我正在为一个 AI 项目构建一个简单的 GUI,并使用 PySide2 和 QML。我已经设法了解如何将功能绑定到按钮并使其工作。但我似乎无法弄清楚如何从 python 字符串列表中填充组合框(然后使用 python 中的选择)。我知道它与属性和模型有关,但我无法让它工作。

这是我的python代码:


import multiprocessing as mp
import sys

import mido
from Fuzzy.aidrummer import AiDrummer

from PySide2.QtWidgets import QApplication
from PySide2.QtQuick import QQuickView
from PySide2.QtCore import QUrl, Slot, QObject, Property, Signal

def run():
    d = AiDrummer('playback', file='../Music/28 coltrane 2.mid', play_instrument='yes', instrument_port='VirtualMIDISynth #1 0',
                  out_port='strike 3', visualize=True)
    d.run()


class Api(QObject):
    proc = None

    def __init__(self):
        QObject.__init__(self)
        self._midi_out = mido.get_output_names()
        print(self._midi_out)
        self._midi_in = mido.get_input_names()

    @Slot()
    def play(self):
        self.proc = mp.Process(target=run)
        self.proc.start()

    @Slot()
    def stop(self):
        try:
            assert isinstance(self.proc, mp.Process)
            self.proc.kill()
        except:
            return

    def read_midi_out(self):
        return self._midi_out

    def set_midi_out(self, val):
        self._midi_out = val

    @Signal
    def midi_out_changed(self):
        pass

    midi_out = Property(list, read_midi_out, set_midi_out, notify=midi_out_changed)


if __name__ == '__main__':
    app = QApplication([])
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    url = QUrl("main.qml")

    api = Api()

    view.setSource(url)
    view.rootContext().setContextProperty('api', api)

    sys.exit(app.exec_())

还有我的 main.qml(带有模型的组合框靠近底部):

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.13
import QtQuick.Controls.Material 2.0

Window {
    id: window
    visible: true
    width: 980
    height: 700
    title: qsTr("AI Drummer")

    Rectangle {
        id: rectangle1
        color: "#191919"
        anchors.rightMargin: 0
        anchors.bottomMargin: 0
        anchors.leftMargin: 0
        anchors.topMargin: 0
        anchors.fill: parent
        clip: true
        rotation: 0

        Rectangle {
            id: rectangle
            x: 711
            width: 400
            height: 200
            color: "#3a3a3a"
            anchors.top: parent.top
            anchors.topMargin: -33
            anchors.right: parent.right
            anchors.rightMargin: -131
            rotation: 45
            clip: true
            Material.theme: Material.Dark
            Material.accent: Material.DeepOrange
        }

        RoundButton {
            id: playButton
            x: 356
            y: 632
            width: 100
            text: "Play"
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 28
            anchors.right: parent.horizontalCenter
            anchors.rightMargin: 70
            onClicked: { api.play()}
        }

        RoundButton {
            id: stopButton
            x: 462
            y: 632
            width: 100
            text: "Stop"
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 28
            anchors.right: parent.horizontalCenter
            anchors.rightMargin: -70
            onClicked: { api.stop()}
        }

        ComboBox {
            id: instrument_port
            x: 214
            y: 637
            width: 120
            height: 30
            anchors.right: parent.horizontalCenter
            anchors.rightMargin: 176
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 33
        }

        ComboBox {
            id: out_port
            x: 68
            y: 637
            width: 120
            height: 30
            anchors.bottomMargin: 33
            anchors.right: parent.horizontalCenter
            anchors.rightMargin: 302
            anchors.bottom: parent.bottom
            model: api.midi_out
        }
    }
    Connections {
        target: api
    }
}

【问题讨论】:

    标签: python qt qml pyside2


    【解决方案1】:

    您的代码有以下错误:

    • midi_out 属性只能读取和通知,因为您无法编写(创建)midi 设备,因此不要实现 setter。

    • midi 设备的名称只在开头获取。如果连接了其他设备?我将不得不关闭并重新打开应用程序,而是添加了允许更新设备名称的“reload()”函数。

    • 如果根元素是Window或ApplicationWindow则必须使用QQmlApplicationEngine,如果是Item则必须使用QQuickView。

    • 如果您想将 PySide2 中的列表作为属性导出,您必须使用 QVariantList (1)

    import multiprocessing as mp
    
    import mido
    
    from Fuzzy.aidrummer import AiDrummer
    
    from PySide2.QtWidgets import QApplication
    from PySide2.QtQml import QQmlApplicationEngine
    from PySide2.QtCore import QUrl, Slot, QObject, Property, Signal
    
    
    def run():
        d = AiDrummer(
            "playback",
            file="../Music/28 coltrane 2.mid",
            play_instrument="yes",
            instrument_port="VirtualMIDISynth #1 0",
            out_port="strike 3",
            visualize=True,
        )
        d.run()
    
    
    class Api(QObject):
        midi_in_names_Changed = Signal()
        midi_out_names_Changed = Signal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.proc = None
            self.reload()
    
        @Slot()
        def reload(self):
            self._midi_in_names = mido.get_input_names()
            self._midi_out_names = mido.get_output_names()
            self.midi_in_names_Changed.emit()
            self.midi_out_names_Changed.emit()
    
        def get_midi_in_names(self):
            return self._midi_in_names
    
        def get_midi_out_names(self):
            return self._midi_out_names
    
        midi_in_names = Property(
            "QVariantList", fget=get_midi_in_names, notify=midi_in_names_Changed
        )
        midi_out_names = Property(
            "QVariantList", fget=get_midi_out_names, notify=midi_out_names_Changed
        )
    
        @Slot()
        def play(self):
            self.proc = mp.Process(target=run)
            self.proc.start()
    
        @Slot()
        def stop(self):
            self.proc.kill()
    
    
    if __name__ == "__main__":
        import os
        import sys
    
        app = QApplication(sys.argv)
    
        api = Api()
    
        engine = QQmlApplicationEngine()
        engine.rootContext().setContextProperty("api", api)
    
        current_dir = os.path.dirname(os.path.realpath(__file__))
    
        url = QUrl.fromLocalFile(os.path.join(current_dir, "main.qml"))
    
        engine.load(url)
    
        if not engine.rootObjects():
            sys.exit(-1)
    
        sys.exit(app.exec_())
    
    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.13
    import QtQuick.Controls.Material 2.0
    
    Window {
        id: window
        visible: true
        width: 980
        height: 700
        title: qsTr("AI Drummer")
    
        Rectangle {
            id: rectangle1
            color: "#191919"
            anchors.rightMargin: 0
            anchors.bottomMargin: 0
            anchors.leftMargin: 0
            anchors.topMargin: 0
            anchors.fill: parent
            clip: true
            rotation: 0
    
            Rectangle {
                id: rectangle
                x: 711
                width: 400
                height: 200
                color: "#3a3a3a"
                anchors.top: parent.top
                anchors.topMargin: -33
                anchors.right: parent.right
                anchors.rightMargin: -131
                rotation: 45
                clip: true
                Material.theme: Material.Dark
                Material.accent: Material.DeepOrange
            }
    
            RoundButton {
                id: playButton
                x: 356
                y: 632
                width: 100
                text: "Play"
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 28
                anchors.right: parent.horizontalCenter
                anchors.rightMargin: 70
                onClicked: { api.play()}
            }
    
            RoundButton {
                id: stopButton
                x: 462
                y: 632
                width: 100
                text: "Stop"
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 28
                anchors.right: parent.horizontalCenter
                anchors.rightMargin: -70
                onClicked: { api.stop()}
            }
    
            ComboBox {
                id: instrument_port
                x: 214
                y: 637
                width: 120
                height: 30
                anchors.right: parent.horizontalCenter
                anchors.rightMargin: 176
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 33
            }
    
            ComboBox {
                id: out_port
                x: 68
                y: 637
                width: 120
                height: 30
                anchors.bottomMargin: 33
                anchors.right: parent.horizontalCenter
                anchors.rightMargin: 302
                anchors.bottom: parent.bottom
                model: api.midi_out_names
            }
        }
    }
    

    (1)Registering a Python list property to QML in pyside2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-11
      • 2016-01-23
      • 1970-01-01
      • 2012-08-27
      • 2016-12-28
      • 1970-01-01
      • 2017-04-17
      • 1970-01-01
      相关资源
      最近更新 更多