PySide2 - 要查看的绑定模型
PySide2 - Binding model to view
希望有人能帮助我,因为我找不到任何在线可用的东西。
我正在为 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
}
}
您的代码存在以下错误:
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)
希望有人能帮助我,因为我找不到任何在线可用的东西。
我正在为 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
}
}
您的代码存在以下错误:
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)