Search code examples
c++macoscocoawxwidgetsrgba

wxWidgets alpha channel of wxColor not working as expected


When setting a panel's BackgroundColor to wxColor(0,0,0,0). It seems to not be completely transparent.

I have a simple setup, I used the helloWorld example to illustrate my problem, I have a frame, with 2 panels like this:

wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(150, 100), NULL, wxString::Format("panel1"));
wxPanel *panel2 = new wxPanel(this, wxID_ANY, wxPoint(155,0) , wxSize(150, 100), NULL, wxString::Format("panel2"));

enter image description here

As you can see I have set the BackgroundColor of the frame to green using SetBackgroundColour:

this->SetBackgroundColour(wxColor(0,255,0,255));

Now I will try to make both panels transparent using SetBackgroundColour:

panel->SetBackgroundColour(wxColor(0,0,0,0));
panel2->SetBackgroundColour(wxColor(255,0,0,0));

The expected result would be to have an all green screen, as the panels would be transparent, you would see the green frame, but instead of that I can still see the 2 panels in a slightly different colour green:

enter image description here

I'm not as much looking for a solution as I'm looking for an explanation as to why this happens.

To try it out here is the source code of the hello world example including my code:

// Start of wxWidgets "Hello World" Program
#include <wx/wx.h>
 
class MyApp : public wxApp
{
public:
    bool OnInit() override;
};
 
IMPLEMENT_APP(MyApp);
DECLARE_APP(MyApp);
 
class MyFrame : public wxFrame
{
public:
    MyFrame();
 
private:
    void OnHello(wxCommandEvent& event);
    void OnExit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
};
 
enum
{
    ID_Hello = 1
};
 
bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame();
    frame->Show(true);
    return true;
}
 
MyFrame::MyFrame()
    : wxFrame(nullptr, wxID_ANY, "Hello World")
{

    wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(150, 100), NULL, wxString::Format("panel1"));
    wxPanel *panel2 = new wxPanel(this, wxID_ANY, wxPoint(155,0) , wxSize(150, 100), NULL, wxString::Format("panel2"));
    
    panel->SetBackgroundColour(wxColor(0,0,0,0));
    panel2->SetBackgroundColour(wxColor(255,0,0,0));
    this->SetBackgroundColour(wxColor(0,255,0,255));

    wxMenu *menuFile = new wxMenu;
    menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
                     "Help string shown in status bar for this menu item");
    menuFile->AppendSeparator();
    menuFile->Append(wxID_EXIT);
 
    wxMenu *menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);
 
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append(menuFile, "&File");
    menuBar->Append(menuHelp, "&Help");
 
    SetMenuBar( menuBar );
   
    CreateStatusBar();
    SetStatusText("Welcome to wxWidgets!");
 
    Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
    Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
    Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
 
void MyFrame::OnExit(wxCommandEvent& event)
{
    Close(true);
}
 
void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxMessageBox("This is a wxWidgets Hello World example",
                 "About Hello World", wxOK | wxICON_INFORMATION);
}
 
void MyFrame::OnHello(wxCommandEvent& event)
{
    wxLogMessage("Hello world from wxWidgets!");
}

I'm compiling this on macos using g++ -std=c++17 main.cpp `wx-config --cxxflags --libs`


Solution

  • There is no support for overlapping (semi)transparent windows in wxWidgets. If you need transparency effects you need to use wxGraphicsContext and things yourself, but this is just not going to work with the standard native windows.