Hi,
I have written a simple Custom Widget for LED using wxPanel. It includes nothing more than a circle with user selected On-Color & Off-Color.
Everything works fine, when background of parent widget is white.
As soon as background of parent widget turns dark, a white(or any other color which I set) rectangle appears around the circle.
Is there any way to make my LED widget background transparent or wxPanel non-rectangular?
TIA,
sam
Making Background of Custom Widget Transparent
Making Background of Custom Widget Transparent
- Attachments
-
- led2.png (484 Bytes) Viewed 15166 times
-
- led1.png (488 Bytes) Viewed 15166 times
Re: Making Background of Custom Widget Transparent
Achieving "real" transparency that e.g. would even work on a parent with a background image, is hard.
For simple cases, just set the background color of the custom widget to the background color of its parent.
For simple cases, just set the background color of the custom widget to the background color of its parent.
Use the source, Luke!
Re: Making Background of Custom Widget Transparent
Hi,
Thanks for info.
Background of the LED widget will be a bitmap/png/jpeg file, actually a map, loaded by the user on the fly.
So background of LED widget may have multiple colors simultaneously.
With circular LED shape, while background may be tolerable, but there can be Triangular shaped LED and its terribly annoying.
Is there a workaround this?
sam
Thanks for info.
Background of the LED widget will be a bitmap/png/jpeg file, actually a map, loaded by the user on the fly.
So background of LED widget may have multiple colors simultaneously.
With circular LED shape, while background may be tolerable, but there can be Triangular shaped LED and its terribly annoying.
Is there a workaround this?
sam
Re: Making Background of Custom Widget Transparent
What exactly is the issue?
This naive code
results on Windows 10 (if you're not on MSW, perhaps SetBackgroundStyle(wxBG_STYLE_TRANSPARENT) could work) in this
Did you get drawing artifacts when resizing etc. with just simple code like above?
BTW, the bitmap panel is just for testing, the image resizing should be done e.g. similarly to viewtopic.php?f=1&t=45099#p186759
EDIT
There were drawing artifacts when resizing a regular panel but that could be fixed by using wxFULL_REPAINT_ON_RESIZE in the panel'style.
This naive code
Code: Select all
#include <wx/wx.h>
class BitmapPanel : public wxPanel
{
public:
BitmapPanel(wxWindow* parent, const wxBitmap& bitmap = wxNullBitmap)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE),
m_bitmap(bitmap)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &BitmapPanel::OnPaint, this);
}
void SetBitmap(const wxBitmap& bitmap)
{
m_bitmap = bitmap;
Update(); Refresh();
}
private:
wxBitmap m_bitmap;
void OnPaint(wxPaintEvent&)
{
wxPaintDC dc(this);
dc.SetBackground(*wxBLACK_BRUSH);
dc.Clear();
if ( !m_bitmap.IsOk() )
return;
wxMemoryDC mdc(m_bitmap);
dc.StretchBlit(wxPoint(0, 0), dc.GetSize(), &mdc, wxPoint(0,0), mdc.GetSize(), wxCOPY, true);
}
};
class wxLEDCtrl : public wxWindow
{
public:
enum Shape { Circle, Triangle };
enum State { Off = 0, On = 1 };
wxLEDCtrl(wxWindow* parent, Shape shape = Circle, State state = On,
const wxColour& colourOn = *wxRED, const wxColour& colourOff = *wxLIGHT_GREY)
: wxWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTRANSPARENT_WINDOW),
m_shape(shape), m_state(state), m_colourOn(colourOn), m_colourOff(colourOff)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &wxLEDCtrl::OnPaint, this);
}
bool HasTransparentBackground() override { return true; }
protected:
wxSize DoGetBestClientSize() const override
{
const int size = FromDIP(32);
return wxSize(size, size);
}
private:
Shape m_shape;
State m_state;
wxColour m_colourOn, m_colourOff;
void OnPaint(wxPaintEvent&)
{
const wxColour* clr = m_state == On ? &m_colourOn : &m_colourOff;
wxPaintDC dc(this);
wxDCPenChanger penChanger(dc, *clr);
wxDCBrushChanger brushChanger(dc, *clr);
const wxRect r = wxRect(dc.GetSize());
if ( m_shape == Circle )
{
dc.DrawCircle(r.GetLeft() + r.GetWidth() / 2, r.GetTop() + r.GetHeight() / 2,
r.GetWidth() / 2 );
}
else
if ( m_shape == Triangle )
{
const int pointCount = 3;
wxPoint points[pointCount];
points[0] = r.GetBottomLeft();
points[1] = r.GetBottomRight();
points[2].x = r.GetLeft() + r.GetWidth() / 2;
points[2].y = r.GetTop();
dc.DrawPolygon(pointCount, points);
}
else
wxFAIL_MSG("Invalid LED shape");
}
};
class MyFrame : public wxFrame
{
public:
MyFrame() : wxFrame(nullptr, wxID_ANY, "Test", wxDefaultPosition, wxSize(640, 640))
{
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
wxButton* button = new wxButton(this, wxID_ANY, "Load image file for background of the third panel...");
mainSizer->Add(button, wxSizerFlags().Expand().Border());
button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MyFrame::OnLoadImageFile, this);
wxPanel* panel1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE);
CreateLEDs(panel1);
mainSizer->Add(panel1, wxSizerFlags().Border());
wxPanel* panel2 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE);
panel2->SetBackgroundColour(*wxYELLOW);
CreateLEDs(panel2);
mainSizer->Add(panel2, wxSizerFlags().Proportion(1).Expand().Border());
m_bitmapPanel = new BitmapPanel(this);
CreateLEDs(m_bitmapPanel);
mainSizer->Add(m_bitmapPanel, wxSizerFlags().Proportion(1).Expand().Border());
SetSizer(mainSizer);
}
protected:
BitmapPanel* m_bitmapPanel;
void CreateLEDs(wxPanel* parent)
{
wxGridSizer* sizer = new wxGridSizer(3);
wxLEDCtrl* LEDCtrl;
LEDCtrl = new wxLEDCtrl(parent);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
LEDCtrl = new wxLEDCtrl(parent, wxLEDCtrl::Circle, wxLEDCtrl::On, *wxGREEN, *wxLIGHT_GREY);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
LEDCtrl = new wxLEDCtrl(parent, wxLEDCtrl::Circle, wxLEDCtrl::Off);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
LEDCtrl = new wxLEDCtrl(parent, wxLEDCtrl::Triangle, wxLEDCtrl::On, *wxRED, *wxLIGHT_GREY);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
LEDCtrl = new wxLEDCtrl(parent, wxLEDCtrl::Triangle, wxLEDCtrl::On, *wxGREEN, *wxLIGHT_GREY);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
LEDCtrl = new wxLEDCtrl(parent, wxLEDCtrl::Triangle, wxLEDCtrl::Off);
sizer->Add(LEDCtrl, wxSizerFlags().DoubleBorder());
parent->SetSizer(sizer);
}
void OnLoadImageFile(wxCommandEvent&)
{
static wxString fileName;
wxImage image;
fileName = wxFileSelector("Choose Image to Load", "", fileName, "",
"Image files (*.jpg;*.png;*.tga;*.bmp;*.tiff;*.gif;*.ico;*.pcx)| *.jpg;*.png;*.tga;*.bmp;*.tiff;*.gif;*.ico;*.pcx",
wxFD_OPEN | wxFD_FILE_MUST_EXIST, this);
if ( !fileName.empty() && image.LoadFile(fileName) )
m_bitmapPanel->SetBitmap(wxBitmap(image));
}
};
class MyApp : public wxApp
{
public:
bool OnInit() override
{
wxInitAllImageHandlers();
(new MyFrame)->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
BTW, the bitmap panel is just for testing, the image resizing should be done e.g. similarly to viewtopic.php?f=1&t=45099#p186759
EDIT
There were drawing artifacts when resizing a regular panel but that could be fixed by using wxFULL_REPAINT_ON_RESIZE in the panel'style.