zoukankan      html  css  js  c++  java
  • QT

    1.

      CONFIG += qt 的作用

      qtbase 编译

      单元测试:参考

      完整的测试代码:

    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    * Author: Alex
    * mail: abnk@qq.com
    * File Type: unix Name: test.cpp
    * Created Time: 2021-07-23 10:15 33
    *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    #include <QtTest/QtTest>
    
    // 参考: https://blog.51cto.com/u_9291927/2114179
    // qmake -project "QT+=testlib
    // qmake && make && ./qt_test
    
    class TestQString: public QObject
    {
        Q_OBJECT
    private slots:
        void toUpper();
        void toUpper_data();
    };
    
    void TestQString::toUpper()
    {
        // 原来没有测试数据的时候需要将测试数据一个一个的写到代码里面。
        // QString str = "Hello";
        // QVERIFY(str.toUpper() == "HELLO");
        // QCOMPARE(str.toUpper(), QString("HELLO"));
    
        QFETCH(QString, lowerString);
        QFETCH(QString, upperResult);
    
        // 添加的数据只需要被调用一次就被批量测试完了
        QCOMPARE(lowerString.toUpper(), upperResult);
    }
    
    // 为测试函数提供数据的函数必须与该测试函数同名,并加上_data后缀
    void TestQString::toUpper_data()
    {
        QTest::addColumn<QString>("lowerString");
        QTest::addColumn<QString>("upperResult");
    
        QTest::newRow("all lower") << "hello" << "HELLO";
        QTest::newRow("mixed")     << "Hello" << "HELLO";
        QTest::newRow("all upper") << "HELLO" << "HELLO";
    }
    
    QTEST_APPLESS_MAIN(TestQString);    // 同类名
    #include "test.moc"                 // 文件名+.moc
    test.cpp

      Qt官方 autotest   参考

    2. QScopeGuard

      析构的时候会做一些事情。

    template <typename F>
    class [[nodiscard]] QScopeGuard
    {
    public:
        explicit QScopeGuard(F &&f) noexcept
            : m_func(std::move(f))
        {
        }
    
        explicit QScopeGuard(const F &f) noexcept
            : m_func(f)
        {
        }
    
        QScopeGuard(QScopeGuard &&other) noexcept
            : m_func(std::move(other.m_func))
            , m_invoke(qExchange(other.m_invoke, false))
        {
        }
    
        ~QScopeGuard() noexcept
        {
            if (m_invoke)
                m_func();
        }
    
        void dismiss() noexcept
        {
            m_invoke = false;
        }
    
    private:
        Q_DISABLE_COPY(QScopeGuard)
    
        F m_func;
        bool m_invoke = true;
    };
    
    #ifdef __cpp_deduction_guides
    template <typename F> QScopeGuard(F(&)()) -> QScopeGuard<F(*)()>;
    #endif
    
    //! [qScopeGuard]
    template <typename F>
    [[nodiscard]] QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
    {
        return QScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
    }
    View Code

    3. run in main thread (use lambda)

    /*!
      rewrite from:  https://zhuanlan.zhihu.com/p/364710810
    */
    #include <QtCore/QCoreApplication>
    #include <QtCore/QObject>
    #include <QtCore/QThread>
    #include <QtCore/QDebug>
    #include <QtCore/QQueue>
    #include <functional>
    #include <unistd.h>  // sleep
    
    using Callback = std::function <void(QQueue <void *>)>;
    
    class Worker : public QObject
    {
        Q_OBJECT
    public:
        Worker() {
            moveToThread(&m_thread);
            m_thread.start();
        }
    public slots:
        void slotRunInSub() {                   // add callback
            // qDebug() << "run in sub thread slot:" << QThread::currentThreadId();
            if (m_workerCallback) {
                m_workerCallback(m_queue);
            }
            emit mSig();
        }
    signals:
         void mSig();
    private:
         QThread m_thread;
         QQueue <void *> m_queue;
         Callback m_workerCallback;
    public:
        void setCallback(Callback &&func, void *arg) {
            m_queue.enqueue(arg);
            m_workerCallback = std::forward<Callback>(func);
        }
    };
    
    class Dummy : public QObject
    {
        Q_OBJECT
    
    public:
        Dummy(QObject* parent=0) : QObject(parent) {
            QObject::connect(this, SIGNAL(sig()), &worker, SLOT(slotRunInSub()));        // update
            QObject::connect(&worker, SIGNAL(mSig()), this, SLOT(slotRunInMain()));  // process
        }
        // template <>
        void PostToChild(Callback &&func, void *arg) {
            // m_queue.enqueue(arg);
            worker.setCallback(std::forward<Callback>(func), arg);
        }
        void PostToMain(Callback &&func, void *arg) {
            m_queue.enqueue(arg);
            m_callback = std::forward<Callback>(func);
            sigToSubThd();   // call slot, note sub thread process data
        }
    
    public slots:
        void sigToSubThd() {
            emit sig();
        }
    signals:
        void sig();
    
    public slots:
        void slotRunInMain() {      // update
            qDebug() << "run in main: " << QThread::currentThreadId();
            if (m_callback) {
                m_callback(m_queue);
            }
        }
    
    private:
        Worker worker;
        QQueue <void *> m_queue;
        Callback m_callback;
    };
    
    #include "main.moc"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        qDebug() << "main thread: " << QThread::currentThreadId();
    
        // QCoreApplication::instance()->thread();
    
        Dummy dummy;
        int data = 1111;
    
        dummy.PostToChild([](QQueue <void *> queue){            // in sub thread
            //        1. memcpy  data;
            //        2. process data;
            //        3. enqueue data;
            qDebug() << "run in sub thread slot:" << QThread::currentThreadId();
            sleep(5);
        }, (void *)&data);                               // set cb, copy data and enqueue.
    
        int enqueueData = 2222;
        dummy.PostToMain([](QQueue <void *> queue){         // in sub thread
            void *deData = queue.dequeue();
             qDebug() << "dequeue: " << *(int *)deData;     // dequeue data, and update???
             qDebug() << "run in main thread: " << QThread::currentThreadId();
        }, (void *)&enqueueData);
    
        qDebug() << "async exec";
    
        return a.exec();
    }
    View Code

      and then, add concurent,

      add ensure connect sub to main.

      add move to main thread

      add variable args function and declytype

      moveToThread has memory hosting relationship 

    /*!
      rewrite from:  https://zhuanlan.zhihu.com/p/364710810
    */
    #include <QtCore/QCoreApplication>
    #include <QtWidgets/QApplication>
    #include <QtCore/QObject>
    #include <QtCore/QThread>
    #include <QtCore/QDebug>
    #include <QtCore/QQueue>
    #include <functional>
    #include <unistd.h>  // sleep
    #include <thread>
    
    #include <QStyle>
    #include <QTimer>
    #include <QPushButton>
    #include <QMainWindow>
    
    using Callback = std::function <void(QQueue <void *>)>;
    
    class Worker : public QObject
    {
        Q_OBJECT
    public:
        Worker() {
            moveToThread(&m_thread);
            m_thread.start();
        }
        ~Worker() {
            if (m_thread.isRunning()) {
                // m_thread.deleteLater();
                // m_thread.exit(0);
                m_thread.quit();
                m_thread.wait();
            }
        }
    public slots:
        void slotRunInSub() {                   // add callback
            // qDebug() << "run in sub thread slot:" << QThread::currentThreadId();
            if (m_workerCallback) {
                m_workerCallback(m_queue);
            }
            emit mSig();
        }
    signals:
         void mSig();
    private:
         QThread m_thread;
         QQueue <void *> m_queue;
         Callback m_workerCallback;
    public:
        void setCallback(Callback &&func, void *arg) {
            m_queue.enqueue(arg);
            m_workerCallback = std::forward<Callback>(func);
        }
    };
    
    class Dummy : public QObject
    {
        Q_OBJECT
    public:
        Dummy(QObject* parent=0) : QObject(parent) {
            // Guranentee connect main thread to child
            if (QCoreApplication::instance() && QCoreApplication::instance()->thread()) {
                moveToThread(QCoreApplication::instance()->thread());
                QObject::connect(this, SIGNAL(signalConnectInMainToChild()), this, SLOT(slotConnectInMainToChild()));
                // qDebug() << "Dummy is constructor in main: " << QThread::currentThreadId();
            }
            emit signalConnectInMainToChild();
        }
        ~Dummy() {
    //        if (worker) {
    //            worker->deleteLater();
    //            worker = nullptr;
    //        }
        }
        // template <>
        void PostToChild(Callback &&func, void *arg) {
            // m_queue.enqueue(arg);
            worker->setCallback(std::forward<Callback>(func), arg);
        }
        void PostToMain(Callback &&func, void *arg) {
            m_queue.enqueue(arg);
            m_callback = std::forward<Callback>(func);
            sigToSubThd();   // call slot, note sub thread process data
        }
    
    public slots:
        void sigToSubThd() {
            emit sig();
        }
    
        void slotConnectInMainToChild() {
            worker = new Worker;
            qDebug() << "Dummy is connect in main: " << QThread::currentThreadId();
            QObject::connect(this, SIGNAL(sig()), worker, SLOT(slotRunInSub()));        // update
            QObject::connect(worker, SIGNAL(mSig()), this, SLOT(slotRunInMain()));  // process
        }
    
    signals:
        void sig();
        void signalConnectInMainToChild();
    
    public slots:
        void slotRunInMain() {      // update
            qDebug() << "run in main: " << QThread::currentThreadId();
            if (m_callback) {
                m_callback(m_queue);
            }
        }
    
    private:
        Worker *worker;
        QQueue <void *> m_queue;
        Callback m_callback;
    };
    
    #include "main.moc"
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        qDebug() << "main thread: " << QThread::currentThreadId();
    
        // QCoreApplication::instance()->thread();
    
        std::thread thd([]{
            Dummy dummy;
            // dummy.signalConnectInMainToChild();
            sleep(1);
            int data = 1111;
    
            dummy.PostToChild([](QQueue <void *> queue){            // in sub thread
                //        1. memcpy  data;
                //        2. process data;
                //        3. enqueue data;
                qDebug() << "run in sub thread slot:" << QThread::currentThreadId();
                // sleep(5);
            }, (void *)&data);                               // set cb, copy data and enqueue.
    
            int enqueueData = 2222;
            dummy.PostToMain([](QQueue <void *> queue){         // in sub thread
                void *deData = queue.dequeue();
                qDebug() << "dequeue: " << *(int *)deData;     // dequeue data, and update???
                qDebug() << "run in main thread: " << QThread::currentThreadId();
            }, (void *)&enqueueData);
    
            qDebug() << "async exec";
    
            sleep(6);
            // qApp->quit();
        });
    
        thd.detach();
    
    
    
        QMainWindow w;
        QWidget central;
        QPushButton button(&central);
        w.setCentralWidget(&central);
    
    #if 1
        // analogue render event
        QTimer timer;
        QObject::connect(&timer, &QTimer::timeout, [&button]{
            static bool flag = false;
            QStyle *style = QApplication::style();
            QIcon openPicture = style->standardIcon(QStyle::SP_TitleBarMenuButton);
            QIcon inforIron = style->standardIcon(QStyle::SP_DialogYesButton);
            button.setIcon(flag ? openPicture : inforIron);
            flag = !flag;
        });
        timer.setInterval(200);
        timer.start();
    #endif
    
    #if 0
        // single event ocupaid block
        QObject o;
        QTimer::singleShot(100, &o, [&button]{
            // while(1)
            {
                sleep(1);
                qDebug() << QThread::currentThreadId();
    
                static bool flag = false;
                QStyle* style = QApplication::style();
                QIcon openPicture = style->standardIcon(QStyle::SP_TitleBarMenuButton);
                QIcon inforIron = style->standardIcon(QStyle::SP_MediaSkipBackward);
                button.setIcon(flag ? openPicture : inforIron);
                flag = !flag;
            }
        });
    #endif
    
    
        w.show();
    
        qDebug() << "enter exec";
        return a.exec();
    }
    View Code

    4. QRunnable

      参考

    4. 国际化

      参考

     

     

  • 相关阅读:
    framework 3 ,4
    C# 线程
    ReportingService错误:配置参数 SharePointIntegrated 被设置为 True,但无法加载 Share Point 对象模型
    C# 打印 word pdf PrintOut方法
    C# 多线程控制控件实例(例程简单,注释详细)
    Windchill MethodServer启动后自动关闭
    Press C#使用指定打印机打印Word,Excel等Office文件和打印PDF文件的代码 (转)
    ExtJs入门
    The transaction log for database 'wcadmin' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.datab
    JS+调用word打印功能实现在Webfrom客户端
  • 原文地址:https://www.cnblogs.com/abnk/p/15047607.html
Copyright © 2011-2022 走看看