Qt(二)--- 使用Qt完成QQ登录界面的输入文本框的实现

在Qt中,对于QLineEdit而言,是没有menu-indicator的,这个时候要实现像qq登录界面的LineEdit:如下图所示,必须需要customize自己的LineEdit,采取的方法是继承QLineEdit,然后在自己的LineEdit添加自己的属性。

Qt(二)--- 使用Qt完成QQ登录界面的输入文本框的实现_第1张图片

首先建立一个Qt Widget Application的工程文件,然后在工程文件中添加c++类:这里我的类名是LogEdit。

继承自QLineEdit,最后得到了关于LogEdit类的logedit.cpp和logedit.h的文件,接着开始对我们需要的edit的实现。

对于这样一个LineEdit,报刊了的输入行以及右边的一个符号,这里我们用QLabel进行装载实现。

因此头文件的内容是:

#ifndef LOGEDIT_H
#define LOGEDIT_H

#include 
#include
#include
class LogEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit LogEdit(QWidget *parent = 0);
    explicit LogEdit(const QString & contents, QWidget *parent = 0);
    explicit LogEdit(const QString & contents, const QString & pic,QWidget *parent = 0);
    virtual ~LogEdit();

    void setLabelPic(const QString strPic);

signals:

    void imageLabelClicked();

protected:
    void init();
    void changeLabelPosition();
protected:

    virtual void resizeEvent(QResizeEvent *event);
    virtual bool eventFilter(QObject *obj, QEvent *e);

private:
    QString mImagePath;
    QLabel *mImageLabel;
};

#endif // LOGEDIT_H

注意

  • 如果要使用Qt的信号槽机制,对象必须要有Q_OBJECT这样一个机制的声明。然后其包含的头文件是#include>,在Assitant中,原文的表达是:The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
  • 对于继承来自QLineEdit的LogEdit,尽量保持着原函数的构造函数,对于QLineEdit的构造函数包含三个:
QLineEdit(QWidget * parent = 0)
QLineEdit(const QString & contents, QWidget * parent = 0)
~QLineEdit()

  • 添加了QLabel的事件处理,即imageLabelClicked()
  • 在这里,由于LogEdit右边需要一个菜单项,因此需要一个Label标记点击的位置,所以在LogEdit中添加了mImageLabel的成员变量
接着是是对头文件的实现,在logedit.cpp文件中实现:

首先是构造函数和析构函数的实现,

对于继承来自于QLineEdit的属性,通过QLineEdit直接实现即可,重点是对新填进去的mImagePath和mImageLabel的初始化:

	
LogEdit::LogEdit(QWidget *parent):QLineEdit(parent)
{
    mImagePath="";
    mImageLabel=NULL;
    setAttribute(Qt::WA_TranslucentBackground);
}

LogEdit::LogEdit(const QString &contents, QWidget *parent):QLineEdit(contents,parent)
{
    mImagePath="";
    mImageLabel=NULL;
    setAttribute(Qt::WA_TranslucentBackground);

}

 
   
  对于读入的对于QLabel的图片的ICON,需要对QLabel的位置进行一定的限制,即在输入行的右下方。其次是对QLabel大小的限定。实现如下: 
  

首先是大小和位置的确定:

void LogEdit::changeLabelPosition()
{
    if(mImageLabel==NULL)
        return;
    if(mImagePath.isEmpty())
    {
        mImageLabel->hide();
    }
    else
    {
        int nHeight=this->height()-4;
        int nWidth=this->height()-4;
        mImageLabel->setMaximumSize(nWidth,nHeight);
    // mImageLabel->setGeometry(width()+nWidth-2,(height()-nHeight)/2,nWidth,nHeight);
        mImageLabel->setGeometry(178-14-2,(28-nHeight)/2,nWidth,nHeight);
        mImageLabel->setPixmap(QPixmap(mImagePath));
        setTextMargins(0,0,height(),0);
    }
}
注意:

  • 起初是想通过读取在QtDesigner中的设计好的界面的宽度和高度,从而确定出QLabel的位置,正如注释调的语句一样,但是读取到的宽度和实际在Designer的大小不一致,万般无赖下来了一个具体的数值,宽度是178,高度是28.
  • setTextMargins是需要联想BoxModel,即在输入行的右边的Margin不为0,即输入的数据不会占据满所有的输入行空间,右边因为有QLabel存在。
接着是对鼠标按下的slot的实现

void LogEdit::resizeEvent(QResizeEvent *event)
{
    QLineEdit::resizeEvent(event);
    changeLabelPosition();
}

bool LogEdit::eventFilter(QObject *obj, QEvent *event)
{
    if (mImageLabel && obj == mImageLabel ) {
            if (event->type() == QEvent::MouseButtonPress) {
                QMouseEvent *mouseEvent = static_cast(event);
                if (mouseEvent->buttons() & Qt::LeftButton)
                {
                    emit imageLabelClicked();
                    return true;
                }
            }
        }
        return QLineEdit::eventFilter(obj, event);
}

注意:

  • resizeEvent的实现原因是因为:This event handler can be reimplemented in a subclass to receive widget resize events which are passed in the event parameter. When resizeEvent() is called, the widget already has its new geometry.

完整的logedit.cpp的实现是:

#include "logedit.h"
#include
#include
#include
#include
LogEdit::LogEdit(QWidget *parent):QLineEdit(parent)
{
    mImagePath="";
    mImageLabel=NULL;
    setAttribute(Qt::WA_TranslucentBackground);
}

LogEdit::LogEdit(const QString &contents, QWidget *parent):QLineEdit(contents,parent)
{
    mImagePath="";
    mImageLabel=NULL;
    setAttribute(Qt::WA_TranslucentBackground);

}


void LogEdit::changeLabelPosition()
{
    if(mImageLabel==NULL)
        return;
    if(mImagePath.isEmpty())
    {
        mImageLabel->hide();
    }
    else
    {
        int nHeight=this->height()-4;
        int nWidth=this->height()-4;
        mImageLabel->setMaximumSize(nWidth,nHeight);
    // mImageLabel->setGeometry(width()+nWidth-2,(height()-nHeight)/2,nWidth,nHeight);
        mImageLabel->setGeometry(178-14-2,(28-nHeight)/2,nWidth,nHeight);
        mImageLabel->setPixmap(QPixmap(mImagePath));
        setTextMargins(0,0,height(),0);
    }
}

void LogEdit::init()
{
    if(mImageLabel==NULL)
    {
        mImageLabel=new QLabel(this);

        //------//
        mImageLabel->setScaledContents(false);

        //这句实现具体的内容待考察
        mImageLabel->installEventFilter(this);
        //设置箭头下标

    }
    changeLabelPosition();


}

LogEdit::LogEdit(const QString &contents, const QString &pic, QWidget *parent)
    :QLineEdit(contents,parent)
{
   mImagePath=pic;
   mImageLabel=NULL;
   setAttribute(Qt::WA_TranslucentBackground);
   init();
}

LogEdit::~LogEdit()
{
    if (mImageLabel)
            delete mImageLabel;
        mImageLabel = NULL;
}
void LogEdit::setLabelPic(const QString strPic)
{
    mImagePath=strPic;
    init();
}

void LogEdit::resizeEvent(QResizeEvent *event)
{
    QLineEdit::resizeEvent(event);
    changeLabelPosition();
}

bool LogEdit::eventFilter(QObject *obj, QEvent *event)
{
    if (mImageLabel && obj == mImageLabel ) {
            if (event->type() == QEvent::MouseButtonPress) {
                QMouseEvent *mouseEvent = static_cast(event);
                if (mouseEvent->buttons() & Qt::LeftButton)
                {
                    emit imageLabelClicked();
                    return true;
                }
            }
        }
        return QLineEdit::eventFilter(obj, event);
}
具体效果是:
Qt(二)--- 使用Qt完成QQ登录界面的输入文本框的实现_第2张图片

PS:

建立了logedit的类后,上下连个输入框是两个不同的实例化类,因为已经有了imageClicked的信号,

对于该信号的处理可以有不同的方式,例如上面显示的,上一个输入行是箭头由上变成下,下面的是

变成了蓝色的键盘,在实际的qq登录是会弹出相应的菜单,这里只需要对该信号的处理机制进行编写

即可实现


你可能感兴趣的:(Qt,Qt学习与实践)