您好我有以下问题:
这是我的工作代码
import sys
from PyQt5.QtCore import QObject, QUrl, Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
import os
import vlc
from time import sleep
# define VLC instance
instance = vlc.Instance()
# Define VLC player
instance = vlc.Instance('--input-repeat=-1', '--fullscreen')
player = instance.media_player_new()
list_test = []
list_name = []
def prepare_url(url):
media = instance.media_new(url)
player.set_media(media)
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("main", engine)
engine.load('SimpleQML.qml')
win = engine.rootObjects()[0]
win.show()
button = win.findChild(QObject, "playBtn")
def myFunction():
print("A fine piece of text")
button.clicked.connect(myFunction) # works on click
myFunction() #works with out clicking
sys.exit(app.exec_())
现在我想通过执行以下代码来扩展它:
import sys
from PyQt5.QtCore import QObject, QUrl, Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
import os
import vlc
from time import sleep
# define VLC instance
instance = vlc.Instance()
# Define VLC player
instance = vlc.Instance('--input-repeat=-1', '--fullscreen')
player = instance.media_player_new()
list_test = []
list_name = []
def prepare_url(url):
media = instance.media_new(url)
player.set_media(media)
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
ctx = engine.rootContext()
ctx.setContextProperty("main", engine)
engine.load('SimpleQML.qml')
win = engine.rootObjects()[0]
win.show()
button = win.findChild(QObject, "playBtn")
comboBox = win.findChild(QObject, "comboBox")
def myFunction():
print("das")
def list_fill():
with open("config/stations.txt") as f:
content = f.readlines()
content = [x.strip() for x in content]
list_t = [item.split("|")[0] for item in content if item]
list_n = [item.split("|")[1] for item in content if item]
del list_test[:]
del list_name[:]
comboBox.clear()
for x in list_t:
list_test.append(x)
for x in list_n:
list_name.append(x)
addItems(list_name)
button.clicked.connect(myFunction) # works too
myFunction()
list_fill() #calling this crashes program
sys.exit(app.exec_())
并且在最后这是错误
das
Traceback (most recent call last):
File "/home/flea/Desktop/quick qt/main.py", line 65, in <module>
list_fill()
File "/home/flea/Desktop/quick qt/main.py", line 55, in list_fill
comboBox.clear()
AttributeError: 'QObject' object has no attribute 'clear'
我试着用硬编码列表做ti,但列表不是问题,由于某种原因我的组合框不被python识别。我不知道这里有什么问题。 我可以加载我的按钮并向其添加一个click事件(可以工作),但是我无法将列表添加到我的comboBox。
这是我的Qml
import QtQuick 2.10
import QtQuick.Controls 2.1
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.3
ApplicationWindow {
id: applicationWindow
Material.theme: Material.Light
title: qsTr("Test Invoke")
width: 600
height: 500
Row {
id: row
width: 200
height: 400
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
Button{
id: playBtn
objectName: "playBtn"
text : "Play"
checked: false
padding: 6
rightPadding: 8
font.wordSpacing: 0
font.pointSize: 10
font.family: "Times New Roman"
topPadding: 4
highlighted: true
Material.accent: Material.Red
}
Button {
id: stopBtn
objectName: "stopBtn"
text: qsTr("Stop")
anchors.left: playBtn.right
anchors.leftMargin: 5
}
Button {
id: stfBtn
text: qsTr("Save")
objectName: "stfBtn"
anchors.left: stopBtn.right
anchors.leftMargin: 5
}
Button {
id: minimize
objectName: "minBtn"
text: qsTr("Min")
anchors.left: stfBtn.right
anchors.leftMargin: 5
}
}
Column {
id: column
x: 135
y: 100
width: 200
height: 400
TextField {
objectName: "nameText"
id: nameText
width: 300
text: qsTr("")
}
TextField {
objectName: "urlText"
id: urlText
width: 300
text: qsTr("")
}
ComboBox {
objectName: "comboBox"
id: comboBox
width: 200
}
}
Slider {
id: slide
objectName: "slider"
x: 160
y: 311
value: 0.5
}
}
答案 0 :(得分:1)
随着时间的推移,用Python或C ++实例化在QML中创建的对象并不是一件好事也不可维护。
适当的方法是用Python或C ++创建一个对象并将其发送到QML,然后创建允许与QML交互的qproperties和插槽。
在你的情况下,我猜list_fill尝试将数据添加到ComboBox,但是ComboBox没有明确的方法,所以如果你想清理它,只需要传递一个空列表,或者在你的情况下传递它新名单。
另一方面,调用show()并不优雅,最好将ApplicationWindow的visible属性设置为true。
<强> main.py 强>
import sys
import os
from PyQt5.QtCore import QObject, QUrl, Qt, pyqtSlot, pyqtSignal, pyqtProperty
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQml import QQmlApplicationEngine
import vlc
# define VLC instance
instance = vlc.Instance()
# Define VLC player
instance = vlc.Instance('--input-repeat=-1', '--fullscreen')
player = instance.media_player_new()
list_test = []
list_name = []
def prepare_url(url):
media = instance.media_new(url)
player.set_media(media)
class Manager(QObject):
stationsChanged = pyqtSignal()
currentStationChanged = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self.m_stations = []
self.m_currentStation = ""
self.currentStationChanged.connect(self.on_currentStationChanged)
@pyqtProperty(str, notify=currentStationChanged)
def currentStation(self):
return self.m_currentStation
@currentStation.setter
def currentStation(self, val):
if self.m_currentStation == val:
return
self.m_currentStation = val
self.currentStationChanged.emit()
@pyqtProperty(list, notify=stationsChanged)
def stations(self):
return self.m_stations
@stations.setter
def stations(self, val):
if self.m_stations == val:
return
self.m_stations = val[:]
self.stationsChanged.emit()
@pyqtSlot()
def play(self):
print("play", self.currentStation)
@pyqtSlot()
def stop(self):
print("stop")
@pyqtSlot()
def on_currentStationChanged(self):
print(self.currentStation)
def list_fill(self):
l = []
with open("config/stations.txt") as f:
content = f.readlines()
content = [x.strip() for x in content]
list_t = [item.split("|")[0] for item in content if item]
list_n = [item.split("|")[1] for item in content if item]
l += list_t + list_n
self.stations = l
if __name__ == "__main__":
os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
manager = Manager()
ctx = engine.rootContext()
ctx.setContextProperty("Manager", manager)
engine.load('main.qml')
if not engine.rootObjects():
sys.exit(-1)
manager.list_fill()
sys.exit(app.exec_())
<强> main.qml 强>
import QtQuick 2.10
import QtQuick.Controls 2.1
import QtQuick.Window 2.2
import QtQuick.Controls.Material 2.3
ApplicationWindow {
id: applicationWindow
Material.theme: Material.Light
title: qsTr("Test Invoke")
visible: true
width: 600
height: 500
Row {
id: row
width: 200
height: 400
anchors.left: parent.left
anchors.leftMargin: 5
anchors.top: parent.top
anchors.topMargin: 5
Button{
id: playBtn
text : "Play"
checked: false
padding: 6
rightPadding: 8
font.wordSpacing: 0
font.pointSize: 10
font.family: "Times New Roman"
topPadding: 4
highlighted: true
Material.accent: Material.Red
onClicked: Manager.play()
}
Button {
id: stopBtn
text: qsTr("Stop")
anchors.left: playBtn.right
anchors.leftMargin: 5
onClicked: Manager.stop()
}
Button {
id: stfBtn
text: qsTr("Save")
objectName: "stfBtn"
anchors.left: stopBtn.right
anchors.leftMargin: 5
}
Button {
id: minimize
objectName: "minBtn"
text: qsTr("Min")
anchors.left: stfBtn.right
anchors.leftMargin: 5
}
}
Column {
id: column
x: 135
y: 100
width: 200
height: 400
TextField {
id: nameText
width: 300
text: qsTr("")
}
TextField {
id: urlText
width: 300
text: qsTr("")
}
ComboBox {
id: comboBox
width: 200
model: Manager.stations
onCurrentTextChanged: Manager.currentStation = currentText
}
}
Slider {
id: slider
x: 160
y: 311
value: 0.5
}
}
此实现的优点是您可以独立修改设计和逻辑部分。如果您通过setContextProperty
传递对象,它将在所有.qml文件中可见。使用您之前的方法,如果您要使用许多.qml