从QML中的C ++类接收带有参数的信号

时间:2018-08-03 14:17:34

标签: c++ qt qml signals-slots

我想从QML中的C ++ QObject类接收信号,我已经阅读了以下指南:

https://doc.qt.io/archives/qt-4.8/qtbinding.html#receiving-signals

但是我在获取结果时遇到了麻烦,这是我的示例代码:

myclass.h

public class AnimatedLine extends View {
    private final Paint mPaint;
    public Canvas mCanvas;
    AnimationListener animationListener;

    Path path;
    private static long animSpeedInMs = 2000;
    private static final long animMsBetweenStrokes = 100;
    private long animLastUpdate;
    private boolean animRunning = true;
    private int animCurrentCountour;
    private float animCurrentPos;
    private Path animPath;
    private PathMeasure animPathMeasure;

    float pathLength;


    float distance = 0;
    float[] pos;
    float[] tan;
    Matrix matrix;
    Bitmap bm;


    public AnimatedLine(Context context) {
        this(context, null);
        mCanvas = new Canvas();
    }

    public AnimatedLine(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(15);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setColor(context.getResources().getColor(R.color.materialcolorpicker__red));


        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            setLayerType(LAYER_TYPE_SOFTWARE, mPaint);
        }
        bm = BitmapFactory.decodeResource(getResources(), R.drawable.hand1);
        bm = Bitmap.createScaledBitmap(bm, 20,20, false);
        distance = 0;
        pos = new float[2];
        tan = new float[2];

        matrix = new Matrix();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mCanvas = canvas;

        if (path != null) {

            if (animRunning) {
                drawAnimation(mCanvas);
            } else {
                drawStatic(mCanvas);
            }

        }

    }


    /**
     * draw Path With Animation
     *
     * @param time in milliseconds
     */
    public void drawWithAnimation(ArrayList<PointF> points, long time,AnimationListener animationListener) {
        animRunning = true;
        animPathMeasure = null;
        animSpeedInMs = time;
        setPath(points);
        setAnimationListener(animationListener);
        invalidate();
    }

    public void setPath(ArrayList<PointF> points) {
        if (points.size() < 2) {
            throw new IllegalStateException("Pass atleast two points.");
        }
        path = new Path();
        path.moveTo(points.get(0).x, points.get(0).y);
        path.lineTo(points.get(1).x, points.get(1).y);
    }

    private void drawAnimation(Canvas canvas) {
        if (animPathMeasure == null) {
            // Start of animation. Set it up.
            animationListener.onAnimationStarted();
            animPathMeasure = new PathMeasure(path, false);
            animPathMeasure.nextContour();
            animPath = new Path();
            animLastUpdate = System.currentTimeMillis();
            animCurrentCountour = 0;
            animCurrentPos = 0.0f;

            pathLength = animPathMeasure.getLength();


        } else {
            // Get time since last frame
            long now = System.currentTimeMillis();
            long timeSinceLast = now - animLastUpdate;

            if (animCurrentPos == 0.0f) {
                timeSinceLast -= animMsBetweenStrokes;
            }

            if (timeSinceLast > 0) {
                // Get next segment of path
                float newPos = (float) (timeSinceLast) / (animSpeedInMs / pathLength) + animCurrentPos;
                boolean moveTo = (animCurrentPos == 0.0f);
                animPathMeasure.getSegment(animCurrentPos, newPos, animPath, moveTo);
                animCurrentPos = newPos;
                animLastUpdate = now;

                 //start draw bitmap along path
                animPathMeasure.getPosTan(newPos, pos, tan);
                matrix.reset();
                matrix.postTranslate(pos[0], pos[1]);
                canvas.drawBitmap(bm, matrix, null);
                //end drawing bitmap



                //take current position
                animationListener.onAnimationUpdate(pos);

                // If this stroke is done, move on to next
                if (newPos > pathLength) {
                    animCurrentPos = 0.0f;
                    animCurrentCountour++;
                    boolean more = animPathMeasure.nextContour();
                    // Check if finished
                    if (!more) {
                        animationListener.onAnimationEnd();
                        animRunning = false;
                    }
                }
            }

            // Draw path
            canvas.drawPath(animPath, mPaint);

        }

        invalidate();
    }

    private void drawStatic(Canvas canvas) {
        canvas.drawPath(path, mPaint);
        canvas.drawBitmap(bm, matrix, null);
    }


    public void setAnimationListener(AnimationListener animationListener) {
        this.animationListener = animationListener;
    }



    public interface AnimationListener {
        void onAnimationStarted();

        void onAnimationEnd();

        void onAnimationUpdate(float[] pos);
    }
}

main.cpp

class myClass : public QObject
 {
  Q_OBJECT

  public:

   explicit myClass(QObject *parent = nullptr);

   Q_INVOKABLE void incrementNumber(){
       number++;
       qDebug()<<number;
       emit numberChanged(number);
   }

  signals:
     Q_INVOKABLE int numberChanged(int &number);
  public slots:

  private:
     int number = 0;
  };

QML

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

    QGuiApplication app(argc, argv);

    QScopedPointer<myClass> myclass (new myClass);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    engine.rootContext()->setContextProperty("myclass",myclass.data());
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}

我在声明QML时出错

  

错误:无法将[undefined]分配给QString”

所以我猜我在做错误的连接。

1 个答案:

答案 0 :(得分:0)

您遇到以下错误:

  • 根据docs信号:它们永远不能具有返回类型(即使用void)。另一方面,它是Q_INVOKABLE毫无意义,最后您必须传递整数值,而不是引用。

  • 在加载QML之前必须导出QObject。

*。h

signals:
    void numberChanged(int number);

main.cpp

...
QQmlApplicationEngine engine;

engine.rootContext()->setContextProperty("myclass", myclass.data());
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
...