QT自定义控件——仿手机文件选择对话框

 


前言

因为项目需求为嵌入式触屏操作,qt自带的文件选择框不适用触屏操作,所以参考Android的文件管理界面重新做了一个文件选择框

 

一、准备工作

因为是一个小模块,所以需要进行拆解,大致可以分为标题栏区域,文件显示区域和操作区域。

二、具体实现

1.自定义文件按钮

从上面的图中可以看到每一个文件夹(或者文件)都是一个按钮,风格布局基本统一,所以第一步就是先实现这个小组件。这个小组件又可以拆分为图标、文件名称、创建日期和表示可以进入文件夹的箭头图标。

核心代码如下:

因为是个按钮所以直接继承QPushButton

#include <QPushButton>
#include "../customcontrol_global.h"
class FileButtonPrivate;
class CUSTOMCONTROLSHARED_EXPORT FileButton : public QPushButton
{
    Q_OBJECT
public:
    explicit FileButton(QWidget *parent = Q_NULLPTR);

    void setFilePath(const QString &path);//设置文件路径
    QString filePath() const;

protected:
    void paintEvent(QPaintEvent *);
private:
    QSharedPointer<FileButtonPrivate>d_ptr;
    Q_DECLARE_PRIVATE(FileButton)
    Q_DISABLE_COPY(FileButton)

};

根据拆分的要求在绘制事件中分别绘制出来

void FileButton::paintEvent(QPaintEvent *)
{
    Q_D(FileButton);
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    QStylePainter stylePainter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    //绘制背景和外框
    d->drawBg(&stylePainter);
    //绘制图标
    d->drawIcon(&painter);
    //文本
    d->drawText(&stylePainter);
    //箭头
    if(d->m_type == FileButtonPrivate::TYPE_Directory)
        d->drawArrow(&painter);
}

 绘制背景,背景直接保留按钮原本的背景绘制,这样做的目的是保留背景可以通过样式表配置

void FileButtonPrivate::drawBg(QStylePainter *painter)
{
    Q_Q(FileButton);
    QStyleOptionButton option;
    q->initStyleOption(&option);
    painter->drawControl(QStyle::CE_PushButtonBevel, option);
}

绘制文件图标

void FileButtonPrivate::drawIcon(QPainter *painter)
{
    Q_Q(FileButton);
    QChar fontChar;
    QColor color;
    QFont font = IconHelper::Instance()->getIconFont();
    if(m_type == TYPE_Directory)//文件夹图标
    {
        color = QColor("ffff99");
        fontChar = IconHelper::Instance()->getFontMap().value("folder");
    }
    else
    {
        color = QColor(Qt::black);
//根据后缀名生成不同的文件图标
        fontChar = getSuffixChar();/*IconHelper::Instance()->getFontMap().value("file-text");*/
    }
    int w = qMax(10,q->height());
    int h = w;
    QRect srcRect(2,2,w-4,h-4);//绘制区域
    if(getSuffixType() == SUFFIX_IMAGE)//这里对图片文件做了一个缩放图处理,直接绘制图片
    {
        QPixmap pixmap(m_filePath);
        painter->drawPixmap(srcRect,pixmap.scaled(w,h,Qt::KeepAspectRatio),srcRect);
    }
    else
    {
        font.setPixelSize(h-4);
        painter->setFont(font);
        painter->setPen(color);
        painter->drawText(srcRect,Qt::AlignCenter,fontChar);
    }
}

 绘制文本,文本分为两块,一个是文件名称,一个是文件创建日期

void FileButtonPrivate::drawText(QStylePainter *painter)
{
    Q_Q(FileButton);
    QStyleOptionButton option;
    q->initStyleOption(&option);
    int startX = qMax(10,q->height())+5;
    int startY = 2;
    int nameHeight = 2*q->height()/3;
    QFont font = q->font();
    if(font.pixelSize()<=0)
    {
        font.setPixelSize(50);
    }
    int nameWidth = QFontMetrics(font).width(m_fileName);
    int timeWidth = QFontMetrics(font).width(m_fileTime);
    int fontHeight = QFontMetrics(font).height();
    painter->setPen(option.palette.color(QPalette::Current,QPalette::Text));
    font.setBold(true);

    while ((nameWidth > (q->width()-30-qMax(10,q->height())) || fontHeight>nameHeight)
           && font.pixelSize()>15
           ) {
        font.setPixelSize(font.pixelSize()-1);
    }
    painter->setFont(font);
    font = q->font();
    if(font.pixelSize()<=0)
    {
        font.setPixelSize(30);
    }
    option.rect = QRect(startX,startY,nameWidth,nameHeight);
    option.text = m_fileName;
    painter->drawControl(QStyle::CE_CheckBoxLabel,option);//绘制文件名
//    painter->drawText(QRect(startX,startY,nameWidth,nameHeight),Qt::AlignLeft | Qt::AlignVCenter,m_fileName);
    while ((timeWidth > (q->width()-30-qMax(10,q->height()))|| fontHeight>(q->height()/3)) && font.pixelSize()>10
           ) {
        font.setPixelSize(font.pixelSize()-1);
    }
    font.setBold(false);
    painter->setFont(font);
    option.rect = QRect(startX,startY+nameHeight+1,timeWidth,q->height()/3);
    option.text = m_fileTime;
    painter->drawControl(QStyle::CE_CheckBoxLabel,option);//绘制日期
//    painter->drawText(QRect(startX,startY+nameHeight+1,timeWidth,q->height()/3),Qt::AlignLeft | Qt::AlignVCenter,m_fileTime);

}

绘制箭头

void FileButtonPrivate::drawArrow(QPainter *painter)
{
    Q_Q(FileButton);
    int startX = q->width()-30;

    QChar fontChar;
    QFont font = IconHelper::Instance()->getIconFont();
    QColor color;
    color = QColor(Qt::gray);
    fontChar = IconHelper::Instance()->getFontMap().value("angle-right");
    QRect srcRect(startX,2,28,q->height()-4);
    font.setPixelSize(q->height()-4);
    painter->setFont(font);
    painter->setPen(color);
    painter->drawText(srcRect,Qt::AlignCenter,fontChar);
}

 

3.选择框界面实现

按钮准备好了,就是对各个组件的组装工作

核心代码如下:

void FileSelectDialogPrivate::initWidget()
{
    Q_Q(FileSelectDialog);
    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->setMargin(2);
    vlayout->setSpacing(5);
    q->setLayout(vlayout);

    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setMargin(5);
    hlayout->setSpacing(5);
    //返回按钮
    iconButton_Back = new IconButton;
    iconButton_Back->setObjectName("iconButton_Back");
    iconButton_Back->setFontIcon("arrow-left");
    iconButton_Back->setMinimumSize(50,50);
    //关闭按钮
    iconButton_close = new IconButton;
    iconButton_close->setFontIcon("times-circle");
    iconButton_close->setFontIconSize(50);
    iconButton_close->setMinimumSize(50,50);

    //标题
    label_caption = new QLabel;
    label_caption->setAlignment(Qt::AlignCenter);
    label_caption->setObjectName("label_caption");
    label_caption->setMinimumHeight(20);

    hlayout->addWidget(iconButton_Back);
    hlayout->addWidget(label_caption,1);
    hlayout->addWidget(iconButton_close);
    vlayout->addLayout(hlayout);

    //文件列表
    listButtonGroup = new QListWidget;
    listButtonGroup->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);
    listButtonGroup->setObjectName("listButtonGroup");
    listButtonGroup->setGridSize(QSize(120,65));

    vlayout->addWidget(listButtonGroup,1);

    connect(iconButton_Back,SIGNAL(clicked(bool)),this,SLOT(slot_backClicked(bool)));
    connect(iconButton_close,SIGNAL(clicked(bool)),q,SLOT(close()));

}

 

 

三、最终效果


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值