Функция загрузки PyQt при запуске (загрузчик qml) - PullRequest
0 голосов
/ 01 мая 2018

Привет, у меня есть следующая проблема:

это мой рабочий код

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'

Я пытался сделать это с жестко закодированным списком, но список не является проблемой, по какой-то причине мое поле со списком не распознается python. Я не уверен, в чем здесь проблема. Я могу загрузить свою кнопку и добавить к ней событие щелчка (это работает), но я не могу добавить список в свой 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
}




}

1 Ответ

0 голосов
/ 01 мая 2018

Создание и исправление объекта, созданного в QML из Python или C ++, не годится и не требует постоянного сопровождения.

Уместно создать объект в Python или C ++ и отправить его в QML, а затем создать свойства и слоты q, которые позволяют взаимодействовать с QML.

В вашем случае, я предполагаю, что list_fill пытается добавить данные в ComboBox, но ComboBox не имеет четкого метода, поэтому, если вы хотите очистить его, просто передайте ему пустой список, или в вашем случае передайте его новый список.

С другой стороны, вызывать show () не элегантно, лучше установить для свойства visible свойства ApplicationWindow значение 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

...