Page 1 of 1

first program

Posted: Wed Jul 22, 2009 12:36 pm
by Dark_Phoenix
I am working on a simple app that has 3 wxTextCtrl's that allows the user to enter an RBG value and display the color. I want to be able to tab between the controls but I have not been able to find any information on this. Can anyone point me in the right direction?

I will post the code I have so if anyone wants to take a look and see if there is anything that I could do different / better please feel free.

Code: Select all

#include <wx/wx.h>

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

class ColorsFrame: public wxFrame
{
    public:
        ColorsFrame(const wxString& title);
        ~ColorsFrame() { }

    private:
        void OnClose(wxCloseEvent& event)   { Destroy(); }
        void OnQuit(wxCommandEvent& event)  { Destroy(); }
        void OnOK(wxCommandEvent& event);
        wxTextCtrl *m_pRedTxtCtrl;
        wxTextCtrl *m_pGreenTxtCtrl;
        wxTextCtrl *m_pBlueTxtCtrl;
        wxPanel    *m_pColorPanel;
        long m_rColor;
        long m_gColor;
        long m_bColor;
        DECLARE_EVENT_TABLE()
};

enum
{
    idMenuQuit  = 1000,
    idRED,
    idGREEN,
    idBLUE
};

BEGIN_EVENT_TABLE(ColorsFrame, wxFrame)
    EVT_CLOSE(ColorsFrame::OnClose)
    EVT_MENU(idMenuQuit, ColorsFrame::OnQuit)
    EVT_BUTTON(wxID_OK, ColorsFrame::OnOK)
END_EVENT_TABLE()

IMPLEMENT_APP(ColorsApp);

bool ColorsApp::OnInit()
{
    ColorsFrame* Frame = new ColorsFrame("Color Selector");
    Frame->Centre();
    Frame->Show();

    return true;
}

ColorsFrame::ColorsFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition), m_rColor(0), m_gColor(0), m_bColor(0)
{
    wxMenuBar* mbar = new wxMenuBar();
    wxMenu* fileMenu = new wxMenu("");
    fileMenu->Append(idMenuQuit, "&Quit", "Quit the application");
    mbar->Append(fileMenu, "&File");
    SetMenuBar(mbar);

    CreateStatusBar(1);
    SetStatusText("Enter RGB values to see the color", 0);

    m_pColorPanel = new wxPanel(this, -1);
    wxBoxSizer *hBox = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer *vBox1 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *vBox2 = new wxBoxSizer(wxVERTICAL);

    wxStaticText *rText = new wxStaticText(this,
                                           -1,
                                           "RED",
                                           wxPoint(5, 5),
                                           wxSize(35, 20) );
    wxStaticText *gText = new wxStaticText(this,
                                           -1,
                                           "GREEN",
                                           wxPoint(5, 5),
                                           wxSize(35, 20) );
    wxStaticText *bText = new wxStaticText(this,
                                           -1,
                                           "BLUE",
                                           wxPoint(5, 5),
                                           wxSize(35, 20) );
    m_pRedTxtCtrl = new wxTextCtrl(this,
                                   idRED,
                                   "0",
                                   wxPoint(5, 5),
                                   wxSize(30, 20),
                                   0,
                                   wxTextValidator(wxFILTER_NUMERIC) );
    m_pGreenTxtCtrl = new wxTextCtrl(this,
                                     idGREEN,
                                     "0",
                                     wxPoint(5, 5),
                                     wxSize(30, 20),
                                     0,
                                     wxTextValidator(wxFILTER_NUMERIC) );
    m_pBlueTxtCtrl = new wxTextCtrl(this,
                                    idBLUE,
                                    "0",
                                    wxPoint(5, 5),
                                    wxSize(30, 20),
                                    0,
                                    wxTextValidator(wxFILTER_NUMERIC) );
    wxButton *okButton = new wxButton(this,
                                      wxID_OK,
                                      "OK",
                                      wxDefaultPosition,
                                      wxSize(30, 30) );

    vBox1->Add(rText, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);
    vBox1->Add(gText, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);
    vBox1->Add(bText, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);

    vBox2->Add(m_pRedTxtCtrl, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);
    vBox2->Add(m_pGreenTxtCtrl, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);
    vBox2->Add(m_pBlueTxtCtrl, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);
    vBox2->Add(okButton, 0, wxTOP | wxBOTTOM | wxLEFT | wxRIGHT, 5);

    hBox->Add(vBox1);
    hBox->Add(vBox2);
    hBox->Add(m_pColorPanel, 1, wxEXPAND, 0);

    SetSizer(hBox);

    m_pColorPanel->SetBackgroundColour(wxColor(0, 0, 0) );
    m_pRedTxtCtrl->SetFocus();
}

void ColorsFrame::OnOK(wxCommandEvent& event)
{
    wxString str;

    str = m_pRedTxtCtrl->GetValue();
    str.ToLong(&m_rColor);

    str = m_pGreenTxtCtrl->GetValue();
    str.ToLong(&m_gColor);

    str = m_pBlueTxtCtrl->GetValue();
    str.ToLong(&m_bColor);

    if (m_rColor < 0 || m_rColor > 255 || m_gColor < 0 || m_gColor > 255 || m_bColor < 0 || m_bColor > 255)
    {
        wxMessageBox("An Incorrect value has been entered\nValue range is 0 - 255");
    }
    else
    {
        m_pColorPanel->SetBackgroundColour(wxColour(m_rColor, m_gColor, m_bColor) );
        Refresh();
    }
}

Posted: Wed Jul 22, 2009 12:53 pm
by spectrum
hello,

i would try to create the controls adding wxTAB_TRAVERSAL style.

regards

Posted: Wed Jul 22, 2009 1:14 pm
by Dark_Phoenix
spectrum wrote:i would try to create the controls adding wxTAB_TRAVERSAL style.
regards
I did try that and it did not work... in fact, after I added that style (I added it to all 3 text controls and the button) I could no longer enter values into the text boxes and clicking the button would not do anything?!?

Posted: Wed Jul 22, 2009 2:19 pm
by DavidHart
Hi,

I suggest you put a wxPanel in your frame as its only child control. Then give the panel a sizer, and do everything else inside this, with controls parented by the panel.

Doing so cures various obscure bugs, including troubles with tab traversal.

Regards,

David

Posted: Wed Jul 22, 2009 6:37 pm
by Dark_Phoenix
OK, Makes sense now.... On a related note, I am doing something different with it now. Instead of typing in an RGB value and displaying the color, I am using a wxColourPickerCtrl to let the user select a color and then display the value as well as change the background color of a panel to reflect that color. Everything works fine except the EVT_COLOURPICKER_CHANGED event does not seem to be processing, as the wxMessageBox inside the handler never comes up. Any ideas?

Code: Select all

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

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

class ColorsFrame: public wxFrame
{
    public:
        ColorsFrame(const wxString& title);
        ~ColorsFrame() { }

    private:
        void OnChangeColour(wxColourPickerEvent &event);
        wxPanel *m_pPanel;
        DECLARE_EVENT_TABLE()
};

const int idChangeColour = 1000;

BEGIN_EVENT_TABLE(ColorsFrame, wxFrame)
    EVT_COLOURPICKER_CHANGED(idChangeColour, OnChangeColour)
END_EVENT_TABLE()

IMPLEMENT_APP(ColorsApp);

bool ColorsApp::OnInit()
{
    ColorsFrame* Frame = new ColorsFrame("Color Selector");
    Frame->Centre();
    Frame->Show();

    return true;
}

ColorsFrame::ColorsFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(1000, 600), wxDEFAULT_FRAME_STYLE)
{
    CreateStatusBar(5);
    SetStatusText("Select a color to see its RGB value", 0);
    SetStatusText("RED =", 2);
    SetStatusText("GREEN =", 3);
    SetStatusText("BLUE =", 4);

    wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL);

    wxColourPickerCtrl *ColourPicker = new wxColourPickerCtrl(this,
                                                              wxID_ANY,
                                                              *wxBLACK,
                                                              wxDefaultPosition,
                                                              wxDefaultSize,
                                                              wxCLRP_USE_TEXTCTRL);
    m_pPanel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(900, 400) );

    vSizer->Add(ColourPicker,0, wxTOP | wxBOTTOM | wxCENTER, 10);
    vSizer->Add(m_pPanel, 0, wxTOP | wxBOTTOM | wxCENTER, 10);
    SetSizer(vSizer);

    m_pPanel->SetBackgroundColour(ColourPicker->GetColour() );
}

void ColorsFrame::OnChangeColour(wxColourPickerEvent &event)
{
    wxColour Colour = event.GetColour();
    m_pPanel->SetBackgroundColour(Colour);
    Refresh();
    wxMessageBox(Colour.GetAsString(wxC2S_CSS_SYNTAX) );
}

Posted: Wed Jul 22, 2009 6:47 pm
by DavidHart
That should be:
EVT_COLOURPICKER_CHANGED(idChangeColour, ColorsFrame::OnChangeColour)

Posted: Wed Jul 22, 2009 6:53 pm
by Dark_Phoenix
DavidHart wrote:That should be:
EVT_COLOURPICKER_CHANGED(idChangeColour, ColorsFrame::OnChangeColour)
Argh! Darn newbie mistakes!

Still, that did not have any effect at all on the problem.... Still doing the same thing.

Posted: Wed Jul 22, 2009 7:40 pm
by Dark_Phoenix
OK, Figured it out. I had an ID mismatch...

Code: Select all

const int idChangeColour = 1000;

Code: Select all

    wxColourPickerCtrl *ColourPicker = new wxColourPickerCtrl(this,
                                                              wxID_ANY, <----!!
                                                              *wxBLACK,

Posted: Wed Jul 22, 2009 8:47 pm
by Dark_Phoenix
so here is my (first) finished app. Code is attached. If anyone cares to review of critic it, see if there are any errors I missed or perhaps a better / more efficient way of doing something, I would appreciate it. Thanks for the help!

Code: Select all

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

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

class CFrame: public wxFrame
{
    public:
        CFrame(const wxString& title);
        ~CFrame() { }

    private:
        void OnChangeColour(wxColourPickerEvent &event);
        void OnOK(wxCommandEvent& event);
        wxPanel            *m_pPanel;
        wxStatusBar        *m_pStatusBar;
        wxColourPickerCtrl *m_pColourPicker;
        wxTextCtrl         *m_pRedTextCtrl;
        wxTextCtrl         *m_pGreenTextCtrl;
        wxTextCtrl         *m_pBlueTextCtrl;
        DECLARE_EVENT_TABLE()
};

enum
{
    idColourPicker = 1000,
    idRedCtrl,
    idGreenCtrl,
    idBlueCtrl
};

BEGIN_EVENT_TABLE(CFrame, wxFrame)
    EVT_COLOURPICKER_CHANGED(idColourPicker, CFrame::OnChangeColour)
    EVT_BUTTON(wxID_OK, CFrame::OnOK)
END_EVENT_TABLE()

IMPLEMENT_APP(CApp);

bool CApp::OnInit()
{
    CFrame* Frame = new CFrame("Color Selector");
    Frame->Centre();
    Frame->Show();

    return true;
}

CFrame::CFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(1000, 600) )
{
    int widths[5] = { 350, -1, -1, -1, 350 };
    m_pStatusBar = new wxStatusBar(this);
    m_pStatusBar->SetFieldsCount(5, widths);
    m_pStatusBar->SetStatusText("", 0);
    m_pStatusBar->SetStatusText("RED = 0", 1);
    m_pStatusBar->SetStatusText("GREEN = 0", 2);
    m_pStatusBar->SetStatusText("BLUE = 0", 3);

    wxPanel *ParentPanel = new wxPanel(this,
                                       wxID_ANY,
                                       wxDefaultPosition,
                                       wxSize(1000, 550) );
    wxBoxSizer *vSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer *hSizer = new wxBoxSizer(wxHORIZONTAL);

    m_pColourPicker = new wxColourPickerCtrl(ParentPanel,
                                            idColourPicker,
                                            *wxBLACK,
                                            wxDefaultPosition,
                                            wxDefaultSize,
                                            wxCLRP_USE_TEXTCTRL);
    m_pPanel = new wxPanel(ParentPanel,
                           wxID_ANY,
                           wxDefaultPosition,
                           wxSize(900, 400) );
    m_pRedTextCtrl = new wxTextCtrl(ParentPanel,
                                    idRedCtrl,
                                    "0",
                                    wxPoint(5, 5),
                                    wxSize(30, 20),
                                    0,
                                    wxTextValidator(wxFILTER_NUMERIC) );
    m_pGreenTextCtrl = new wxTextCtrl(ParentPanel,
                                      idGreenCtrl,
                                      "0",
                                      wxPoint(5, 5),
                                      wxSize(30, 20),
                                      0,
                                      wxTextValidator(wxFILTER_NUMERIC) );
    m_pBlueTextCtrl = new wxTextCtrl(ParentPanel,
                                     idBlueCtrl,
                                     "0",
                                     wxPoint(5, 5),
                                     wxSize(30, 20),
                                     0,
                                     wxTextValidator(wxFILTER_NUMERIC) );
    wxButton *okButton = new wxButton(ParentPanel,
                                      wxID_OK,
                                      "OK",
                                      wxDefaultPosition,
                                      wxSize(30, 30) );

    hSizer->Add(m_pRedTextCtrl, 0, wxALL, 10);
    hSizer->Add(m_pGreenTextCtrl, 0, wxALL, 10);
    hSizer->Add(m_pBlueTextCtrl, 0, wxALL, 10);
    hSizer->Add(okButton, 0, wxALL, 10);
    vSizer->Add(m_pColourPicker, 0, wxTOP | wxBOTTOM | wxALIGN_CENTER, 10);
    vSizer->Add(m_pPanel, 0, wxTOP | wxBOTTOM | wxALIGN_CENTER, 10);
    vSizer->Add(hSizer, 0, wxALIGN_CENTER_HORIZONTAL , 0);
    SetSizer(vSizer);

    m_pPanel->SetBackgroundColour(m_pColourPicker->GetColour() );
}

void CFrame::OnChangeColour(wxColourPickerEvent &event)
{
    wxColour Colour = event.GetColour();
    m_pPanel->SetBackgroundColour(Colour);
    Refresh();
    m_pStatusBar->SetStatusText(wxString::Format("RED = %d", Colour.Red() ), 1);
    m_pStatusBar->SetStatusText(wxString::Format("GREEN = %d", Colour.Green() ), 2);
    m_pStatusBar->SetStatusText(wxString::Format("BLUE = %d", Colour.Blue() ), 3);
}

void CFrame::OnOK(wxCommandEvent& event)
{
    wxString str;
    long rColour = 0, gColour = 0, bColour = 0;
    m_pRedTextCtrl->GetValue().ToLong(&rColour);
    m_pGreenTextCtrl->GetValue().ToLong(&gColour);
    m_pBlueTextCtrl->GetValue().ToLong(&bColour);

    if (rColour < 0 || rColour > 255 || gColour < 0 || gColour > 255 || bColour < 0 || bColour > 255)
    {
        wxMessageBox("An Incorrect value has been entered\nValue range is 0 - 255");
    }
    else
    {
        m_pPanel->SetBackgroundColour(wxColour(rColour, gColour, bColour) );
        m_pColourPicker->SetColour(wxColour(rColour, gColour, bColour) );
        Refresh();
        m_pStatusBar->SetStatusText(wxString::Format("RED = %d", rColour), 1);
        m_pStatusBar->SetStatusText(wxString::Format("GREEN = %d", gColour), 2);
        m_pStatusBar->SetStatusText(wxString::Format("BLUE = %d", bColour), 3);
    }
}

Posted: Thu Jul 23, 2009 1:29 am
by Auria
After a quick look it look good, only noticed this :

Code: Select all


void CFrame::OnOK(wxCommandEvent& event)
{
    wxString str; // <---- this variable is never used
    long rColour = 0, gColour = 0, bColour = 0;
    m_pRedTextCtrl->GetValue().ToLong(&rColour);
    m_pGreenTextCtrl->GetValue().ToLong(&gColour);
    m_pBlueTextCtrl->GetValue().ToLong(&bColour);
Also, in all code conventions I used, constants (like IDs) where written in ALL_CAPS (though that's not an error if you do it otherwise, just a matter of code conventions)

I also noticed you implicitely passed srings literals to wxStrings :

Code: Select all

CFrame* Frame = new CFrame("Color Selector");
This is OK in wxWidgets 2.8 ANSI builds, and wxWidgets 2.9/3.0 (upcoming), but will fail on wxWidgets 2.8 Unicode - so if you expect to need Unicode support before wxWidgets 3.0 (or 2.9 if you're willing to use unstable versions), surround you literals with wxT()

apart from that, good job :)

Posted: Thu Jul 23, 2009 12:13 pm
by Dark_Phoenix
Auria wrote: wxString str; // <---- this variable is never used
Wow, never noticed that!
I also noticed you implicitely passed srings literals to wxStrings
so if you expect to need Unicode support before wxWidgets 3.0 (or 2.9 if you're willing to use unstable versions), surround you literals with wxT()
Never really messed with unicode before, but probably not a bad practice to get into
apart from that, good job :)
Thanks!