wxWidgetsでお絵描きするまでの例

,

インストール

Ubuntu 16.04LTSでは次:

$ sudo apt install libwxgtk3.0-dev

Hello, world!

特に上のサンプルを元に必要最小限まで削ったものは以下:

#include <wx/wx.h>

class MyApp : public wxApp {
public:
    virtual bool OnInit() {
        wxFrame *frame = new wxFrame(NULL, wxID_ANY, "Hello, world!");
        frame->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

コンパイルは次:

$ $CXX mmvis.cpp `wx-config --cxxflags --libs`

絵を書く

EVT_PAINT()を発生させhandlerを呼びその中でwxPaintDCを生成して絵を書く。 それ以外の方法はあまり推奨されていないように見える。

#include <wx/wx.h>

class MyPanel : public wxPanel {
public:
    MyPanel(wxFrame *parent)
            : wxPanel(parent) {
        Bind(wxEVT_PAINT, &MyPanel::myOnPaint, this);
    }

    void myOnPaint(wxPaintEvent & evt) {
        wxPaintDC dc(this);
        wxPen pen(*wxBLACK, /* width = */ 1);
        dc.SetPen(pen);
        dc.DrawText(wxT("Hello, "), 40, 60);
        int dx = 90;
        int dy = 60;
        int scale = 5;
        auto draw_line = [&](int x1, int y1, int x2, int y2) {
            x1 = dx + x1 * scale;
            y1 = dy + y1 * scale;
            x2 = dx + x2 * scale;
            y2 = dy + y2 * scale;
            dc.DrawLine(x1, y1, x2, y2);
        };
        { // se
            draw_line(0, 1, 4, 1);
            draw_line(1, 0, 1, 3);
            draw_line(1, 3, 4, 3);
            draw_line(2, 0, 2, 2);
            draw_line(2, 2, 3, 2);
            draw_line(3, 0, 3, 2);
        }
        { // kai
            dx = 120;
            dy = 60;
            scale = 4;
            for (int z = 0; z < 3; ++ z) {
                draw_line(1, z, 3, z);
                draw_line(z + 1, 0, z + 1, 2);
            }
            draw_line(2, 2, 0, 4);
            draw_line(2, 2, 5, 4);
            draw_line(2, 3, 1, 5);
            draw_line(3, 3, 3, 5);
        }
        dc.SetPen(wxNullPen);
    }
};

class MyApp : public wxApp {
public:
    virtual bool OnInit() {
        wxFrame *frame = new wxFrame(NULL, wxID_ANY, "Hello, world!");
        MyPanel *panel = new MyPanel(frame);
        frame->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

動的に更新する

例えばEVT_TIMERを発生させてデータ列を生成しグラフにしてみる。

画面への反映はRefreshを呼ぶ。Updateは好みで: https://forums.wxwidgets.org/viewtopic.php?t=10114

#include <deque>
#include <wx/wx.h>

class MyPanel : public wxPanel {
public:
    MyPanel(wxFrame *parent)
            : wxPanel(parent),
              timer(this) {
        Bind(wxEVT_PAINT, &MyPanel::myOnPaint, this);
        Bind(wxEVT_TIMER, &MyPanel::myOnTimer, this, timer.GetId());
        timer.Start(10); // msec
    }

    void myOnPaint(wxPaintEvent & evt) {
        wxPaintDC dc(this);
        for (int x = 0; x < int(points.size()) - 1; ++ x) {
            dc.DrawLine(x, points[x], x + 1, points[x + 1]);
        }
    }

    void myOnTimer(wxTimerEvent & event) {
        int value = wxGetMouseState().GetY() - GetScreenPosition().y;
        points.push_back(value);
        if (points.size() > 640) {
            points.pop_front();
        }
        Refresh();
    }

private:
    wxTimer timer;
    std::deque<int> points;
};

class MyApp : public wxApp {
public:
    virtual bool OnInit() {
        wxFrame *frame = new wxFrame(NULL, wxID_ANY, "Hello, world!",
                wxDefaultPosition, wxSize(640, 480));
        MyPanel *panel = new MyPanel(frame);
        frame->Show();
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

その他