在 Qt 中高效地绘制物理上精确的标尺

2023-12-01

我有一个统治者类(称为Graduation)使用方向来计算应在何处绘制线条。像这样:

enter image description here

当方向设置为Qt::Horizontal I do line_xpos = precendent_line_xpos + number。那么如果方向是Qt::Vertical我添加到 y 位置。

我下面有一些代码,这是我如何执行此操作的示例if...else and ?:声明:

/* std::vector<QLineF> m_lines; */

void Graduation::resizeEvent(QResizeEvent *event)
{   
    qreal newLength = (m_orientation == Qt::Horizontal)
        ? event->size().width()
        : event->size().height();
    qreal oldLength = (m_orientation == Qt::Horizontal)
        ? event->oldSize().width()
        : event->oldSize().height();

    if(newLength != oldLength) {
        if(newLength < oldLength) { /* Delete lines */
            int count = m_lines.size();
            if(count == 0)
                return;

            if(m_orientation == Qt::Horizontal) {
                while(m_lines[count-1].x1() > newLength) {
                    --count;
                }
            } else {
                while(m_lines[count-1].y1() > newLength) {
                    --count;
                }
            }

            m_lines.erase(
                m_lines.begin()+count,
                m_lines.begin()+m_lines.size()
            );
        } else
          /* ... Append lines ... */
    }
}

这是显示如何绘制线条的paintEvent:

void Graduation::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QPainter painter(this);
    painter.setPen(QPen(Qt::black, 0.5));

    for(unsigned int i = 0; i < m_lines.size(); ++i)
        painter.drawLine(m_lines[i]);
}

我想知道我是否可以避免对这些条件进行数千次检查。我感兴趣的是您可以使用什么代码模式来避免这种情况(尽管最好只计算一次线条位置并只绘制可见的部分).


好的,在您发布该图像后,看起来您确实可以寻求更简单且有效的解决方案。

你的线条形成了一个可重复的图案,因此,绘制整个事物、手动管理线条等等都是一种浪费。您可以创建一个小的像素图并仅绘制重复图案的一段,如下所示:

pattern

然后根据方向,您可以保持原样或旋转/翻转它。然后你可以使用QPainter来填补你的Graduation小部件与它Qt::TexturePattern using QBrush::setTexture(pixmap)它会快速有效地用图案填充整个小部件的长度/高度,无论它有多少。

如果您想更改标尺的样式或间距,您所要做的就是重新绘制缓存的图案并使用相同的过程来更新标尺。

最后但并非最不重要的一点是,您可以使用 Qt 提供的布局将标尺固定到正确的位置,以便 100% 自动管理它们,从而使您当前使用的逻辑变得多余。

好的,这里有更多帮助,另外这将向您展示不必每条线都画线,代码很简单,并且将为给定的 DPI 生成图案段:

QPixmap drawCMPattern(qreal dpi) {
    qreal dpcm = dpi / 2.54;
    QPixmap rulerCache(dpcm, dpcm / 2);
    rulerCache.fill();
    qreal dpmm = dpcm / 10;
    QPainter p(&rulerCache);
    p.setRenderHint(QPainter::HighQualityAntialiasing);
    qreal lineWidth = dpmm / 5;
    p.setPen(QPen(Qt::black, lineWidth));
    qreal xpos = lineWidth / 2;
    for (int i = 0; i < 10; ++i) {
        if (i == 0) p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height()));
        else if (i == 5) p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height() / 2));
        else p.drawLine(QLineF(xpos, 0, xpos, rulerCache.height() / 4));
        xpos += dpmm;
    }
    return rulerCache;
}

您可能会注意到,在典型的低 DPI 桌面显示器上,线条有些模糊,但这就是您为实现“物理精确”而付出的代价 - 您要么是公制完美,要么是像素完美,除非您的 DPI 与公制单位匹配,否则您不能两者兼得。完美的是,大多数线条必然发生在像素之间。在高 DPI 移动设备上,它看起来不会那么糟糕。

或者,如果省略,您可以获得清晰的线条HighQualityAntialiasing,但是这些线的距离将不相等。尽管如此,这可能对您有好处,因为它对于像 Photoshop 这样的商业软件来说显然已经足够好了:

PS ruler

然而,PS 比较棘手,1 厘米内的线条较少,因此差异并不像每毫米有一条线时那么明显。以下是该代码结果在我的 108.79 DPI 桌面上的外观:

this code

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Qt 中高效地绘制物理上精确的标尺 的相关文章

  • PySide6.1 与 matplotlib 3.4 不兼容

    当我只安装PySide6时 GUI程序运行良好 但是一旦我安装了matplotlib及其依赖包 包括pyqt5 则GUI程序将无法运行并输出以下错误消息 This application failed to start because no
  • 如何在类文件中使用 Url.Action() ?

    如何在 MVC 项目的类文件中使用 Url Action Like namespace 3harf public class myFunction public static void CheckUserAdminPanelPermissi
  • 按扩展名过滤搜索文件返回太多结果

    我正在开发一个 C 控制台应用程序 它必须管理 Windows 操作系统上的文件 我需要获取具有特定扩展名的文件名 列表 我找到了很多解决方案 最建议的是以下一种 HANDLE hFind WIN32 FIND DATA data hFin
  • 从复选框列表中选择循环生成的复选框中的一个复选框

    抱歉我的英语不好 在我的 ASP NET 网站上 我从 SQL 表导入软件列表 看起来像这样 但实际上要长得多 Microsoft Application Error Reporting br br Microsoft Applicatio
  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • java中如何重新初始化int数组

    class PassingRefByVal static void Change int pArray pArray 0 888 This change affects the original element pArray new int
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 如何使用 Regex.Replace 从字符串中删除数字?

    我需要使用Regex Replace从字符串中删除所有数字和符号 输入示例 123 abcd33输出示例 abcd 请尝试以下操作 var output Regex Replace input d string Empty The d标识符
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 如何使用 x64 运行 cl?

    我遇到了和这里同样的问题致命错误 C1034 windows h 未设置包含路径 https stackoverflow com questions 931652 fatal error c1034 windows h no include
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • C++:二叉树所有节点值的总和

    我正在准备面试 我被一个二叉树问题困住了 我们如何计算二叉树所有节点中存在的值的总和 优雅的递归解决方案 伪代码 def sum node if node NULL return 0 return node gt value sum nod
  • 了解 Lambda 表达式和委托 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我已经尝试解决这个问题很长一段时间了 阅读在线博客和文章 但到目前为止还没有成功 什么是代表 什么是 Lambda 表达式 两者的优点
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names
  • 我可以使用 lambda 函数或 std::function 对象来代替函数指针吗?

    我有一个需要使用的库 它定义了以下内容 typedef void CallbackFunction const int i 并且有一个注册回调的函数 如下所示 void registerCallback CallbackFunction p

随机推荐

  • Cronjob 但适用于 jQuery/Javascript

    我正在尝试开发一个主要使用 PHP 的 Web 应用程序 但我正在使用 jQuery Javascript 从人们的 URL 中获取他们的推文 问题是想要运行 PHP cron 作业来获取已注册我的应用程序的人的最新推文 但我不知道如何用
  • Scip 与 Pyomo 接口的问题

    我正在尝试使用 Pyomo 解决非线性优化问题 首先 我尝试了 Ipopt 求解器 并且运行起来了 然后我想尝试一下求解器Scip由于 Ipopt 是局部求解器 因此尝试进行全局优化 但是 我在使用它时遇到了我无法理解的错误 让 Scip
  • SSIS 包将不再在 Visual Basic 中执行 - 而是通过“构建”

    我是一个超级初学者 使用 Visual Studio 2017 创建我的第一个 SSIS 包 此包打开一个平面文件 csv 并将其添加到 SQL 服务器上的表中 当我按下 开始 按钮 在 Visual Studio 中 时 SSIS 包可以
  • 相对位置的顶部未按预期工作

    为什么 top 属性不起作用 img 当标签 img 是兄弟姐妹 p 但是如果我删除标签 p p 这有效 html body height 100 img position relative top 40 p p Lorem ipsum d
  • 以编程方式将 ipython 笔记本保存为脚本

    优秀的ipython笔记本有一个方便的 script命令行标志自动将笔记本的副本保存为 py脚本文件 删除任何标题和 Markdown 单元格 有没有办法在笔记本打开后从笔记本内部打开此功能 显然 此选项无法访问 config magic
  • 使用jna消费按键事件

    在我正在编写的应用程序之一中 我需要使用某些关键事件 以便其他应用程序不处理它们 在我的代码中 我创建了一个 com sun jna platform win32 WinUser LowLevelKeyboardProc 如下所示 impo
  • 在 Java 中从键盘读取 double

    如何在 Java 中从键盘读取双精度变量 我正在尝试解决这个问题 但没有成功 它说 线程 main 中的异常 java util InputMismatchException 在 java util Scanner throwFor Sca
  • 正则表达式重复字符计数

    如果我有一组像 abcdefghij 这样的字符并使用这些字符 我会使用这些字符随机生成一个密码 例如 生成的密码可以有 6 个字符 如何使用正则表达式验证密码 以使相邻字符不相同并且字符不会重复两次以上 你可以使用类似的东西 1 neig
  • 我可以在 C# 项目上使用 .rc 资源文件吗?

    我有一个 C 解决方案 我需要更新资源文件中的版本 resx 文件是 xml 文件 我已经在 C 资源文件 不是 xml 文件 中完成了它 我想知道是否可以使用类似的东西在我的 C 项目中 您无法直接从 Visual Studio 执行此操
  • 如何通过 Azure 上传小文件 API 在 Yammer API 上上传文件

    如何随 Yammer 消息一起上传附件 任何遗留方法通过attachment1等领域 messages json端点将不再工作 新方法没有很好的记录 https developer yammer com docs upload files
  • com.sun.faces.context.PartialViewContextImpl.createPartialResponseWriter 处的 java.lang.NullPointerException

    我在 JBoss AS 7 1 上的 JSF 2 应用程序中有一个带有延迟加载的 PrimeFaces 5 1 数据表 它在页面加载时排序 所以我知道我的排序实现有效 但是当我单击列进行排序时 它会抛出以下异常 17 48 34 855 E
  • UIWebView 中的 Javascript 回调到 C/Objective-C

    当在 UIWebView 中检测到特定事件时 有没有办法获得对 Objective C 的回调 Javascript 可以向 Objective C 发送回调吗 更新 不再使用 UIWebView 使用 WKWebView 或更好的 Saf
  • 使用本机函数计算 Google 表格的分层标签

    使用 Google Sheets 我想自动对行进行编号 如下所示 关键是我想要这个使用内置函数 only 我有一个实现 其中子项位于单独的列中 例如 Foo 位于 B 列中 Bar 位于 C 列中 Baz 位于 D 列中 但是 它使用自定义
  • boost Spirit x3分裂后奇怪的语义行为

    在我将语法分成推荐的语法后 我遇到了 boostspirit x3 的奇怪行为parser hpp parser def hpp parser cpp文件 我的示例语法解析某种简单的枚举 enum enum gt identifier gt
  • 如何在 C++ 中使用 libgit2 检查是否需要 pull ? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我想检查我是否有最新版本的程序 我已将我的程序共享到 bitbucket org 并且如果我需要提取最新版本 或者我已经拥有最新版本 我希望我的 C 代码可以写给我 首先 您必须
  • jquery $.post() 被取消[重复]

    这个问题在这里已经有答案了 每当我执行 jquery post 时 我都会收到 已取消 状态 看起来像是异步问题 我通过以下方式访问本地项目http 127 0 0 1 8933 myproject default index html 索
  • 如何在C中不使用科学记数法显示大双数?

    如何显示双重喜欢 5000683 代替5 000683e6 in C 我努力了 d g and f 但无济于事 看起来像 f工作得很好 include
  • SQL Server 触发器 - 按事务分组

    在工作中 我们刚刚开始为数据库构建审核框架 即记录创建或更新数据时发生的更改 我们非常希望使用触发器来实现这一点 因为数据有时会从其他地方导入到系统中 而不仅仅是通过前端 这似乎是一个相当共同解决方案 不过 我想补充一点 如果用户运行更新多
  • Ruby 方法instance_eval() 和send() 是否否定了私有可见性的好处?

    w Widget new Create a Widget w send utility method Invoke private method w instance eval utility method Another way to i
  • 在 Qt 中高效地绘制物理上精确的标尺

    我有一个统治者类 称为Graduation 使用方向来计算应在何处绘制线条 像这样 当方向设置为Qt Horizontal I do line xpos precendent line xpos number 那么如果方向是Qt Verti