第11章 GUI Page406~411 步骤四 显示多条直线

运行效果:

一  源代码:

//item_line.hpp
#ifndef ITEM_LINE_HPP_INCLUDED
#define ITEM_LINE_HPP_INCLUDED

#include <wx/gdicmn.h>
#include <wx/dc.h>

class LineItem
{
public:
    LineItem()
        : _startPosition(0, 0), _endPosition(0, 0)
    {

    }

    void SetStartPosition(wxPoint const& point);
    void SetEndPosition(wxPoint const& point);

    wxPoint const& GetStartPosition() const
    {
        return _startPosition;
    }

    wxPoint const& GetEndPosition() const
    {
        return _endPosition;
    }

private:
    //不写Logic后缀,但仍然是存储逻辑坐标
    wxPoint _startPosition, _endPosition;
};

#endif // ITEM_LINE_HPP_INCLUDED

//item_line.cpp
#include "item_line.hpp"

void LineItem::SetStartPosition(wxPoint const& point)
{
    this->_startPosition = point;
}

void LineItem::SetEndPosition(wxPoint const& point)
{
    this->_endPosition = point;
}

/***************************************************************
 * Name:      wxMyPainterMain.h
 * Purpose:   Defines Application Frame
 * Author:    yanzhenxi (3065598272@qq.com)
 * Created:   2023-12-21
 * Copyright: yanzhenxi ()
 * License:
 **************************************************************/

#ifndef WXMYPAINTERMAIN_H
#define WXMYPAINTERMAIN_H
#include <list>
#include "item_line.hpp"

//(*Headers(wxMyPainterFrame)
#include <wx/scrolwin.h>
#include <wx/sizer.h>
#include <wx/menu.h>
#include <wx/listbox.h>
#include <wx/frame.h>
#include <wx/statusbr.h>
//*)

class wxMyPainterFrame: public wxFrame
{
    public:

        wxMyPainterFrame(wxWindow* parent,wxWindowID id = -1);
        virtual ~wxMyPainterFrame();

    private:

        //(*Handlers(wxMyPainterFrame)
        void OnQuit(wxCommandEvent& event);
        void OnAbout(wxCommandEvent& event);
        void OnScrolledWindow1LeftDown(wxMouseEvent& event);
        void OnScrolledWindow1MouseMove(wxMouseEvent& event);
        void OnScrolledWindow1LeftUp(wxMouseEvent& event);
        void OnScrolledWindow1Paint(wxPaintEvent& event);
        //*)

        //(*Identifiers(wxMyPainterFrame)
        static const long ID_LISTBOX1;
        static const long ID_SCROLLEDWINDOW1;
        static const long idMenuQuit;
        static const long idMenuAbout;
        static const long ID_STATUSBAR1;
        //*)

        //(*Declarations(wxMyPainterFrame)
        wxScrolledWindow* ScrolledWindow1;
        wxStatusBar* StatusBar1;
        wxListBox* ListBox1;
        //*)

    private:
        void RemoveAllItems();
        /*每当用户鼠标按下,就创建一个新的_newItem,等画完之后(鼠标抬起),
        就将它加入“_items”列表中。这也解释了为什么不需要“_drawing”这个标志,
        因为当“_newItem”不为空,就说明用户正在画新的线。OnPaint事件的思路配套调整
        为:每次都画出“_items”中的所有元素;然后如果“_newItem”不为空,则把用户正在
        拖拽的线也画出来。*/
        LineItem* _newItem;
        std::list <LineItem*> _items;

        DECLARE_EVENT_TABLE()
};

#endif // WXMYPAINTERMAIN_H

/***************************************************************
 * Name:      wxMyPainterMain.cpp
 * Purpose:   Code for Application Frame
 * Author:    yanzhenxi (3065598272@qq.com)
 * Created:   2023-12-21
 * Copyright: yanzhenxi ()
 * License:
 **************************************************************/

#include "wxMyPainterMain.h"
#include <wx/msgdlg.h>
#include <wx/dcclient.h>

//(*InternalHeaders(wxMyPainterFrame)
#include <wx/settings.h>
#include <wx/intl.h>
#include <wx/string.h>
//*)

//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

//(*IdInit(wxMyPainterFrame)
const long wxMyPainterFrame::ID_LISTBOX1 = wxNewId();
const long wxMyPainterFrame::ID_SCROLLEDWINDOW1 = wxNewId();
const long wxMyPainterFrame::idMenuQuit = wxNewId();
const long wxMyPainterFrame::idMenuAbout = wxNewId();
const long wxMyPainterFrame::ID_STATUSBAR1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(wxMyPainterFrame,wxFrame)
    //(*EventTable(wxMyPainterFrame)
    //*)
END_EVENT_TABLE()

wxMyPainterFrame::wxMyPainterFrame(wxWindow* parent,wxWindowID id)
    : _newItem(nullptr)
{
    //(*Initialize(wxMyPainterFrame)
    wxMenuItem* MenuItem2;
    wxMenuItem* MenuItem1;
    wxMenu* Menu1;
    wxBoxSizer* BoxSizer1;
    wxMenuBar* MenuBar1;
    wxMenu* Menu2;

    Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
    SetClientSize(wxSize(208,94));
    BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
    ListBox1 = new wxListBox(this, ID_LISTBOX1, wxDefaultPosition, wxSize(168,68), 0, 0, 0, wxDefaultValidator, _T("ID_LISTBOX1"));
    BoxSizer1->Add(ListBox1, 0, wxALL|wxEXPAND, 5);
    ScrolledWindow1 = new wxScrolledWindow(this, ID_SCROLLEDWINDOW1, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL, _T("ID_SCROLLEDWINDOW1"));
    ScrolledWindow1->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
    BoxSizer1->Add(ScrolledWindow1, 1, wxALL|wxEXPAND, 5);
    SetSizer(BoxSizer1);
    MenuBar1 = new wxMenuBar();
    Menu1 = new wxMenu();
    MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
    Menu1->Append(MenuItem1);
    MenuBar1->Append(Menu1, _("&File"));
    Menu2 = new wxMenu();
    MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
    Menu2->Append(MenuItem2);
    MenuBar1->Append(Menu2, _("Help"));
    SetMenuBar(MenuBar1);
    StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
    int __wxStatusBarWidths_1[1] = { -1 };
    int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
    StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
    StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
    SetStatusBar(StatusBar1);
    SetSizer(BoxSizer1);
    Layout();

    ScrolledWindow1->Connect(wxEVT_PAINT,(wxObjectEventFunction)&wxMyPainterFrame::OnScrolledWindow1Paint,0,this);
    ScrolledWindow1->Connect(wxEVT_LEFT_DOWN,(wxObjectEventFunction)&wxMyPainterFrame::OnScrolledWindow1LeftDown,0,this);
    ScrolledWindow1->Connect(wxEVT_LEFT_UP,(wxObjectEventFunction)&wxMyPainterFrame::OnScrolledWindow1LeftUp,0,this);
    ScrolledWindow1->Connect(wxEVT_MOTION,(wxObjectEventFunction)&wxMyPainterFrame::OnScrolledWindow1MouseMove,0,this);
    Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxMyPainterFrame::OnQuit);
    Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxMyPainterFrame::OnAbout);
    //*)

    //设置滚动选项
    ScrolledWindow1->SetScrollRate(10, 10);
    ScrolledWindow1->SetVirtualSize(500, 480);
}

wxMyPainterFrame::~wxMyPainterFrame()
{
    RemoveAllItems();
    //(*Destroy(wxMyPainterFrame)
    //*)
}

void wxMyPainterFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}

void wxMyPainterFrame::OnAbout(wxCommandEvent& event)
{
    wxString msg = wxbuildinfo(long_f);
    wxMessageBox(msg, _("Welcome to..."));
}

void wxMyPainterFrame::RemoveAllItems()
{
    for(std::list<LineItem*>::iterator it = _items.begin()
                        ; it != _items.end(); ++it)
    {
        delete *it; //释放每个_newItem占据的内存
    }

    _items.clear(); //释放_items中元素(指向_newItem的指针)占据的内存
}

void wxMyPainterFrame::OnScrolledWindow1LeftDown(wxMouseEvent& event)
{
    if(_newItem)//逻辑别搞反
    {
        return; //正在划线,返回
    }

    _newItem = new LineItem();
    _newItem->SetStartPosition(
                    ScrolledWindow1->CalcUnscrolledPosition(event.GetPosition()));
}

void wxMyPainterFrame::OnScrolledWindow1MouseMove(wxMouseEvent& event)
{
    if(!_newItem) //不在绘画状态
    {
        return;//直接退出
    }

    _newItem->SetEndPosition(//物理坐标转为逻辑坐标
                    ScrolledWindow1->CalcUnscrolledPosition(event.GetPosition()));
    ScrolledWindow1->Refresh();
}

void wxMyPainterFrame::OnScrolledWindow1LeftUp(wxMouseEvent& event)
{
    if(!_newItem) //不在绘画状态?
    {
        return;//直接退出
    }

    _newItem->SetEndPosition(//物理坐标转为逻辑坐标
                    ScrolledWindow1->CalcUnscrolledPosition(event.GetPosition()));
    _items.push_back(_newItem); //记录到列表中
    _newItem = nullptr; //结束绘画状态

    ScrolledWindow1->Refresh();
}
//将_items中的所有线都画出来
void wxMyPainterFrame::OnScrolledWindow1Paint(wxPaintEvent& event)
{
    wxPaintDC dc(ScrolledWindow1);

    //先画出list中的每一条线
    for(std::list <LineItem*> :: const_iterator it = _items.begin()
                ; it != _items.end(); ++it)
    {
        LineItem const* item = *it;
                                //逻辑坐标转为物理坐标
        wxPoint startPostion = ScrolledWindow1->CalcScrolledPosition(
                                                 item->GetStartPosition());
        wxPoint endPosition = ScrolledWindow1->CalcScrolledPosition(
                                                item->GetEndPosition());

        dc.DrawLine(startPostion, endPosition);
    }

    //如果刚巧用户正在画新线,把它也显示出来
    //否则用户只能“盲画”了
    if(_newItem)
    {
        wxPoint startPosition = ScrolledWindow1->CalcScrolledPosition(
                                    _newItem->GetStartPosition());
        wxPoint endPosition = ScrolledWindow1->CalcScrolledPosition(
                                    _newItem->GetEndPosition());
        dc.DrawLine(startPosition, endPosition);
    }
}

/***************************************************************
 * Name:      wxMyPainterApp.h
 * Purpose:   Defines Application Class
 * Author:    yanzhenxi (3065598272@qq.com)
 * Created:   2023-12-21
 * Copyright: yanzhenxi ()
 * License:
 **************************************************************/

#ifndef WXMYPAINTERAPP_H
#define WXMYPAINTERAPP_H

#include <wx/app.h>

class wxMyPainterApp : public wxApp
{
    public:
        virtual bool OnInit();
};

#endif // WXMYPAINTERAPP_H

/***************************************************************
 * Name:      wxMyPainterApp.cpp
 * Purpose:   Code for Application Class
 * Author:    yanzhenxi (3065598272@qq.com)
 * Created:   2023-12-21
 * Copyright: yanzhenxi ()
 * License:
 **************************************************************/

#include "wxMyPainterApp.h"

//(*AppHeaders
#include "wxMyPainterMain.h"
#include <wx/image.h>
//*)

IMPLEMENT_APP(wxMyPainterApp);

bool wxMyPainterApp::OnInit()
{
    //(*AppInitialize
    bool wxsOK = true;
    wxInitAllImageHandlers();
    if ( wxsOK )
    {
    	wxMyPainterFrame* Frame = new wxMyPainterFrame(0);
    	Frame->Show();
    	SetTopWindow(Frame);
    }
    //*)
    return wxsOK;

}

二 关键代码:

添加item_line.hpp

添加item_line.cpp

添加一个私有成员函数和两个私有成员

wxMyPainterMain.h头文件,wxMyPaiterFram类中添加成员函数和成员变量

        void RemoveAllItems

        LineItem* _newItem;
        std::list <LineItem*> _items;

原来的_startPositionLogical, _currentPositionLogical,以及 _drawing成员,全都不需要了,改成

并初始化为:

实现清理图元的函数,并由析构函数调用。

实现鼠标左键按下,鼠标移动,左键抬起的函数

实现画线函数

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值