QPushButton导出到QML

时间:2019-06-03 10:55:41

标签: qt qml

我目前正在使用Qt 5.7,并且已经将QPushButton子类化,其基本思想是在Qt Style sheets上使用QML side。这是头文件:

#ifndef LTPUSHBUTTON_H
#define LTPUSHBUTTON_H

#include <QWidget>
#include <QPushButton>
#include <QString>

/**
 * @class Modified push button class
 */
class LtPushButton : public QPushButton
{
    Q_OBJECT

public:
    /**
     * @brief Constructor
     * @param parent
     */
    LtPushButton(const QString& ltText=QString(),
                 QWidget* const parent=Q_NULLPTR);

    /**
     * @brief Method for settings CSS style from QML side
     * @param ltCSSStyle
     */
    Q_INVOKABLE void ltSetCSSStyle(const QString& ltCSSStyle);
};

#endif // LTPUSHBUTTON_H

及其实现:

#include "ltpushbutton.h"

LtPushButton::LtPushButton(const QString &ltText,
                           QWidget* const parent)
    : QPushButton(parent)
{
    this->setText(ltText);
}   // constructor


void LtPushButton::ltSetCSSStyle(const QString& ltCSSStyle)
{
    this->setStyleSheet(ltCSSStyle);
}   // ltSetCSSStyle

LtPushButton类型已在main.cpp中注册:

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>

#include "ltpushbutton.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    qmlRegisterType<LtPushButton>("com.testapp.gui",
                                  1,
                                  0,
                                  "LtPushButton");

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);

    engine.load(url);

    return app.exec();
}

,当我尝试在main.qml中设置窗口的样式表时:

import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.3

import com.testapp.gui 1.0

Window
{
    width: 640
    height: 480

    visible: true

    title: qsTr("Hello World")

    color: "red"

    GridLayout
    {
        anchors.fill: parent

        rows: 2
        columns: 2

        LtPushButton
        {
            id: ltUpperLeftButton

            Layout.fillWidth: true
            Layout.fillHeight: true
            Layout.alignment: Qt.AlignHCenter|Qt.AlignVCenter

            text: qsTr("One");
        }   // LtPushButton

        Component.onCompleted:
        {
            ltUpperLeftButton.ltSetCSSStyle("border-top-left-radius: 20px;
                                             border-top-right-radius: 20px;
                                             border-bottom-left-radius: 20px;
                                             border-bottom-right-radius: 20px;
                                             background-color: #0047bd;
                                             border: 2px solid #0047bd;
                                             color: #ffffff;
                                             outline: none;");
        }   // Component.onCompleted
    }   // GridLayout
}   // Window

该应用程序崩溃。基本上,我正在尝试使用任意数量的径向角实现QML Button,例如,右下角是径向角,其他角是垂直的:

ButtonConfirm

或左下角呈放射状转角,其他角垂直:

ButtonCancel

上角相同。

1 个答案:

答案 0 :(得分:0)

您不能像这样在QML中嵌入Qt小部件。 QML使用场景图(可以将QGraphicsProxyWidget与使用QGraphicsView的Qt Quick 1一起使用。

现在您必须使用QQuickPaintedItem

但是,通过使用Shape,在QML中直接制作带有径向角的按钮非常容易。

一个简单的例子:

Button {
        id: button
        background: Shape {
            ShapePath {
                id: shape
                property int angleRadius: 12
                strokeWidth: 4
                fillColor: "red"
                startX: 0; startY: 0
                PathLine { x: button.width; y: 0 }
                PathLine { x: button.width; y: button.height - shape.angleRadius }
                PathArc {
                        x: button.width - shape.angleRadius; y: button.height
                        radiusX: shape.angleRadius
                        radiusY: shape.angleRadius
                    }
                PathLine { x: 0; y: button.height }
                PathLine { x: 0; y: 0 }
            }
        }
        text: "Confirm"
    }

如果您不想使用Shape,则可以使用基本的Rectangle(无边框):其中一个带有圆角,另外两个带有圆角。

例如:

Button {
    id: button2
    background: Rectangle {
        id: bg
        radius: 8
        color: "green"
        Rectangle {
            width: bg.width
            height: bg.radius
            x: 0
            y: 0
            color: bg.color
        }
        Rectangle {
            width: bg.radius
            height: bg.height
            x: 0
            y: 0
            color: bg.color
        }
    }
    text: "Confirm"
}

如果您真的想使用C ++类,请使用QQuickPaintedItem

class Button : public QQuickPaintedItem
{
    Q_OBJECT
    Q_PROPERTY(QColor color READ color WRITE setColor)
    Q_PROPERTY(QString text READ text WRITE setText)
public:
    Button(QQuickItem* parent=nullptr): QQuickPaintedItem(parent) {
        setAcceptedMouseButtons(Qt::LeftButton);
    }

    virtual void paint(QPainter* painter) override
    {
        QPainterPath path;
        path.setFillRule(Qt::WindingFill);
        path.addRoundRect(contentsBoundingRect(), 90, 90);
        path.addRect(0, 0, width(), height() / 2);
        path.addRect(0, 0, width() / 2, height());
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(color());
        painter->drawPath(path);
        painter->restore();
    }

    QColor color() const { return bgColor; }
    QString text() const { return contentText; }
public slots:
    void setColor(QColor const& color) { bgColor = color; }
    void setText(QString const& text) { contentText = text; }

signals:
    void clicked();
private:
    QColor bgColor;
    QString contentText;

    QElapsedTimer pressedTimer;

    virtual void mousePressEvent(QMouseEvent* event) override
    {
        if (event->button() != Qt::MouseButton::LeftButton)
        {
            pressedTimer.invalidate();
            return;
        }
        pressedTimer.restart();
    }

    virtual void mouseReleaseEvent(QMouseEvent* /*event*/) override
    {
        if (pressedTimer.elapsed() < 200)
            clicked();
        pressedTimer.invalidate();
    }
};


// In main.cpp
qmlRegisterType<Button>("my.app", 1, 0, "MyButton");

// main.qml
MyButton {
    text: "Cancel"
    color: "blue"
    width: 60
    height: 30
    onClicked: console.log("Clicked")
}