QTextEdit是一个可以显示各种复杂类型信息的控件,比如文本信息,图片,html等,有时作为输入框我们需要实现拖拽展示或发送一些文件等,而如果要实现拖拽发送文件,这个时候需要重载dropEvent事件和insertFromMimeData()函数,在使用这两个函数的过程中,发现拖拽文件时,source获取的信息都是文本信息即一个路径,而复制功能,粘贴也是一段文本信息,而这样就有一个问题了,发送信息时,我复制一段存在的文件的路径是否把这个当作是文件呢还是纯文本呢,例如:拖拽D盘bak目录下的11111.png文件
好在经过查看验证发送hasUrls可以区分是复制的文件Url还是纯文本信息,当然QMimData还有其他属性,但只有这个能区分这种情况,下面请看示例:
CustomTextEdit.h
#ifndef CUSTOMTEXTEDIT_H
#define CUSTOMTEXTEDIT_H
#include <QTextEdit>
#include <QDropEvent>
class CustomTextEdit: public QTextEdit
{
Q_OBJECT
public:
CustomTextEdit(QWidget *parent = nullptr);
QStringList getSplitUrl(QString text);
QString getFileSizeFormat(qint64 size);
QPixmap getFileIconPixmap(const QString &path);
signals:
void signalShowIcon(const QPixmap &pix);
protected:
void insertFromMimeData(const QMimeData *source) override;
void dropEvent(QDropEvent *event) override;
bool canInsertFromMimeData(const QMimeData *source) const override;
};
#endif // CUSTOMTEXTEDIT_H
CustomTextEdit.cpp
#include "CustomTextEdit.h"
#include <QDebug>
#include <QMimeData>
#include <QFileInfo>
#include <QClipboard>
#include <QApplication>
#include <QMessageBox>
#include <QPixmap>
#include <QFileIconProvider>
#include <QPainter>
#include <QIcon>
#include <QFont>
CustomTextEdit::CustomTextEdit(QWidget *parent)
:QTextEdit(parent)
{
}
void CustomTextEdit::dropEvent(QDropEvent *event)
{
insertFromMimeData(event->mimeData());
event->accept();
}
QStringList CustomTextEdit::getSplitUrl(QString text)
{
QStringList urls;
if(text.isEmpty())
return urls;
QStringList list = text.split("\n");
foreach (QString url, list) {
if(!url.isEmpty()){
// url = file:///D:/bak/11111.png
QFileInfo info(url);
qDebug() << "======getUrl=======url===" << url << "==info.exists==" << info.exists()<< __LINE__;
QStringList str = url.split("///");
// str== ("file:", "D:/bak/11111.png")
if(str.size()>=2)
{
QFileInfo info2(str.at(1));
qDebug() << "======getUrl=======url===" << url << "==info2.exists==" << info2.exists() << __LINE__;
urls.append(str.at(1));
}
}
}
return urls;
}
void CustomTextEdit::insertFromMimeData(const QMimeData *source)
{
qDebug() << "======insertFromMimeData=======1===hasText===" << source->hasText() << __LINE__;
qDebug() << "======insertFromMimeData=======1===hasUrls===" << source->hasUrls() << __LINE__;
qDebug() << "======insertFromMimeData=======1===hasHtml===" << source->hasHtml() << __LINE__;
qDebug() << "======insertFromMimeData=======1===hasImage===" << source->hasImage() << __LINE__;
qDebug() << "======insertFromMimeData=======1===hasColor===" << source->hasColor() << __LINE__;
QString insertInfo = source->text();
if(insertInfo.isEmpty())
return;
QClipboard *clipBoard= QApplication::clipboard();
QString strClip = clipBoard->text();
qDebug() << "======insertFromMimeData=======2===clipBoard===" << strClip << __LINE__;
qDebug() << "======insertFromMimeData=======2===source->text()===" << source->text() << __LINE__;
QStringList strList = getSplitUrl(insertInfo);
qDebug() << "======insertFromMimeData=======2===strList===" << strList << __LINE__ << "\n\n";
bool isFile = source->hasUrls();//这个标志非常重要,因为不管理是拖拽文件还是复制文本信息,source->text()都是有值的,就能区分是复制的文本还是文件
if(!isFile)//纯文本类型
{
this->setText(insertInfo);
}
else if(1 == strList.size())
{
QFileInfo fileInfo(strList[0]);
if(fileInfo.isDir())
{
QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("不允许拖拽目录!"));
return;
}
if(fileInfo.size() > 50 * 1024 * 1024)
{
QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("发送的文件大小不能大于50M"));
return;
}
QPixmap pix = getFileIconPixmap(strList[0]);
emit signalShowIcon(pix);
}
else if(strList.size() > 1)
{
QMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("只允许拖拽单个文件!"));
}
}
QPixmap CustomTextEdit::getFileIconPixmap(const QString &path)
{
QFileIconProvider provder;
QFileInfo fileInfo(path);
QIcon icon = provder.icon(fileInfo);
QString strFileSize = getFileSizeFormat(fileInfo.size());
QFont font(QString("Microsoft YaHei"));
font.setPixelSize(12);
QFontMetrics fontMetrics(font);
QSize textSize = fontMetrics.size(Qt::TextSingleLine, fileInfo.fileName());
QSize fileSize = fontMetrics.size(Qt::TextSingleLine, strFileSize);
int maxWidth = textSize.width() > fileSize.width() ? textSize.width() :fileSize.width();
QPixmap pix(50 + maxWidth + 10, 50);
pix.fill();
QPainter painter;
painter.begin(&pix);
// 文件图标
QRect rectIcon(0, 0, 50, 50);
painter.drawPixmap(rectIcon, icon.pixmap(40,40));
painter.setPen(Qt::black);
// 文件名称
QRect rectText(50+10, 3, textSize.width(), textSize.height());
painter.drawText(rectText, fileInfo.fileName());
// 文件大小
QRect rectFile(50+10, textSize.height()+5, fileSize.width(), fileSize.height());
painter.drawText(rectFile, strFileSize);
painter.end();
return pix;
}
QString CustomTextEdit::getFileSizeFormat(qint64 size)
{
QString strSize;
double num;
if(size < 1024){
num = size;
strSize = "B";
}
else if(size < 1024 * 1224){
num = size / 1024.0;
strSize = "KB";
}
else if(size < 1024 * 1024 * 1024){
num = size / 1024.0 / 1024.0;
strSize = "MB";
}
else{
num = size / 1024.0 / 1024.0/ 1024.0;
strSize = "GB";
}
return QString::number(num,'f',2) + " " + strSize;
}
bool CustomTextEdit::canInsertFromMimeData(const QMimeData *source) const
{
return source->hasImage() || source->hasUrls() ||
QTextEdit::canInsertFromMimeData(source);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "CustomTextEdit.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initView();
void initData();
public slots:
void slotShowFileIcon(const QPixmap &pix);
private:
Ui::MainWindow *ui;
CustomTextEdit *textEdit{nullptr};
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
initView();
initData();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initView()
{
ui->label->setText("");
textEdit = new CustomTextEdit(this);
connect(textEdit, &CustomTextEdit::signalShowIcon, this, &MainWindow::slotShowFileIcon);
textEdit->setGeometry(QRect(10, 10, 300, 450));
textEdit->show();
}
void MainWindow::initData()
{
}
void MainWindow::slotShowFileIcon(const QPixmap &pix)
{
ui->label->setPixmap(pix);
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
运行结果:
从D盘bak目录下拖拽11111.png文件到TextEdit
复制file:///D:/bak/11111.png到TextEdit