We use wxWidgets 3.1.3 under Linux, Windows and macOS. Under the latter we have a strange phenomenon when our application is displayed on a retina monitor.
We draw almost all components ourselves. If we use the background style wxBG_STYLE_PAINT, we get a kind of right and bottom border.
In the attached picture you can see the white lines between buttons and you can also guess the line below.
The color of this border is the same as the color of the parent component. It almost seems as if painting the background (realized with GetSize and DrawRectangle) does not paint the full area. Interestingly, the effect does not occur if you leave the Default Background Style or simply move the window to a non-retina monitor.
Does anyone have an idea why this is the case or how to get rid of this effect? Thanks a lot.
Strange borders on macOS with wxBG_STYLE_PAINT on retina screen
Re: Strange borders on macOS with wxBG_STYLE_PAINT on retina screen
Hi,
Can you reproduce it with the minimal sample?
If not - can you post some code?
Thank you.
Can you reproduce it with the minimal sample?
If not - can you post some code?
Thank you.
Re: Strange borders on macOS with wxBG_STYLE_PAINT on retina screen
Yes, I adapted the minimal sample using a class which inherits from wxPanel.
You will see two red areas with a blue right/bottom border on a retina screen. With no retina screen you won't see the blue borders.
You will see two red areas with a blue right/bottom border on a retina screen. With no retina screen you won't see the blue borders.
Code: Select all
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWidgets headers)
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------
// the application icon (under Windows it is in resources and even
// though we could still include the XPM here it would be unused)
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
#endif
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// Define a new application type, each program should derive a class from wxApp
class MyApp : public wxApp
{
public:
// override base class virtuals
// ----------------------------
// this one is called on application startup and is a good place for the app
// initialization (doing it here and not in the ctor allows to have an error
// return: if OnInit() returns false, the application terminates)
virtual bool OnInit() wxOVERRIDE;
};
#include <wx/dcbuffer.h>
class MyPanel : public wxPanel {
public:
MyPanel(wxWindow* parent) : wxPanel(parent) {
SetBackgroundStyle(wxBG_STYLE_PAINT);
Connect(wxEVT_PAINT, wxPaintEventHandler(MyPanel::onPaint));
}
void onPaint( wxPaintEvent& event ) {
wxAutoBufferedPaintDC dc( this );
int w, h;
GetSize(&w, &h);
wxRect rect( 0,0, w, h );
dc.SetBrush( wxBrush( *wxRED ) );
dc.SetPen( wxPen( *wxRED ) );
dc.DrawRectangle( rect );
}
};
// Define a new frame type: this is going to be our main frame
class MyFrame : public wxFrame
{
public:
// ctor(s)
MyFrame(const wxString& title);
// event handlers (these functions should _not_ be virtual)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
private:
// any class wishing to process wxWidgets events must use this macro
wxDECLARE_EVENT_TABLE();
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
// IDs for the controls and the menu commands
enum
{
// menu items
Minimal_Quit = wxID_EXIT,
// it is important for the id corresponding to the "About" command to have
// this standard value as otherwise it won't be handled properly under Mac
// (where it is special and put into the "Apple" menu)
Minimal_About = wxID_ABOUT
};
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------
// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
wxEND_EVENT_TABLE()
// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also implements the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
wxIMPLEMENT_APP(MyApp);
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
// call the base class initialization method, currently it only parses a
// few common command-line options but it could be do more in the future
if ( !wxApp::OnInit() )
return false;
// create the main application window
MyFrame *frame = new MyFrame("Minimal wxWidgets App");
// and show it (the frames, unlike simple controls, are not shown when
// created initially)
frame->Show(true);
frame->Layout();
frame->Refresh();
// success: wxApp::OnRun() will be called which will enter the main message
// loop and the application will run. If we returned false here, the
// application would exit immediately.
return true;
}
// ----------------------------------------------------------------------------
// main frame
// ----------------------------------------------------------------------------
// frame constructor
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title)
{
// set the frame icon
SetIcon(wxICON(sample));
// If menus are not available add a button to access the about box
SetBackgroundColour(*wxBLUE);
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(new MyPanel(this), 1, wxEXPAND);
sizer->Add(new MyPanel(this), 1, wxEXPAND);
SetSizer(sizer);
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(2);
SetStatusText("Welcome to wxWidgets!");
#endif // wxUSE_STATUSBAR
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
Close(true);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(wxString::Format
(
"Welcome to %s!\n"
"\n"
"This is the minimal wxWidgets sample\n"
"running under %s.",
wxVERSION_STRING,
wxGetOsDescription()
),
"About wxWidgets minimal sample",
wxOK | wxICON_INFORMATION,
this);
}
Re: Strange borders on macOS with wxBG_STYLE_PAINT on retina screen
No solution but some workarounds
1. Set the background color of the parent to match (not always possible, since there are several children and the fix only helps for one child component)
2. Do without the Background Style Flag wxBG_STYLE_PAINT for macOS. However, the wxAutoBufferedPaintDC has to be omitted, because it has an assertion for the presence of this flag.
3. Using a wxGraphicsContext for rendering. Its drawing methods also work correctly on a retina display.
1. Set the background color of the parent to match (not always possible, since there are several children and the fix only helps for one child component)
2. Do without the Background Style Flag wxBG_STYLE_PAINT for macOS. However, the wxAutoBufferedPaintDC has to be omitted, because it has an assertion for the presence of this flag.
3. Using a wxGraphicsContext for rendering. Its drawing methods also work correctly on a retina display.