因为项目需求为嵌入式触屏操作,qt自带的文件选择框不适用触屏操作,所以参考Android的文件管理界面重新做了一个文件选择框
因为是一个小模块,所以需要进行拆解,大致可以分为标题栏区域,文件显示区域和操作区域。
从上面的图中可以看到每一个文件夹(或者文件)都是一个按钮,风格布局基本统一,所以第一步就是先实现这个小组件。这个小组件又可以拆分为图标、文件名称、创建日期和表示可以进入文件夹的箭头图标。
核心代码如下:
因为是个按钮所以直接继承QPushButton
#include
#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:
QSharedPointerd_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);
}
按钮准备好了,就是对各个组件的组装工作
核心代码如下:
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()));
}