根据软件需求和设计的思路,提词器主体的部分应该就是一个无框的窗体,然后叠加一个qtextedit,利用qtextedit的滚动条功能,结合qtimer实现定时滚动的功能。
有个qt编写经验的同学其实知道,如果直接用ui建立widget的模式,实现无框窗体的话,设置qtextedit背景透明是没有问题的,关键是如果要实现窗体的移动和缩放就没有那么容易的了,你不能强制客户只在某一个位置点击鼠标然后移动和拖放,客户需要傻瓜化的操作,所以就必须考虑窗体边界的自动识别以及在窗体外围拖拉鼠标进行缩放,以及鼠标在窗体任意位置点击后都可以进行窗体移动的可能。
本章尽然是为了在crtl+c和crtl+v的基础上进行拼接开发,那就祭出大杀器,程序员的参考宝库,github.com,国内是gitee,不过很多资源是搬迁自github的,那就直接github吧。打开网页,搜索qt 无框窗体,当然你也可以直接搜索提词器或者英文的关键词,也有一个开源的qpromt,不过看着感觉不是太爽,所以就从最基础的开始。
搜索关键词:FramelessWindow,无框窗体,提词器等等,然后看带qt的,日期不要太远,然后最好有点forks的。然后就找到了一个。

看描述,qt 无边框窗口,支持边界缩放,ok,就他了,再次感谢下分享该资源的朋友。
不过进去看下,内容太简单了,有很多功能不是需要的,而且有些监听事件重复,编译运行下,好像功能有部分并没有实现,软件最贵的是借鉴别人的思路,里面窗体和边界缩放还是不错的,直接把这个作为基础,然后把不用的代码测试删除,只保留无框窗体painter部分和边界缩放部分代码。

透明窗体刷新和重绘部分

void Widget::resizeBackground(int w, int h, int round, int margin, QColor color)
{//如果窗口高度与屏幕高度相同,设置全屏模式,取消白边与圆角if(height() == screenHeight)round = margin = 0;m_bkImg = QImage(size(), QImage::Format::Format_ARGB32);m_bkImg.fill(QColor(0,0,0,0));//背景透明 int r, int g, int b, int aQPainter painter(&m_bkImg);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);QPainterPath painterPath;painter.setPen(color);painterPath.addRoundedRect(margin, margin, w - 2 * margin, h - 2 * margin, round, round);painter.fillPath(painterPath, color);for (int i = 0; i < margin; i++){QPainterPath path;path.setFillRule(Qt::WindingFill);path.addRoundedRect(margin - i, margin - i, w - (margin - i) * 2, h - (margin - i) * 2, round, round);color.setAlpha(static_cast<int>((margin - i - 1) / (1.0 * margin) * 192));QPen pen(color);pen.setWidth(1);painter.setPen(pen);painter.drawPath(path);}
}void Widget::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);painter.drawImage(0, 0, m_bkImg.scaled(this->size()));//qDebug()<< "paint event";
}

边界判断部分

void Widget::region(const QPoint &cursorGlobalPoint, bool &activeFlag)
{QRect rect = this->rect();QPoint tl = mapToGlobal(rect.topLeft());QPoint rb = mapToGlobal(rect.bottomRight());int x = cursorGlobalPoint.x();int y = cursorGlobalPoint.y();activeFlag = true;if (tl.x() + PADDING + 2 >= x && tl.x() <= x && tl.y() + PADDING + 2 >= y && tl.y() <= y) {m_dir = WMSZ_TOPLEFT;this->setCursor(QCursor(Qt::SizeFDiagCursor));} else if (x >= rb.x() - PADDING - 2 && x <= rb.x() && y >= rb.y() - PADDING - 2 && y <= rb.y()) {m_dir = WMSZ_BOTTOMRIGHT;this->setCursor(QCursor(Qt::SizeFDiagCursor));} else if (x <= tl.x() + PADDING + 2 && x >= tl.x() && y >= rb.y() - PADDING - 2 && y <= rb.y()) {m_dir = WMSZ_BOTTOMLEFT;this->setCursor(QCursor(Qt::SizeBDiagCursor));} else if (x <= rb.x() && x >= rb.x() - PADDING - 2 && y >= tl.y() && y <= tl.y() + PADDING + 2) {m_dir = WMSZ_TOPRIGHT;this->setCursor(QCursor(Qt::SizeBDiagCursor));} else if (x <= tl.x() + PADDING && x >= tl.x()) {m_dir = WMSZ_LEFT;this->setCursor(QCursor(Qt::SizeHorCursor));} else if (x <= rb.x() && x >= rb.x() - PADDING) {m_dir = WMSZ_RIGHT;this->setCursor(QCursor(Qt::SizeHorCursor));} else if (y >= tl.y() && y <= tl.y() + PADDING){m_dir = WMSZ_TOP;this->setCursor(QCursor(Qt::SizeVerCursor));} else if (y <= rb.y() && y >= rb.y() - PADDING) {m_dir = WMSZ_BOTTOM;this->setCursor(QCursor(Qt::SizeVerCursor));} else {m_dir = -1;this->setCursor(QCursor(Qt::ArrowCursor));activeFlag = false;}
}

本地事件监听与鼠标事件反馈(savexmlsetting部分是后面添加的,实现窗体移动后保存参数,下次启动后窗体实现位置记忆功能)

bool Widget::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{Q_UNUSED(result)if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG"){auto msg = reinterpret_cast<MSG*>(message);if(msg->hwnd != reinterpret_cast<HWND>(this->winId())) return false;if (msg->message == WM_MOUSEMOVE){bool activeFlag;region(cursor().pos(), activeFlag);}else if (msg->message == WM_SIZING){qDebug() << "wm sizing";}else if (msg->message == WM_MOVING){qDebug() << "wm moving";}}//qDebug() << "native event filter";return false;
}void Widget::mousePressEvent(QMouseEvent *event)
{bool activeFlag;region(cursor().pos(), activeFlag);//qDebug() << "check left button " << activeFlag << m_dir;if(event->button() == Qt::LeftButton){if(::ReleaseCapture()){if (activeFlag &&  m_dir > 0) {::SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_SIZE | m_dir, 0);}::SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);QRect rect = this->rect();QPoint tl = mapToGlobal(rect.topLeft());posx = tl.x();posy = tl.y();savexmlsetting("posx",QString("%1").arg(posx));savexmlsetting("posy",QString("%1").arg(posy));}//qDebug() << "check Left Button";}else if(event->button() == Qt::RightButton){//qDebug() << "check Right Button";}else if(event->button() == Qt::MidButton){//qDebug() << "check middle Button";}//qDebug() << "mousepressevent" << event->button();__super::mousePressEvent(event);
}

窗体缩放后,根据缩放进行事件处理,原作者是重绘窗体,此处上面加了窗口缩放后尺寸大小的记忆功能

void Widget::resizeEvent(QResizeEvent *event)
{Q_UNUSED(event)ticiW = width();ticiH = height();savexmlsetting("width",QString("%1").arg(ticiW));savexmlsetting("height",QString("%1").arg(ticiH));if(height() != screenHeight){m_normalSize = size();}resizeBackground(width(), height(), 0, 0, QColor(backR,backG,backB,backA));//set your like//qDebug() << "resizeEvent";
}

运行测试,一个可改变背景的透明窗体就ok了,大房子第一步,平面图搞定,就像一个画板,先确定布局,后面就可以在此界面上在进行后续的搭建和绘画。

五天拼出一款提词器软件之二软件基础代码与功能实现相关推荐

  1. 五天拼出一款提词器软件之一项目立项与准备

    直播是这两年的热门,不过我属于后知后觉的,没有搭上顺风车,也没有想上这辆车.前期一个朋友做直播器材的销售,想与学校对接做一些项目,然后对直播方面才多了一些了解,朋友提到除了各种直播平台之外,做直播的更 ...

  2. 有没有免费的提词器?这款软件很好用

    有没有免费的提词器?从事教师行业的小伙伴们每天都需要给学生进行上课,对于一些老教师来说上课是件十分轻松的事情.但是对于新手老师来说,上课总是会出来忘词.卡顿等情况.这种情况下我们有个好用的提词器就显得 ...

  3. 推荐几款适用于手机做直播的提词器,快来收藏

    从事自媒体的小伙伴们或许都会使用一些提词器来帮助自己,提词器的使用不仅能够在拍摄视频时为我们提示台词,节省我们记忆台词的时间,还能够使得我们在拍摄时自信.流畅地进行口播,顺利地完成视频的拍摄,避免忘词 ...

  4. 手机滚动字幕软件java_提词器app下载

    提词器安卓版是一款非常好用的手机滚动字幕软件,支持视频和音频等多种录制方式,可以提前把将要说的话录到里面,避免忘词尴尬,适用于众多场景,方便又快捷,欢迎喜爱的朋友下载使用! 官方介绍 专业视频拍摄台词 ...

  5. 提词器app用什么好?这里有你想知道的答案

    随着现在各大视频平台的不断发展,越来越多的人加入了视频制作的行列.不知道各位小伙伴有没有自己拍摄过视频?小伙伴们在拍摄视频的时候,会因为面对镜头紧张,而导致忘词吗?为了能让视频拥有更好的拍摄效果,一款 ...

  6. 手机直播提词器哪个软件好?这两款软件值得收藏

    相信做视频自媒体的小伙伴,常常都会遇到一个问题,那就是忘词,导致需要重新录制视频.很多小伙伴都有在问,要怎么样才可以做到流畅的录制视频,其实我们只需要一个提词器,就看减少因错漏.忘词而导致视频需要重新 ...

  7. QPrompt:一款为视频创作者提供的自由开源的提词器

    这些天来,各种各样的人都在创建视频内容.从专业的 YouTubers 到学校教师,创建视频内容已经成为各种工作内容的一部分. 从屏幕记录器到视频编辑器,有各种工具可以帮助创建良好的视频.提词器也是这样 ...

  8. 这两款软件让你实现把手机屏幕变成提词器

    随着短视频逐渐的火热发展,越来越多的人都拿起手机加入了制作短视频的队伍中.对于第一次面对镜头的人来说,难免会感到紧张,总会时不时的出现一些小差错,导致视频的拍摄不完整. 其实我们可以借助软件来让我们在 ...

  9. 三分钟时间告诉你提词器哪款软件好用

    现在短视频的发展已经是一股不可阻挡的潮流了,也有许多小伙伴开始尝试加入短视频的行业.但对一些面对镜头就紧张,忘词的小伙伴来说,拍摄短视频的难度要远远大于其他人.其实我们可以运用好一些软件,来辅助我们更 ...

最新文章

  1. 有关ubuntu16.04进行sudo apt-get update更新时出现:‘。。。N: 无法安全地用该源进行更新,所以默认禁用该源。。。’等问题解决方案
  2. apache 不解释php,apache-2.2 – Apache不解释.PHP文件
  3. OpenGL sparsetexture稀疏纹理的实例
  4. win10无法检测java_Javac 在windows10系统不识别
  5. android mvvm流程图,MVVM框架模式详解
  6. 一个简单的python日志服务器
  7. java中set怎么建int型_使用Array.setInt来填充Java中的数组
  8. 一个没暂时没有办法实现的问题和一个有意思的小问题!
  9. RocketMQ 延时消息的使用和延时级别的配置
  10. JavaScript中的“黑话”
  11. 方块方舟怎么自建服务器,方块方舟新版更新,玩家可自定义单机局域网数值
  12. w3cschool数据库mysql教程_SQLite 简介 | w3cschool菜鸟教程
  13. 一次帮妹子去水印经历<反编译DLL>
  14. java面试(1)如何防止恶意攻击短信验证码接口
  15. Burp Suite配合xray代理socks流量
  16. java 句柄无效_java.io.IOException: 句柄无效 异常是什么引起的
  17. 软件测试人员常用的SQL语句
  18. 如何将docx文本转换成使用微信小程序rich-text能编译的格式
  19. Mac用Pycharm安装mediapipe报错ERROR: Could not find a version that satisfies the requirement mediapipe
  20. Windows系统中 Xmanager 6 企业版下载安装激活教程

热门文章

  1. 售价40万,年租金500的房子值得投资不?
  2. 生产力工具推荐,思维导图测评 #CSDN博文精选##思维导图##系统化学习#
  3. 标准15针 VGA 显示接口定义及焊接方法
  4. 《中国人工智能学会通讯》——2.5 智能汽车人机交互与人机协同技术 的研究进展...
  5. ubuntu中文和韩文共存,韩文字体显示不清楚
  6. NPN的工作原理是什么?
  7. 基于javaweb+JSP+Servlet学生成绩管理系统(管理员、教师、学生)
  8. 我是大富翁安卓小游戏开发成果
  9. 斗图神器DIY多功能微信小程序源码下载支持多流量主
  10. PPNP和APPNP