KiCad源代码研究:KiCad是如何渲染和绘图的。

common.json文件中appearance.show_scrollbars
common.json对应于代码的common_settings

1.EDA_DRAW_PANEL_GAL类

EDA_DRAW_PANEL_GAL类中定义了绘图的基本要素:

/// Interface for drawing objects on a 2D-surfaceKIGFX::GAL*              m_gal;/// Stores view settings (scale, center, etc.) and items to be drawnKIGFX::VIEW*             m_view;/// Contains information about how to draw items using GALstd::unique_ptr<KIGFX::PAINTER> m_painter;

1.1类图

EDA_DRAW_PANEL_GAL类包含多个子类,其中SCH_DRAW_PANEL是他的子类之一。
在这里插入图片描述

@startuml
class EDA_DRAW_PANEL_GAL {KIGFX::GAL*              m_gal;}
wxScrolledCanvas <|-- EDA_DRAW_PANEL_GAL 
EDA_DRAW_PANEL_GAL *-- GAL
EDA_DRAW_PANEL_GAL <|- SCH_PREVIEW_PANEL
class SCH_DRAW_PANEL{
KIGFX::SCH_VIEW* m_view
KIGFX::WX_VIEW_CONTROLS m_viewControls
}
EDA_DRAW_PANEL_GAL <|-- SCH_DRAW_PANEL
SCH_DRAW_PANEL *-- WX_VIEW_CONTROLS 
SCH_DRAW_PANEL *-- SCH_VIEW
WX_VIEW_CONTROLS *-- SCH_DRAW_PANEL 
WX_VIEW_CONTROLS *-- SCH_VIEW
SCH_VIEW *-- GAL
@enduml

调用SCH_DRAW_PANEL类的地方:

SCH_DRAW_PANEL* SCH_BASE_FRAME::GetCanvas() const
{return static_cast<SCH_DRAW_PANEL*>( EDA_DRAW_FRAME::GetCanvas() );
}

SCH_DRAW_PANEL类就是sch_edit_frame位于中央部分的画布,如下图所示,画红框的区域就是SCH_DRAW_PANEL:
在这里插入图片描述
从图中我们可以发现一个问题,如果器件长度过长,超出画布的部分没有办法编辑?正常逻辑出发,我们的发布应当有一个滚动条才对。。
滚动时wxScrolledWindow中的图像损坏

1.2 m_gal

   /// Interface for drawing objects on a 2D-surfaceKIGFX::GAL*              m_gal;

关于GAL类的定义:


namespace KIGFX
{
/*** Abstract interface for drawing on a 2D-surface.** The functions are optimized for drawing shapes of an EDA-program such as BTD-ABS. Most methods* are abstract and need to be implemented by a lower layer, for example by a Cairo or OpenGL* implementation.  Almost all methods use world coordinates as arguments. The board design is* defined in world space units for drawing purposes these are transformed to screen units with* this layer. So zooming is handled here as well.**/
class GAL : GAL_DISPLAY_OPTIONS_OBSERVER

何时创建m_gal?SwitchBackend中可以创建函数:

bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )

2.wxScrolledCanvas类

wxScrolledCanvas类是一个wxWidgets C++库中的类,它提供了一个可滚动的绘图区域,可以在其中绘制图形和文本。它继承了wxScrolledWindow类和wxCanvas类的特性,可以自动处理滚动条和滚动事件,使得用户可以通过滚动条来浏览绘图区域的内容。

2.1wxScrolledCanvas滚动条

可能是因为您的wxScrolledCanvas子类没有设置滚动条的大小和位置。

  • 请确保您已经正确设置了wxScrolledCanvas的虚拟大小(即可滚动的区域大小),并且将这些值传递给wxScrolledCanvas类的SetVirtualSize()方法。
  • 请确保您已经正确设置了wxScrolledCanvas的实际大小(即显示在屏幕上的大小),并且将这些值传递给SetSize方法。

另外,请确保您已经启用了滚动条,可以通过调用wxScrolledCanvas类的SetScrollbars方法来实现。如果问题仍然存在,请检查您的代码是否有其他问题,例如滚动条的位置设置不正确等。
以下是一个简单的wxScrolledCanvas子类的示例代码,它使用了SetScrollbars方法来设置滚动条:

#include <wx/wx.h>
#include <wx/scrolwin.h>class MyScrolledCanvas : public wxScrolledCanvas
{
public:MyScrolledCanvas(wxWindow* parent) : wxScrolledCanvas(parent){SetVirtualSize(800, 600); // 设置虚拟大小为800x600SetScrollbars(10, 10, 80, 60); // 启用滚动条,每次滚动10个像素,总共有80个像素,滚动区域大小为60个像素}void OnPaint(wxPaintEvent& event){wxPaintDC dc(this);dc.SetPen(wxPen(wxColor(255, 0, 0), 2));dc.DrawLine(0, 0, 800, 600);}wxDECLARE_EVENT_TABLE();
};wxBEGIN_EVENT_TABLE(MyScrolledCanvas, wxScrolledCanvas)EVT_PAINT(MyScrolledCanvas::OnPaint)
wxEND_EVENT_TABLE()class MyFrame : public wxFrame
{
public:MyFrame() : wxFrame(nullptr, wxID_ANY, "My Frame"){auto* canvas = new MyScrolledCanvas(this);auto* vbox = new wxBoxSizer(wxVERTICAL);vbox->Add(canvas, 1, wxEXPAND);SetSizer(vbox);}
};class MyApp : public wxApp
{
public:bool OnInit() override{auto* frame = new MyFrame();frame->Show();return true;}
};wxIMPLEMENT_APP(MyApp);

在上面的示例代码中,我们创建了一个名为MyScrolledCanvas的wxScrolledCanvas子类,并在其构造函数中设置了虚拟大小和滚动条。在OnPaint方法中,我们绘制了一条红色的对角线,以便在滚动时可以看到滚动的效果。最后,在MyFrame类中,我们将MyScrolledCanvas添加到了一个wxBoxSizer中,并将其设置为窗口的唯一子控件。

请注意,这只是一个简单的示例代码,您可以根据自己的需求进行修改和扩展。

SetScrollbars(10, 10, 80, 60);参数大小为什么要这么设置,有什么根据吗?还有调用SetScrollbars之前必须调用SetVirtualSize吗?

关于SetScrollbars方法的参数设置,第一个参数是滚动条每次滚动的单位大小,第二个参数是滚动条的初始位置,第三个参数是滚动条的总长度,第四个参数是可见区域的大小。这些参数的设置应该根据您的实际需求来决定,例如可见区域的大小应该根据窗口大小来设置,而滚动条的单位大小和总长度则应根据您的绘图内容来设置。

对于调用SetVirtualSize方法,它是必须在调用SetScrollbars方法之前完成的。
在默认状态下,要显示滚动条,窗口的虚拟大小必须大于窗口的实际大小。

scr->SetVirtualSize(wxSize(2000,2000));

然而,在3.1版本中,这还不足以让滚动条出现。用户还必须设置滚动速率。(对我来说,这感觉像是一个bug,因为似乎应该有一个有效的默认设置。)

scr->SetScrollRate(1, 1);

3.wxScrolledCanvas滚动条Sample

一个wxScrolledCanvas实现滚动条的sample,来自网络
这是一个最小的框架样本,它有一个分割器,左边有位图,右边有一个面板。

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"#ifdef __BORLANDC__#pragma hdrstop
#endif// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP#include "wx/wx.h"
#endif#include <wx/scrolwin.h>
#include <wx/splitter.h>
#include <wx/dcbuffer.h>class MyFrame : public wxFrame
{public:MyFrame( wxWindow* parent, int id = wxID_ANY, wxString title = "Demo",wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize,int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );private:void OnScrollPaint( wxPaintEvent& event );wxScrolledCanvas* m_canvas;wxBitmap m_bitmap;
};MyFrame::MyFrame( wxWindow* parent, int id, wxString title, wxPoint pos,wxSize size, int style ):wxFrame( parent, id, title, pos, size, style )
{m_bitmap=wxBitmap ("test.png", wxBITMAP_TYPE_PNG   );wxSplitterWindow* m_splitter1= new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition,wxDefaultSize, wxSP_LIVE_UPDATE );m_canvas = new wxScrolledCanvas( m_splitter1, wxID_ANY, wxDefaultPosition,wxDefaultSize, wxSTATIC_BORDER|wxHSCROLL|wxVSCROLL );m_canvas->SetScrollRate( 5, 5 );m_canvas->SetVirtualSize(m_bitmap.GetWidth(), m_bitmap.GetHeight());m_canvas->SetBackgroundStyle(wxBG_STYLE_PAINT);m_canvas->Bind( wxEVT_PAINT, &MyFrame::OnScrollPaint , this );wxPanel* m_panel2 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition,wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL );m_splitter1->SplitVertically( m_canvas, m_panel2, GetSize().x/2 );
}void MyFrame::OnScrollPaint( wxPaintEvent& event )
{wxAutoBufferedPaintDC dc(m_canvas);m_canvas->DoPrepareDC(dc);dc.Clear();dc.DrawBitmap(m_bitmap,0,0);
}class MyApp : public wxApp
{public:virtual bool OnInit(){wxInitAllImageHandlers();MyFrame* frame = new MyFrame(NULL);frame->Show();return true;}
};wxIMPLEMENT_APP(MyApp);

要运行此操作,请确保将第35行中的"test.png“更改为计算机上实际图像文件的名称(如果图像文件不是png,则更改wxBITMAP_TYPE_PNG )。

重要的部分是:

将画布的背景样式设置为wxBG_STYLE_PAINT,如第46行所示。
在油漆处理程序中,调用油漆the上的DoPrepareDC方法。
顺便说一下,我的样本中显示的油漆处理程序不是很好。它每次都会绘制整个位图。一种更好的方法是获取更新区域,只重新绘制所需的部分,但我想保持这个简单。

3.1实现局部更新:

上文中说,一种更好的方法是获取更新区域,只重新绘制所需的部分应该怎样实现

要实现只重新绘制所需的部分,可以通过以下步骤来获取更新区域并进行相应的绘制:

  • 在窗口的绘图事件处理程序(如OnPaint)中,使用wxPaintDC或wxClientDC对象获取设备上下文(DC)。

  • 调用DC的**GetUpdateRegion()**方法,该方法将返回一个表示需要更新的区域的wxRegion对象。

  • 遍历更新区域,对于每个矩形区域,进行相应的绘制操作。可以使用DC的绘图函数(如DrawRectangle、DrawLine等)或自定义的绘图函数来实现。

这种方法可以减少不必要的绘制操作,只对需要更新的区域进行绘制,从而提高绘图效率。

以下是一个简单的示例代码,演示了如何获取更新区域并进行相应的绘制:

c
Copy
void MyCanvas::OnPaint(wxPaintEvent& event)
{wxPaintDC dc(this);wxRegionIterator updIterator(dc.GetUpdateRegion());while (updIterator){wxRect rect = updIterator.GetRect();// 在需要更新的区域进行相应的绘制操作dc.DrawRectangle(rect);++updIterator;}
}

在上述示例代码中,我们使用wxPaintDC对象获取设备上下文,并通过dc.GetUpdateRegion()方法获取更新区域。然后,我们遍历更新区域,并对每个矩形区域进行绘制操作(在这里是绘制矩形)。您可以根据实际需求,在相应的区域内执行您需要的绘制操作。

通过这种方式,您可以只重新绘制需要更新的部分,从而提高绘图效率,并减少不必要的绘制操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/150636.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主播三维能力总览

主播需要的三维能力包括话术能力、成交能力和表现力 主播的话术能力 主播在直播过程中运用语言和表达方式的能力。好的话术能力可以帮助主播吸引观众、增加互动、提高直播效果等。 1.了解观众需求:在直播前&#xff0c;主播应该了解观众的需求和兴趣&#xff0c;以便在直播过…

小程序商城免费搭建之java商城 电子商务Spring Cloud+Spring Boot+二次开发+mybatis+MQ+VR全景+b2b2c

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

98.qt qml-使用曲线图综合示例、支持多种鼠标交互、支持百万数据显示(已适配黑白风格)

在上章我们只是简单实现了曲线图和折线图的显示: 79.qt qml-如何在QML中使用QCustomPlot之曲线/折线示例(已适配黑白风格)_qml 折线图_诺谦的博客-CSDN博客 所以本章实现综合示例、并添加多种功能如下所示: 详细显示:鼠标任意移动显示具体值内容鼠标右击: 弹出菜单栏,支持…

记一次解决Pyqt6/Pyside6添加QTreeView或QTreeWidget导致窗口卡死(未响应)的新路历程,打死我都想不到是这个原因

文章目录 💢 问题 💢🏡 环境 🏡📄 代码💯 解决方案 💯⚓️ 相关链接 ⚓️💢 问题 💢 我在窗口中添加了一个 QTreeWidget控件 ,但是程序在运行期间,只要鼠标进入到 QTreeWidget控件 内进行操作,时间超过几秒中就会出现窗口 未响应卡死的 状态 🏡 环境 �…

智慧校园烟火识别及预警解决方案,保障校园消防安全

一、方案背景 校园消防安全一直以来是社会各界备受关注的问题。为了保障师生的人身安全和财产安全&#xff0c;越来越多的学校开始引入AI智能检测技术&#xff0c;通过运用AI智能烟火检测技术&#xff0c;对学校的周界、教室、走廊、公共区域、教学楼、食堂等场所进行安全监测…

世微 电动车摩托车灯 5-80V 1.2A 一切二降压恒流驱动器AP2915

产品描述 AP2915 是一款可以一路灯串切换两路灯串的降压恒流驱动器,高效率、外围简单、内置功率管&#xff0c;适用于5-80V 输入的高精度降压 LED 恒流驱动芯片。内置功率管输出最大功率可达 12W&#xff0c;最大电流 1.2A。AP2915 一路灯亮切换两路灯亮&#xff0c;其中一路灯…

Leetcode 153. 寻找旋转排序数组中的最小值

class Solution {//因为最小值和最大值总是相邻的&#xff08;除了初始状态&#xff09;//1.用二分查找&#xff0c;如果右侧是有序则最小值在左侧//2.如果右侧无序则最小值在右侧//如果mid正好是最小值&#xff0c;那么右侧自然是有序的&#xff0c;//为了将mid加入到搜索的一…

windows上安装MySQL Server.

进入官网 MySQL 找到 下载&#xff0c;并点进入。 往下翻&#xff0c;找到社区下载&#xff0c;进入页面 选择 Mysql community Server 选择系统&#xff0c;下载 之后解压。 将解压文件夹下的bin路径添加到变量值中 配置初始化的my.ini文件 [mysqld] # 设置3306端口 port330…

Docker(镜像、容器、仓库)工具安装使用命令行选项及构建、共享和运行容器化应用程序

文章目录 前言&#x1f31f;一、Docker工具安装&#x1f31f;二、Docker命令行选项&#x1f30f;2.1.docker run命令选项&#xff1a;&#x1f30f;2.2.docker build命令选项&#xff1a;&#x1f30f;2.3.docker images命令选项&#xff1a;&#x1f30f;2.4.docker ps命令选项…

【日常总结】java JSON 转 实体类 (含多层嵌套)

一、场景 二、问题 三、解决方案 四、实战 1. 引入maven依赖 2. IEDA 安装lombok 插件 3. 安装 GsonFormPlu 插件 4. 使用 Stage 1&#xff1a;新建类&#xff0c;右键 选择 Generate Stage 2&#xff1a;选择 GsonFormatPlus Stage 3&#xff1a;将json复制其中&…

【Flink 问题集】The generic type parameters of ‘Collector‘ are missing

错误展示&#xff1a; Exception in thread "main" org.apache.flink.api.common.functions.InvalidTypesException: The return type of function main(CollectionDemo.java:33) could not be determined automatically, due to type erasure. You can give type in…

研究前沿| Nature:艰难梭菌引发肠道神经源性炎症的新机制

前言 艰难梭菌感染&#xff08;Clostridioides difficile infection&#xff09;是目前发达国家医院和社区内获得性肠道细菌感染腹泻的最主要原因之一。在美国&#xff0c;每年有约50万例病例和导致约29,000例死亡。艰难梭菌&#xff08;C. difficile&#xff09;是一种产生孢子…

sftp 从windows10向linux(centos7)传输文件

前言背景&#xff1a;该示例是需要从windows10向本地linux系统传输一个qt安装文件&#xff0c;不想或者无法安装xftp这些传输工具&#xff0c;直接通过命令传输&#xff1b; 首先保证windows10 ping通linux系统ip&#xff0c;linux ping 通windows10系统&#xff1b; 注意&am…

Linux:动静态库

目录 一、软硬链接 1、软链接 2、硬链接 二、动态库和静态库 编写一个库 ①静态库 使用静态库的方法 ②动态库 使用动态库的方法 库存在的意义 一、软硬链接 软硬链接的本质区别就是&#xff1a;有无独立的inode 软链接有独立的inode&#xff0c;也就意味着软链接是一…

Java(三)(static,代码块,单例设计模式,继承)

目录 static 有无static修饰的成员变量 有无static修饰的成员方法 static的注意事项 代码块 静态代码块 实例代码块 单例设计模式 饿汉式单例写法 懒汉式单例写法 继承 基本概念 注意事项 权限修饰符 单继承 object 方法重写 子类方法中访问其他成员(成员变量…

虹科分享 | PEAK版本升级,看看有没有你关注的新功能?

号外号外&#xff01;近期PEAK进行了重要的版本升级&#xff0c;这次升级带来了许多令人兴奋的功能优化&#xff0c;助力您的工作流程更加便捷高效。为了帮助您更好地了解PEAK新版本&#xff0c;我们提供了详细的说明和指导&#xff0c;快来看看有没有你关注的新功能&#xff1…

【2023春李宏毅机器学习】快速了解机器学习基本原理

文章目录 机器学习约等于机器自动找一个函数 机器学习分类 regression&#xff1a;输出为连续值classification&#xff1a;输出为一个类别structured learning&#xff1a;又叫生成式学习generative learning 生成有结构的物件&#xff08;如&#xff1a;影像、句子&#xf…

【每日一题】53. 最大子数组和-2023.11.20

题目&#xff1a; 53. 最大子数组和 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2…