QtQuick/Qml自定义控件(1)-ToolTip

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QtQuick/Qml自定义控件(1)-ToolTip相关的知识,希望对你有一定的参考价值。

参考技术A 首先我们看看官方提供的QtQuick.Controls 2.x Tooltip Tooltip
效果是怎么样的

看起来还是挺好用的 也很方便 然后我们再看来看看特殊的情况
我们将窗体大小缩小后

很明显 Tooltip的文字描述长度超过窗体右边边界时 无法正常显示了.
我们在看看边界的情况
正常关闭按钮的Tooltip:

上面两个问题的原因很简单, Tooltip继承于Popup, 不属于独立窗体.
为此我决定自定义开发一个QtQuick方式的Tooltip

首先Tooltip应该是基于独立窗体的, 并且因为要考虑资源占用问题, 所以最好是单例模式, 就是说始终只存在一个ToolTip的实例.
ToolTip有两大重要属性, 一是延时启动, 二是延时消失, 这两个当然是需要可设置的

同样, SilkQmlToolTip也需要有同样的功能

结果是预期的: 1秒显示 5秒隐藏 当然鼠标移开也是立即隐藏的
我们又在三峰驼演示程序里看看效果

关闭按钮的ToolTip可以在窗体外正常显示

三峰驼演示程序里的效果也是正常.

访问三峰驼Qml控件大全

<img src="https://github.com/zhengtianzuo/zhengtianzuo.github.io/blob/master/weixin.jpg?raw=true" width="30%" height="30%" /> <img src="https://github.com/zhengtianzuo/zhengtianzuo.github.io/blob/master/zhifubao.jpg?raw=true" width="30%" height="30%" />

如何从 PySide 访问 QML\QtQuick 控件?

【中文标题】如何从 PySide 访问 QML\\QtQuick 控件?【英文标题】:How to access QML\QtQuick controls from PySide?如何从 PySide 访问 QML\QtQuick 控件? 【发布时间】:2019-03-05 22:03:20 【问题描述】:

我正在尝试从启动 QQmlApplication 引擎的 python 文件中访问 FileDialog 控件,以检索文件路径属性。我已经在 .qml 文件中设置了一个信号,但是我无法通过 python 文件中的 id 访问文件对话框来设置插槽。 application.py 中的 findChild 方法返回 None。代码如下:

应用程序.py

import sys
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine, QQmlFileSelector

sys_argv = sys.argv
sys_argv += ['--style', 'material']
app = QGuiApplication(sys_argv)

window = QQmlApplicationEngine()
window.load("QML/main.qml")

fileDialog = window.findChild(QQmlFileSelector, "fileDialog")
print(fileDialog)

app.exec_()

Page1.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2

Page 
    width: 600
    height: 400

    header: Label 
        text: qsTr("Prepare Data")
        horizontalAlignment: Text.AlignHCenter
        font.pixelSize: Qt.application.font.pixelSize * 2
        padding: 10
    

    Button 
        text: qsTr("Load data")
        anchors.centerIn: parent
        onClicked: fileDialog.visible = true
        padding: 10
    

    signal folderSelected()

    FileDialog 
        id: fileDialog
        selectFolder: true
        title: qsTr("Select the data directory")
        folder: shortcuts.home
        onAccepted: 
            parent.folderSelected()
        
    

main.qml

import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12

ApplicationWindow
    visible: true
    title: qsTr("Main window")
    width: 1000
    height: 800

    Material.theme: Material.Light
    Material.accent: Material.Orange

    SwipeView 
        id: swipeView
        anchors.fill: parent

        Page1 
        

        Page2 
        

        Page3 
        

    

【问题讨论】:

【参考方案1】:

在old answer 部分中解释 Pushing References to QML 如何从 QML 更新一些 python 对象,该方法是 Qt 推荐的方法,也是现在应该使用的方法.使用您当前的方法,您需要建立一个在许多情况下可能会出现问题的对象名称。

所以解决方案是创建一个我们导出到 QML 并更新 qproperty 的 QObject,这将发出一个信号,我们连接到一个插槽,我们可以在其中执行我们想要的逻辑。另一方面 FileDialog 返回一个 url,所以属性必须是 QUrl:

ma​​in.qml

import os
import sys
from PySide2 import QtCore, QtGui, QtQml

class FileManager(QtCore.QObject):
    file_url_Changed = QtCore.Signal(QtCore.QUrl)

    def __init__(self, parent=None):
        super(FileManager, self).__init__(parent)
        self._file_url = QtCore.QUrl()

    def get_file_url(self):
        return self._file_url

    def set_file_url(self, file_url):
        if self._file_url != file_url:
            self._file_url = file_url
            self.file_url_Changed.emit(self._file_url)

    file_url = QtCore.Property(QtCore.QUrl, fget=get_file_url, fset=set_file_url, notify=file_url_Changed)

@QtCore.Slot(QtCore.QUrl)
def on_file_url_changed(file_url):
    print(file_url.toLocalFile())

if __name__ == '__main__':
    sys.argv += ['--style', 'material']
    app = QtGui.QGuiApplication(sys.argv)

    file_manager = FileManager()
    file_manager.file_url_Changed.connect(on_file_url_changed)

    engine = QtQml.QQmlApplicationEngine()
    engine.rootContext().setContextProperty("file_manager", file_manager)
    file = os.path.join(os.path.dirname(os.path.realpath(__file__)), "QML", "main.qml")
    engine.load(QtCore.QUrl.fromLocalFile(file))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

Page1.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Dialogs 1.2

Page 
    width: 600
    height: 400

    header: Label 
        text: qsTr("Prepare Data")
        horizontalAlignment: Text.AlignHCenter
        font.pixelSize: Qt.application.font.pixelSize * 2
        padding: 10
    

    Button 
        text: qsTr("Load data")
        anchors.centerIn: parent
        onClicked: fileDialog.visible = true
        padding: 10
    

    FileDialog 
        id: fileDialog
        selectFolder: true
        title: qsTr("Select the data directory")
        folder: shortcuts.home
        onAccepted: 
            file_manager.file_url = fileDialog.fileUrl // <---
        
    

【讨论】:

谢谢,效果很好!但是,例如,这如何转化为整个形式?我是否必须创建一个新的 QObject,然后将其设置为表单中每个组件的上下文属性? @dkalev 不,FileManager 可以有其他 qproperties,因此您只能使用单个对象

以上是关于QtQuick/Qml自定义控件(1)-ToolTip的主要内容,如果未能解决你的问题,请参考以下文章

组织孩子的 Qt Quick2 自定义控件

如何从 PySide 访问 QML\QtQuick 控件?

QtQuick 2 - 自定义元素,如何调整根对象的大小?

QML用户界面基础(一)

QML::常用基础控件属性1

QtQuick:未安装模块