Преглед на файлове

新增 2个官方用例

mrh преди 2 години
родител
ревизия
b17049d7f3

+ 1 - 1
1-YourFirstQtQuickQMLApplication/ui/view.qml

@@ -8,7 +8,7 @@ Rectangle {
 
 
     Text {
     Text {
         text: "Hello World"
         text: "Hello World"
-        // 使文本显示在id为:main的对象的中心,在本例中为矩形
+        // anchors 鏄�敋锛屽湪绐楀彛涓�績瀵归綈
         anchors.centerIn: main
         anchors.centerIn: main
     }
     }
 }
 }

BIN
3-QMLCountry/logo.png


+ 46 - 0
3-QMLCountry/main.py

@@ -0,0 +1,46 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+import urllib.request
+import json
+from pathlib import Path
+
+from PySide6.QtQuick import QQuickView
+from PySide6.QtCore import QStringListModel, QUrl
+from PySide6.QtGui import QGuiApplication
+
+
+if __name__ == '__main__':
+
+    #get our data
+    url = "http://country.io/names.json"
+    response = urllib.request.urlopen(url)
+    data = json.loads(response.read().decode('utf-8'))
+
+    #Format and sort the data
+    data_list = list(data.values())
+    data_list.sort()
+
+    #Set up the application window
+    app = QGuiApplication(sys.argv)
+    view = QQuickView()
+    view.setResizeMode(QQuickView.SizeRootObjectToView)
+
+    #Expose the list to the Qml code
+    my_model = QStringListModel()
+    my_model.setStringList(data_list)
+    view.setInitialProperties({"myModel": my_model})
+
+    #Load the QML file
+    qml_file = Path(__file__).parent / "view.qml"
+    view.setSource(QUrl.fromLocalFile(qml_file.resolve()))
+
+    #Show the window
+    if view.status() == QQuickView.Error:
+        sys.exit(-1)
+    view.show()
+
+    #execute and cleanup
+    app.exec()
+    del view

BIN
3-QMLCountry/newpyproject.png


BIN
3-QMLCountry/projectsmode.png


BIN
3-QMLCountry/pyprojname.png


BIN
3-QMLCountry/pyprojxplor.png


BIN
3-QMLCountry/qmlapplication.png


+ 132 - 0
3-QMLCountry/qmlapplication.rst

@@ -0,0 +1,132 @@
+#########################
+QML Application Tutorial
+#########################
+
+This tutorial provides a quick walk-through of a python application
+that loads a QML file. QML is a declarative language that lets you
+design UIs faster than a traditional language, such as C++. The
+QtQml and QtQuick modules provides the necessary infrastructure for
+QML-based UIs.
+
+In this tutorial, you'll also learn how to provide data from Python
+as a QML initial property, which is then consumed by the ListView
+defined in the QML file.
+
+Before you begin, install the following prerequisites:
+
+* The `PySide6 <https://pypi.org/project/PySide6/>`_ Python packages.
+* Qt Creator v4.9 beta1 or later from
+  `https://download.qt.io
+  <https://download.qt.io/snapshots/qtcreator/>`_.
+
+
+The following step-by-step instructions guide you through application
+development process using Qt Creator:
+
+#. Open Qt Creator and select **File > New File or Project..** menu item
+   to open following dialog:
+
+   .. image:: newpyproject.png
+
+#. Select **Qt for Python - Empty** from the list of application templates
+   and select **Choose**.
+
+   .. image:: pyprojname.png
+
+#. Give a **Name** to your project, choose its location in the
+   filesystem, and select **Finish** to create an empty ``main.py``
+   and ``main.pyproject``.
+
+   .. image:: pyprojxplor.png
+
+   This should create a ``main.py`` and ```main.pyproject`` files
+   for the project.
+
+#. Download :download:`view.qml<view.qml>` and :download:`logo.png <logo.png>`
+   and move them to your project folder.
+
+#. Double-click on ``main.pyproject`` to open it in edit mode, and append
+   ``view.qml`` and ``logo.png`` to the **files** list. This is how your
+   project file should look after this change:
+
+   .. code::
+
+    {
+        "files": ["main.py", "view.qml", "logo.png"]
+    }
+
+#. Now that you have the necessary bits for the application, import the
+   Python modules in your ``main.py``, and download country data and
+   format it:
+
+   .. literalinclude:: main.py
+      :linenos:
+      :lines: 3-23
+      :emphasize-lines: 7-9,14-17
+
+#. Now, set up the application window using
+   :ref:`PySide6.QtGui.QGuiApplication<qguiapplication>`, which manages the application-wide
+   settings.
+
+   .. literalinclude:: main.py
+      :linenos:
+      :lines: 3-28
+      :emphasize-lines: 23-25
+
+   .. note:: Setting the resize policy is important if you want the
+      root item to resize itself to fit the window or vice-a-versa.
+      Otherwise, the root item will retain its original size on
+      resizing the window.
+
+#. You can now expose the ``data_list`` variable as a QML initial
+   property, which will be consumed by the QML ListView item in ``view.qml``.
+
+   .. literalinclude:: main.py
+      :linenos:
+      :lines: 3-33
+      :emphasize-lines: 28-31
+
+#. Load the ``view.qml`` to the ``QQuickView`` and call ``show()`` to
+   display the application window.
+
+   .. literalinclude:: main.py
+      :linenos:
+      :lines: 3-42
+      :emphasize-lines: 33-40
+
+#. Finally, execute the application to start the event loop and clean up.
+
+   .. literalinclude:: main.py
+      :linenos:
+      :lines: 3-
+      :emphasize-lines: 42-44
+
+#. Your application is ready to be run now. Select **Projects** mode to
+   choose the Python version to run it.
+
+   .. image:: projectsmode.png
+
+Run the application by using the ``CTRL+R`` keyboard shortcut to see if it
+looks like this:
+
+.. image:: qmlapplication.png
+
+You could also watch the following video tutorial for guidance to develop
+this application:
+
+.. raw:: html
+
+    <div style="position: relative; padding-bottom: 56.25%; height: 0;
+    overflow: hidden; max-width: 100%; height: auto;">
+        <iframe src="https://www.youtube.com/embed/JxfiUx60Mbg" frameborder="0"
+        allowfullscreen style="position: absolute; top: 0; left: 0;
+        width: 100%; height: 100%;">
+        </iframe>
+    </div>
+
+********************
+Related information
+********************
+
+* `QML Reference <https://doc.qt.io/qt-5/qmlreference.html>`_
+* :doc:`../qmlintegration/qmlintegration`

+ 56 - 0
3-QMLCountry/view.qml

@@ -0,0 +1,56 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+
+Page {
+    width: 640
+    height: 480
+    required property var myModel
+
+    header: Label {
+        color: "#15af15"
+        text: qsTr("Where do people use Qt?")
+        font.pointSize: 17
+        font.bold: true
+        font.family: "Arial"
+        renderType: Text.NativeRendering
+        horizontalAlignment: Text.AlignHCenter
+        padding: 10
+    }
+    Rectangle {
+        id: root
+        width: parent.width
+        height: parent.height
+
+        Image {
+            id: image
+            fillMode: Image.PreserveAspectFit
+            anchors.centerIn: root
+            source: "./logo.png"
+            opacity: 0.5
+
+        }
+
+        ListView {
+            id: view
+            anchors.fill: root
+            anchors.margins: 25
+            model: myModel
+            delegate: Text {
+                anchors.leftMargin: 50
+                font.pointSize: 15
+                horizontalAlignment: Text.AlignHCenter
+                text: display
+            }
+        }
+    }
+    NumberAnimation {
+        id: anim
+        running: true
+        target: view
+        property: "contentY"
+        duration: 500
+    }
+}

BIN
4-QMl-SQL-PySide6/chat-database.sqlite3


+ 28 - 0
4-QMl-SQL-PySide6/chat.log

@@ -0,0 +1,28 @@
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Message: "FASD
+" 
+ Received by: "machine"
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Message: "·¢ËͶË
+" 
+ Received by: "machine"
+DEBUG:root:Message: "VSµÄ·ç¸ñ" 
+ Received by: "machine"
+DEBUG:root:Message: "helo" 
+ Received by: "machine"
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Message: "·¢" 
+ Received by: "machine"
+DEBUG:root:Message: "ɶ¶¼¸ã
+" 
+ Received by: "machine"
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Message: "sen by me" 
+ Received by: "machine"
+DEBUG:root:Table was loaded successfully.
+DEBUG:root:Message: "yes
+" 
+ Received by: "machine"
+DEBUG:root:Table was loaded successfully.

+ 98 - 0
4-QMl-SQL-PySide6/chat.qml

@@ -0,0 +1,98 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import ChatModel
+
+ApplicationWindow {
+    id: window
+    title: qsTr("Chat")
+    width: 640
+    height: 960
+    visible: true
+
+    SqlConversationModel {
+        id: chat_model
+    }
+
+    ColumnLayout {
+        anchors.fill: parent
+
+        ListView {
+            id: listView
+            Layout.fillWidth: true
+            Layout.fillHeight: true
+            Layout.margins: pane.leftPadding + messageField.leftPadding
+            displayMarginBeginning: 40
+            displayMarginEnd: 40
+            verticalLayoutDirection: ListView.BottomToTop
+            spacing: 12
+            model: chat_model
+            delegate: Column {
+                anchors.right: sentByMe ? listView.contentItem.right : undefined
+                spacing: 6
+
+                readonly property bool sentByMe: model.recipient !== "Me"
+                Row {
+                    id: messageRow
+                    spacing: 6
+                    anchors.right: sentByMe ? parent.right : undefined
+
+                    Rectangle {
+                        width: Math.min(messageText.implicitWidth + 24,
+                            listView.width - (!sentByMe ? messageRow.spacing : 0))
+                        height: messageText.implicitHeight + 24
+                        radius: 15
+                        color: sentByMe ? "lightgrey" : "steelblue"
+
+                        Label {
+                            id: messageText
+                            text: model.message
+                            color: sentByMe ? "black" : "white"
+                            anchors.fill: parent
+                            anchors.margins: 12
+                            wrapMode: Label.Wrap
+                        }
+                    }
+                }
+
+                Label {
+                    id: timestampText
+                    text: Qt.formatDateTime(model.timestamp, "d MMM hh:mm")
+                    color: "lightgrey"
+                    anchors.right: sentByMe ? parent.right : undefined
+                }
+            }
+
+            ScrollBar.vertical: ScrollBar {}
+        }
+
+        Pane {
+            id: pane
+            Layout.fillWidth: true
+
+            RowLayout {
+                width: parent.width
+
+                TextArea {
+                    id: messageField
+                    Layout.fillWidth: true
+                    placeholderText: qsTr("Compose message")
+                    wrapMode: TextArea.Wrap
+                }
+
+                Button {
+                    id: sendButton
+                    text: qsTr("Send")
+                    enabled: messageField.length > 0
+                    onClicked: {
+                        listView.model.send_message("machine", messageField.text, "Me");
+                        messageField.text = "";
+                    }
+                }
+            }
+        }
+    }
+}

+ 52 - 0
4-QMl-SQL-PySide6/main.py

@@ -0,0 +1,52 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import sys
+import logging
+
+from PySide6.QtCore import QDir, QFile, QUrl
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlApplicationEngine
+from PySide6.QtSql import QSqlDatabase
+
+# We import the file just to trigger the QmlElement type registration.
+import sqlDialog
+
+logging.basicConfig(filename="chat.log", level=logging.DEBUG)
+logger = logging.getLogger("logger")
+
+
+def connectToDatabase():
+    database = QSqlDatabase.database()
+    if not database.isValid():
+        database = QSqlDatabase.addDatabase("QSQLITE")
+        if not database.isValid():
+            logger.error("Cannot add database")
+
+    write_dir = QDir("")
+    if not write_dir.mkpath("."):
+        logger.error("Failed to create writable directory")
+
+    # Ensure that we have a writable location on all devices.
+    abs_path = write_dir.absolutePath()
+    filename = f"{abs_path}/chat-database.sqlite3"
+
+    # When using the SQLite driver, open() will create the SQLite
+    # database if it doesn't exist.
+    database.setDatabaseName(filename)
+    if not database.open():
+        logger.error("Cannot open database")
+        QFile.remove(filename)
+
+
+if __name__ == "__main__":
+    app = QGuiApplication()
+    connectToDatabase()
+
+    engine = QQmlApplicationEngine()
+    engine.load(QUrl("chat.qml"))
+
+    if not engine.rootObjects():
+        sys.exit(-1)
+
+    app.exec()

+ 1 - 0
4-QMl-SQL-PySide6/readme.md

@@ -0,0 +1 @@
+[source code on github](https://github.com/qtproject/pyside-pyside-setup/tree/d509e486fa2a931c177292ce0cb81ceecd24c81d/sources/pyside6/doc/tutorials/qmlsqlintegration)

+ 116 - 0
4-QMl-SQL-PySide6/sqlDialog.py

@@ -0,0 +1,116 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import datetime
+import logging
+
+from PySide6.QtCore import Qt, Slot
+from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlRecord, QSqlTableModel
+from PySide6.QtQml import QmlElement
+
+table_name = "Conversations"
+QML_IMPORT_NAME = "ChatModel"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+def createTable():
+    if table_name in QSqlDatabase.database().tables():
+        return
+
+    query = QSqlQuery()
+    if not query.exec_(
+        """
+        CREATE TABLE IF NOT EXISTS 'Conversations' (
+            'author' TEXT NOT NULL,
+            'recipient' TEXT NOT NULL,
+            'timestamp' TEXT NOT NULL,
+            'message' TEXT NOT NULL,
+        FOREIGN KEY('author') REFERENCES Contacts ( name ),
+        FOREIGN KEY('recipient') REFERENCES Contacts ( name )
+        )
+        """
+    ):
+        logging.error("Failed to query database")
+
+    # This adds the first message from the Bot
+    # and further development is required to make it interactive.
+    query.exec_(
+        """
+        INSERT INTO Conversations VALUES(
+            'machine', 'Me', '2019-01-07T14:36:06', 'Hello!'
+        )
+        """
+    )
+    logging.info(query)
+
+
+@QmlElement
+class SqlConversationModel(QSqlTableModel):
+    def __init__(self, parent=None):
+        super(SqlConversationModel, self).__init__(parent)
+
+        createTable()
+        self.setTable(table_name)
+        self.setSort(2, Qt.DescendingOrder)
+        self.setEditStrategy(QSqlTableModel.OnManualSubmit)
+        self.recipient = ""
+
+        self.select()
+        logging.debug("Table was loaded successfully.")
+
+    def setRecipient(self, recipient):
+        if recipient == self.recipient:
+            pass
+
+        self.recipient = recipient
+
+        filter_str = (f"(recipient = '{self.recipient}' AND author = 'Me') OR "
+                      f"(recipient = 'Me' AND author='{self.recipient}')")
+        self.setFilter(filter_str)
+        self.select()
+
+    def data(self, index, role):
+        if role < Qt.UserRole:
+            return QSqlTableModel.data(self, index, role)
+
+        sql_record = QSqlRecord()
+        sql_record = self.record(index.row())
+
+        return sql_record.value(role - Qt.UserRole)
+
+    def roleNames(self):
+        """Converts dict to hash because that's the result expected
+        by QSqlTableModel"""
+        names = {}
+        author = "author".encode()
+        recipient = "recipient".encode()
+        timestamp = "timestamp".encode()
+        message = "message".encode()
+
+        names[hash(Qt.UserRole)] = author
+        names[hash(Qt.UserRole + 1)] = recipient
+        names[hash(Qt.UserRole + 2)] = timestamp
+        names[hash(Qt.UserRole + 3)] = message
+
+        return names
+
+    # This is a workaround because PySide doesn't provide Q_INVOKABLE
+    # So we declare this as a Slot to be able to call it  from QML
+    @Slot(str, str, str)
+    def send_message(self, recipient, message, author):
+        timestamp = datetime.datetime.now()
+
+        new_record = self.record()
+        new_record.setValue("author", author)
+        new_record.setValue("recipient", recipient)
+        new_record.setValue("timestamp", str(timestamp))
+        new_record.setValue("message", message)
+
+        logging.debug(f'Message: "{message}" \n Received by: "{recipient}"')
+
+        if not self.insertRecord(self.rowCount(), new_record):
+            logging.error("Failed to send message: {self.lastError().text()}")
+            return
+
+        self.submitAll()
+        self.select()