简述
QTextEdit控件我这里就不做详细说明,如有需要请查看Qt官方文档。QTextEdit最常用的使用场景就是编辑框。它支持纯文本、富文本的编辑和查看功能比较强大,但我在使用中发现其原生的接口或使用场景有限不能满足开发者自定义的一些操作。因为项目需要做一个类似于即时通讯程序的消息输入控件故采用的QTextEdit这个控件。在使用中也遇到了一些难题在此记录一下我的解决方法和一些心得(大佬们有更好的方法也可以给小弟指点一二,不胜感激)记录在此和大家一下交流。
正文
- 从系统桌面拖拽文件或图片到QTextEdit,QTextEdit原生的拖拽文件或图片的操作显示的只是文件或图片的路径,这显然是不符合一个即时通讯工具消息编辑框的风格(参考微信、qq)。所以我们要做得好看一点就必须得自己重新实现这种操作,废话不多说直接上代码,这里文件和图片我是单独处理的
/*! * \brief 设置文件在编辑框中的图标 * \param strPath */ void EditDrop::SetEditImage(QString strPath) { qDebug()<<"FilePath:"<<strPath; if(strPath.isEmpty()) return; if(strPath.length() > 256) { QFileInfo fileTempInfo(strPath); qDebug() << QString("拖入文件失败,\"%1\" 文件名或文件源路径大于系统支持的长度,请重命名或更改路径后再试!").arg(fileTempInfo.fileName()); QString strError = QString("拖入文件失败,\"%1\" 文件名或文件源路径大于系统支持的长度,请重命名或更改路径后再试!").arg(fileTempInfo.fileName()); QMessageBox::information(this->window(), "提示", strError); return; } QFileInfo file(strPath); QHash<QString, QString>::iterator iter = m_hash_Path.find(strPath); if(iter != m_hash_Path.end()) { QMessageBox::information(this->window(), "提示", tr("正在待发送中,不能重复发送。")); return; } if(!file.exists()) { QMessageBox::information(this->window(), "提示", "该文件不存在,可能被删或被移动,无法发送!"); return; } else if(file.isFile()) { if(file.size() == 0) { QMessageBox::information(this->window(), "提示", tr("%1,该文件为空文件,无法发送,请重新选择。").arg(file.fileName())); return; } if(file.suffix().contains("lnk")) { QMessageBox::information(this->window(), "提示", tr("%1,暂不支持发送该类型文件。").arg(file.fileName())); return; } } else { QMessageBox::information(this->window(), "提示", "暂不支持发送文件夹"); return; } //m_hash_Path[strPath] = strPath; QString strSize = toalSize(file.size()); QFileIconProvider fileicon; QIcon sss = fileicon.icon(file); QPixmap pix = sss.pixmap(100, 100); pix = pix.scaled(35,35, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); QSize size = pix.size(); // if(size.width() == 0) // return; //画图片 QPixmap pixmap(pix_width, pix_height); pixmap.fill(Qt::transparent); int y = (pix_height - size.height() - rect_spac * 2) / 2; QPainter painter(&pixmap); painter.drawPixmap(pix_spac + rect_spac, y, pix); //画文字 QFont font("Microsoft YaHei UI", 10); painter.setFont(font); QFontMetrics fm(font); int t_height = fm.boundingRect(strPath).height(); int x = pix_spac * 2 + rect_spac + size.width(); QString newFileName = strPath; QFileInfo newFileInfo(newFileName); QString strElidedText = fm.elidedText(newFileInfo.fileName(), Qt::ElideMiddle, 200, Qt::TextShowMnemonic); painter.drawText(QPoint(x, 20), strElidedText); painter.drawText(QPoint(x, 20 + t_height), strSize); //画边框 painter.setPen(QPen(QColor("#d0d0d0"))); painter.drawRect(rect_spac, rect_spac, pix_width - 3, pix_height - 3); QTextDocument * textDocument = this->document(); textDocument->addResource( QTextDocument::ImageResource, strPath, QVariant(pixmap)); QTextCursor cursor = this->textCursor(); cursor.beginEditBlock(); QTextImageFormat imageFormat; imageFormat.setWidth(pixmap.width()); imageFormat.setHeight(pixmap.height()); imageFormat.setName(strPath); cursor.insertImage(imageFormat); cursor.endEditBlock(); }
处理拖拽进来的文件中加入了一些操作习惯的判断,对文件的一些判断具体的代码里面有体现。该方法现在有个已知bug:安装winrar解压软件v5.50版本时文件图标会很小如图:
如果各位大佬有解决方案,回复小弟一下,不胜感激!
下面是处理拖拽图片接口
/*! * \brief 处理拖拽或剪切进来的图片 * \param image 图片数据 * \param url 图片路径 * \return */ QString EditDrop::SetPixPath(const QImage &image,const QUrl &url) { QPixmap pix = QPixmap::fromImage(image); QString TempPath = GetTempScreenFilePath(); QString path = TempPath + url.toString() + ".PNG"; pix.save(path,nullptr); QUrl pathurl(path); QHash<QString, QString>::iterator iter = m_hash_Path.find(path); if(iter != m_hash_Path.end()) { QMessageBox::information(this->window(), "提示", tr("%1,已有该图片。").arg(path)); return ""; } int width ; int height; width = pix.width(); //获得以前图片的宽和高 height = pix.height(); int width_im = width; int height_im = height; if(width > 120) width_im = 120; if(height > 100) height_im = 100; double dvalue = 0.0; if(width > height) { dvalue = (double)height / (double)width; height_im = (double)width_im * dvalue; } else { dvalue = (double)width / (double)height; width_im = (double)height_im * dvalue; } if(width_im < 30) width_im = 30; if(height_im < 20) height_im = 20; QPixmap pixmap = pix.scaled(width_im, height_im, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); QImage image_test = pixmap.toImage(); document()->addResource(QTextDocument::ImageResource, pathurl, image_test); QTextCursor cursor = this->textCursor(); cursor.beginEditBlock(); QTextImageFormat imageFormat; imageFormat.setWidth(pixmap.width()); imageFormat.setHeight(pixmap.height()); imageFormat.setName(path); cursor.insertImage(imageFormat); cursor.endEditBlock(); return path; }
效果图:拖拽进来的图片我这里做了个缓存,当在编辑框复制该图片时能找到该图片的路径,图片也做了缩放处理。具体处理方法代码里面有体现。
-
即时通讯工具肯定少不了表情之类的功能,QTextEdit原生的功能可以加载并显示表情,但复制粘贴的操作必须要自己重新实现(原生的公能第二次复制粘贴时就只显示路径了)代码如下:
/*! * \brief 加载表情到编辑框 * \param strPath 表情路径 */ void EditDrop::SetEmojiPath(QString strPath) { QPixmap pixmap(strPath); QTextDocument * textDocument = this->document(); textDocument->addResource( QTextDocument::ImageResource, strPath, QVariant(pixmap)); QTextCursor cursor = this->textCursor(); cursor.beginEditBlock(); QTextImageFormat imageFormat; imageFormat.setWidth(pixmap.width()); imageFormat.setHeight(pixmap.height()); imageFormat.setName(strPath); cursor.insertImage(imageFormat); cursor.endEditBlock(); m_list_emoji.append(strPath); this->window()->activateWindow(); this->setFocus(); } //测试发现这种添加资源的方法会影响效率,目前还没找到解决办法
由于篇幅过长请各位大佬移步小弟第二篇文章.....