Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Custom widget plugin doubled in designer



  • Description

    After completing a custom widget, I dragged it from designer into a QWidget, then closed the ui file and reopened it, repeated this action several times, then this custom widget was doubled by desinger, and if I repeat this reopen action again, the number of this custom widget will be doubled to 4, 8...

    This problem appears randomly, and can only restore by deleting this custom widget and adding it again. However, this problem will still appear with a high probability if I repeat the action.

    Does anyone got the same problems? Any solutions?

    Environment

    • Qt Version: 5.10.1
    • Platform: Mac OS and Windows 10 (MSVC2015)

    Download project


    BTW, I have wrote a macro to generate Q_PROPERTY for my each custom widget, here is the code:

    // **********************************************
    // Gnerate common Q_PROPERTY
    // Support: anchor layout, must be QWidget
    // Support: free control from parent if it is QLayout or has set QLayout
    // Must declare after Q_PROPERTY
    // **********************************************
    #define Q_EX_SUPPORT_ANCHOR \
    Q_PROPERTY(bool anchorLeft READ anchorLeft WRITE setAnchorLeft) \
    Q_PROPERTY(bool anchorTop READ anchorTop WRITE setAnchorTop) \
    Q_PROPERTY(bool anchorRight READ anchorRight WRITE setAnchorRight) \
    Q_PROPERTY(bool anchorBottom READ anchorBottom WRITE setAnchorBottom) \
    Q_PROPERTY(int leftAnchorMargin READ leftAnchorMargin WRITE setLeftAnchorMargin) \
    Q_PROPERTY(int topAnchorMargin READ topAnchorMargin WRITE setTopAnchorMargin) \
    Q_PROPERTY(int rightAnchorMargin READ rightAnchorMargin WRITE setRightAnchorMargin) \
    Q_PROPERTY(int bottomAnchorMargin READ bottomAnchorMargin WRITE setBottomAnchorMargin) \
    Q_PROPERTY(bool freeFromLayout READ freeFromLayout WRITE setFreeFromLayout) \
    \
        typedef struct stAnchors { \
            int left = 0; \
            int top = 0; \
            int right = 0; \
            int bottom = 0; \
            bool anchorLeft = false; \
            bool anchorTop = false; \
            bool anchorRight = false; \
            bool anchorBottom = false; \
        } Anchors; \
    \
    public: \
        bool anchorLeft() const {return m_anchors.anchorLeft;} \
        bool anchorTop() const {return m_anchors.anchorTop;} \
        bool anchorRight() const {return m_anchors.anchorRight;} \
        bool anchorBottom() const {return m_anchors.anchorBottom;} \
        int leftAnchorMargin() const {return m_anchors.left;} \
        int topAnchorMargin() const {return m_anchors.top;} \
        int rightAnchorMargin() const {return m_anchors.right;} \
        int bottomAnchorMargin() const {return m_anchors.bottom;} \
        bool freeFromLayout() const {return m_bFreeFromLayout;}\
    \
        void setAnchorLeft(const bool &anchorLeft) {\
            m_anchors.anchorLeft = anchorLeft;\
            updateSelfGeometry(); \
        } \
        \
        void setAnchorTop(const bool &anchorTop) {\
            m_anchors.anchorTop = anchorTop;\
            updateSelfGeometry(); \
        } \
        \
        void setAnchorRight(const bool &anchorRight) {\
            m_anchors.anchorRight = anchorRight;\
            updateSelfGeometry(); \
        } \
        \
        void setAnchorBottom(const bool &anchorBottom) {\
            m_anchors.anchorBottom = anchorBottom;\
            updateSelfGeometry(); \
        } \
        \
        void setLeftAnchorMargin(const int &left) {\
            if (!m_anchors.anchorLeft) {\
                return;\
            }\
            QSize parentSize = ((QWidget*)this->parent())->size();\
            m_anchors.right = parentSize.width() - left - this->size().width();\
            m_anchors.left = left; \
            updateSelfGeometry(); \
        } \
        \
        void setTopAnchorMargin(const int &top) {\
            if (!m_anchors.anchorTop) {\
                return;\
            }\
            QSize parentSize = ((QWidget*)this->parent())->size();\
            m_anchors.bottom = parentSize.height() - top - this->size().height();\
            m_anchors.top = top; \
            updateSelfGeometry(); \
        } \
        \
        void setRightAnchorMargin(const int &right) {\
            if (!m_anchors.anchorRight) {\
                return;\
            }\
            QSize parentSize = ((QWidget*)this->parent())->size();\
            m_anchors.left = parentSize.width() - right - this->size().width();\
            m_anchors.right = right; \
            updateSelfGeometry(); \
        } \
        \
        void setBottomAnchorMargin(const int &bottom) {\
            if (!m_anchors.anchorBottom) {\
                return;\
            }\
            QSize parentSize = ((QWidget*)this->parent())->size();\
            m_anchors.top = parentSize.height() - bottom - this->size().height();\
            m_anchors.bottom = bottom; \
            updateSelfGeometry(); \
        } \
        \
        void setFreeFromLayout(const bool &free) {\
            m_bFreeFromLayout = free;\
            updateSelfGeometry(); \
        } \
    \
    private: \
        bool isFreeFromParentLayout() {\
            if (!parent()) {\
                return false;\
            }\
            QLayout *layout = Q_NULLPTR;\
            if (isParentLayout()) {\
                layout = (QLayout*)parent();\
            }\
            else if (isParentHasLayout()) {\
                layout = ((QWidget*)parent())->layout();\
            }\
            if (Q_NULLPTR != layout) {\
                int index = layout->indexOf(this);\
                if (-1 == index) {\
                    return true;\
                }\
            }\
            return false;\
        }\
        \
        bool isParentLayout() {\
            if (parent() &&parent()->inherits("QLayout")) {\
                return true;\
            }\
            return false;\
        }\
        \
        bool isParentHasLayout() {\
            if (parent() && parent()->inherits("QWidget") && Q_NULLPTR != ((QWidget*)parent())->layout()) {\
                return true;\
            }\
            return false;\
        }\
        \
        void updateSelfGeometry() {\
            if (parent()) {\
                QLayout *layout = Q_NULLPTR;\
                bool bParentIsOrHasLayout = (isParentLayout() || isParentHasLayout());\
                if (isParentLayout()) {\
                    layout = (QLayout*)parent();\
                }\
                else if (isParentHasLayout()) {\
                    layout = ((QWidget*)parent())->layout();\
                }\
                if (m_bFreeFromLayout && bParentIsOrHasLayout && !isFreeFromParentLayout()) {\
                    layout->removeWidget((QWidget*)this);\
                }\
                else if (!m_bFreeFromLayout && bParentIsOrHasLayout && isFreeFromParentLayout()) {\
                    layout->addWidget((QWidget*)this);\
                    layout->update();\
                    return;\
                }\
                else if (!m_bFreeFromLayout && bParentIsOrHasLayout && !isFreeFromParentLayout()) {\
                    return;\
                }\
            }\
            \
            QSize parentSize = ((QWidget*)this->parent())->size();\
            QRect selfRect = this->geometry();\
            QSize selfSize = this->size();\
            if (m_anchors.anchorLeft) {\
                selfRect.setX(m_anchors.left);\
                selfRect.setSize(selfSize);\
            }\
            \
            if (m_anchors.anchorRight) {\
                selfRect.setX(parentSize.width() - selfSize.width() - m_anchors.right);\
                selfRect.setSize(selfSize);\
            }\
            \
            if (m_anchors.anchorTop) {\
                selfRect.setY(m_anchors.top);\
                selfRect.setSize(selfSize);\
            }\
            \
            if (m_anchors.anchorBottom) {\
                selfRect.setY(parentSize.height() - selfSize.height() - m_anchors.bottom);\
                selfRect.setSize(selfSize);\
            }\
            \
            this->setGeometry(selfRect);\
        }\
    \
    private: \
        Anchors m_anchors; \
        bool m_bFreeFromLayout = false;\
    \
    

    To use this macro in a custom widget:

    class QDESIGNER_WIDGET_EXPORT CCLabel : public QLabel
    {
        Q_OBJECT
        Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
        Q_PROPERTY(bool elidedText READ isElidedText WRITE setElidedText NOTIFY elidedTextSettingChanged)
        Q_PROPERTY(int fontSizeIncrement READ fontSizeIncrement WRITE setFontSizeIncrement NOTIFY fontSizeIncrementChanged)
    
        // Must declare after Q_PROPERTY
        Q_EX_SUPPORT_ANCHOR
    public:
        explicit CCLabel(QWidget *parent = 0);
        ~CCLabel();
    
        // getter
        bool isElidedText() {return m_bElidedText;}
        QString text() {return m_strText;}
        int fontSizeIncrement() {return m_fontSizeIncrement;}
    
        // setter
        void setElidedText(const bool &bElidedText);
        void setText(const QString &strText);
        void setFontSizeIncrement(const int sizeIncrement);
    
    signals:
        // change events
        void elidedTextSettingChanged(const bool bTextElided);
        void textChanged(const QString &strNewText);
        void fontSizeIncrementChanged(qint32 fontSize);
    
    protected:
        // reimpl
        void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
        bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
        void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
        void moveEvent(QMoveEvent *event) Q_DECL_OVERRIDE;
    
    private:
        // Functions
        bool isTextExceeded(const QString &strText);
        void checkTextElided(const QString &strText);
    
        void updateUI();
        void updateFont();
    
        // Variables
        Ui::CCLabel *ui;
        bool m_bElidedText = true;
        QString m_strText = QString("");
        int m_fontSizeIncrement = 0;
        int m_initFontSize = 0;
    };
    

  • Lifetime Qt Champion

    Hi
    That i have never seen.
    Even when fiddling with Designer plugins during my get to know Qt periode. ( i crashed Creator a few times :)
    I would test with
    http://doc.qt.io/qt-5/qtdesigner-worldtimeclockplugin-example.html
    to see if you can reproduce it with a sample.

    Since reopening UI files seems to double the counter of your widget. As soon as it has the issue, close creator and inspect the UI file to see if there really are stored multiple versions



  • @mrjj

    Hi, thanks for your attention.

    Here is the download link of qtexcontrols project, you can build and deploy it to QtCreator
    https://drive.google.com/open?id=1J_Qjh-SFsxFNF0pnCwgT8Y7O-lGKlRC9


Log in to reply