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-surface
    KIGFX::GAL*              m_gal;

    /// Stores view settings (scale, center, etc.) and items to be drawn
    KIGFX::VIEW*             m_view;

    /// Contains information about how to draw items using GAL
    std::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-surface
    KIGFX::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); // 设置虚拟大小为800x600
        SetScrollbars(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()方法获取更新区域。然后,我们遍历更新区域,并对每个矩形区域进行绘制操作(在这里是绘制矩形)。您可以根据实际需求,在相应的区域内执行您需要的绘制操作。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在公网环境下使用笔记本的Potplayer访问本地群晖webdav中的影视资源

文章目录 如何在公网环境下使用笔记本的Potplayer访问本地群晖webdav中的影视资源**那么问题来了&#xff0c;potplayer只能局域网内访问资源&#xff0c;那我不在家中怎么看本地电影&#xff1f;** 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果…

目标检测 Faster RCNN全面解读复现

Faster RCNN 解读 经过R-CNN和Fast RCNN的积淀&#xff0c;Ross B. Girshick在2016年提出了新的Faster RCNN&#xff0c;在结构上&#xff0c;Faster RCNN已经将特征抽取(feature extraction)&#xff0c;proposal提取&#xff0c;bounding box regression(rect refine)&…

DGL创建异构图

利用DGL创建具有3种节点类型和3种边类型的异构图 graph_data {# (src_type, edge_type, dst_type)(drug, interacts, drug): (th.tensor([0, 1]), th.tensor([1, 2])),(drug, interacts,, disease): (th.tensor([1]), th.tensor([2])) }g dgl.heterograph(graph_data)上述代…

110.firefly-overlayroot

折腾rk3399的开发板的时候&#xff0c;突然发现overlayroot这个词汇。 我移植一下linux5.10的内核到firefly3399开发板&#xff0c;结果启动之后文件系统提示只读&#xff01;&#xff01;&#xff01; 这就让我很莫名。后来看到mount文件系统的情况&#xff0c;感觉也是不可…

集成多元算法,打造高效字面文本相似度计算与匹配搜索解决方案,助力文本匹配冷启动[BM25、词向量、SimHash、Tfidf、SequenceMatcher]

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

图解算法数据结构-LeetBook-栈和队列03_验证栈的取出顺序

现在图书馆有一堆图书需要放入书架&#xff0c;并且图书馆的书架是一种特殊的数据结构&#xff0c;只能按照 一定 的顺序 放入 和 拿取 书籍。 给定一个表示图书放入顺序的整数序列 putIn&#xff0c;请判断序列 takeOut 是否为按照正确的顺序拿取书籍的操作序列。你可以假设放…

万宾科技智能井盖传感器,预防城市道路安全

随着城市交通的不断发展和城市化进程的加速推进&#xff0c;城市道路安全问题日益凸显。市政井盖作为城市道路的一部分&#xff0c;承担着重要的交通安全保障职责。然而传统的市政井盖管理方式存在许多不足。针对这些问题政府需要采取适当的措施&#xff0c;补足传统管理方式的…

bitmap实践-留存计算

目录 1. 介绍2. 留存问题3. 思路解析4. 逻辑4.1 b表建设4.2 留存计算4.3 近X天的访问天数 5.分析 1. 介绍 bitmap方法是数据压缩使用的常用算法&#xff0c;当字段有明确上下界的时候&#xff0c;使用位图模式来减少存储。在业务指标体系中特别适合通用型留存指标的计算。 2.…

RAID技术复习笔记

Raid&#xff08;Redundant Array of independent Disks&#xff09;独立磁盘冗余阵列&#xff1a;磁盘阵列 Raid 分为:软raid、硬raid、软硬混合三种。 软Raid&#xff1a;所有的功能均有操作系统和CPU来完成&#xff0c;没有独立的raid控制、处理芯片和IO处理处理芯片。 硬R…

如何从零开始制作一本企业宣传画册?

最近公司领导要求为公司制作一本企业宣传画册&#xff0c;用来展示我们的产品和服务&#xff0c;增加品牌影响力。可是&#xff0c;像我这种零基础的小白&#xff0c;完全不知道如何制作啊&#xff1f;对此我感到很焦虑&#xff0c;怕做不好影响公司形象&#xff0c;也怕耽误时…

LR学习笔记——初识lightroom

文章目录 介绍图库界面修改照片界面 介绍 Lightroom是Adobe公司开发的一款用于图片后期处理制作的软件&#xff0c;被称为Adobe Photoshop Lightroom。其增强的校正工具、强大的组织功能以及灵活的打印选项可以帮助加快图片后期处理速度&#xff0c;将更多的时间投入拍摄。 相…

Navicat DML 操作

在表格种插入 列信息 -- 修改数据 update 表名 set 列名 值1, 列名值2,[where 条件]; -- 注意&#xff1a;如果update语句没有加where 表里对应行的全部信息都会被改; -- 删除数据 delecte from 表名 [where 条件]; 未删除前&#xff1a; 执行删除后为&#xff1a; DQL - 条…

打印工具HandyPrint Pro Mac中文版软件特点

HandyPrint Pro Mac是一款打印工具&#xff0c;它支持AIrPrint协议&#xff0c;可以让用户在iPhone、iPad、iPod等设备上进行打印操作&#xff0c;只需要将这些设备连接到Mac电脑的WiFi网络中即可实现打印功能。 ​ HandyPrint Pro Mac软件特点 简单易用&#xff1a;用户只需…

不标年份的葡萄酒质量好吗?

我们在葡萄酒标上经常看到生产年份&#xff0c;也就是指全部葡萄采摘的年份。旧世界葡萄酒产国认为葡萄酒年份对他们的影响较大&#xff0c;而新世界葡萄酒&#xff0c;年份的意义就稍微小些。甚至有一部分葡萄酒酒标上没有年份。在酒标上没有标注年份的葡萄酒&#xff0c;被称…

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

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

Druid介绍

Druid介绍 Druid首先是一个数据库连接池&#xff0c;并且是目前最好的数据库连接池&#xff0c;在功能、性能、扩展性方面&#xff0c;都超过其他数据库连接池&#xff0c;包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。但它不仅仅是一个数据库连接池&#xff0c;它还包…

使用frp搭建内网穿透服务

使用frp搭建内网穿透服务 frp 是一个专注于内网穿透的高性能的反向代理应用&#xff0c;支持 TCP、UDP、HTTP、HTTPS 等多种协议&#xff0c;且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。 1.下载frp 下载地址 2.服务端安装 …

工作电压范围,转换速率高,相位补偿等特性的双运算放大器芯片D4510的描述

D4510是一块双运算放大器&#xff0c;具有较宽的工作电压范围&#xff0c;转换速率高&#xff0c;相位补偿等特性。电路能在低电源电压下:工作,电源电压范围:双电源为1V-3.5V和单电源电压为2V~7V。 主要特点&#xff1a; ● 低电压工作 ● 转换速率高 ● 动态输…

深度学习领域中的耦合与解耦

在阅读论文的时候应该会看到两个操作&#xff0c;一个是耦合&#xff0c;一个是解耦&#xff0c;经常搭配着出现的就是两个词语&#xff0c;耦合头&#xff08;Coupled head&#xff09;以及Decoupled head&#xff08;解耦合头&#xff09;&#xff0c;那为什么要耦合&#xf…

冬天起不来床怎么办?羊大师给你好建议

冬天起不来床怎么办&#xff1f;羊大师给你好建议 冬季是让人感到懒散的季节&#xff0c;尤其是早上起床。寒冷的天气和温暖的被窝让人们很难离开床铺。如果你也常常遇到这个问题&#xff0c;不要担心&#xff0c;本文小编羊大师将为你分析起床困难的原因&#xff0c;并提供一…