Image corruption in wxScrolledWindow while scrolling - c++

I want to view an image in one of wxSplitterWindow using wxScrolledWindow.
I derived class from wxPanel, which I add into wxScrolledWindow. But the result is not what i want.(
class ImagePanel : public wxPanel
{
public:
//ImagePanel(wxFrame* parent);
ImagePanel(wxWindow* parent);
void paintEvent(wxPaintEvent& event);
void paintNow();
void setBitmap(wxBitmap& imBitmap);
void setBitmap(wxImage& img);
int GetHeight();
int GetWidth();
void render(wxDC& dc);
DECLARE_EVENT_TABLE()
private:
wxBitmap curBitmap;
};
Paint event:
void ImagePanel::paintEvent(wxPaintEvent& event)
{
wxBufferedPaintDC dc(this);
render(dc);
}
This is how I have written the interface into main frame constructor:
topSizer = new wxBoxSizer(wxVERTICAL);
topSplitter = new wxSplitterWindow(this,ID_TOPSPLITTER,wxDefaultPosition,wxDefaultSize,wxSP_LIVE_UPDATE|wxSP_3D);
topSizer->Add(topSplitter,1,wxALL|wxEXPAND,0);
imagePanel = new wxPanel(topSplitter,ID_IMAGEPANEL);
imageSizer = new wxBoxSizer(wxVERTICAL);
imagePanel->SetSizer(imageSizer);
optionPanel = new wxPanel(topSplitter,ID_OPTIONPANEL);
optionSizer = new wxBoxSizer(wxVERTICAL);
optionPanel->SetSizer(optionSizer);
topSplitter->SplitVertically(imagePanel, optionPanel);
topSplitter->SetMinimumPaneSize(200);
//===========================================
//image panel interface
imageScWindow=new wxScrolledWindow(imagePanel,ID_IMAGESCWINDOW,wxDefaultPosition,wxDefaultSize,
wxVSCROLL|wxHSCROLL|wxALL|wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE);
imgArea = new ImagePanel(imageScWindow);
imageSizer->Add(imageScWindow,1,wxEXPAND,0);
scrollSizer = new wxBoxSizer(wxVERTICAL);
imageScWindow->SetSizer(scrollSizer);
scrollSizer->Add(imgArea,1,wxEXPAND,0);
imageScWindow->SetTargetWindow(imgArea);
And this is the function that loads image:
void MainFrame::Setpic(wxCommandEvent& event)
{
wxString path = GetCurrentWorkingDir()+wxT("\\")+tmptxt1->GetValue();
wxImage img(path);
wxBitmap imBitmap(img,-1);
imgArea->setBitmap(imBitmap);
imageScWindow->SetScrollbars(1,1,imgArea->GetWidth(),imgArea->GetHeight());
imageScWindow->Refresh();
}
Thats what i get:
https://i.imgur.com/x1GIlrl.png
I have also tried to do like this in the constructor, without SetTargetArea:
//===========================================
//image panel interface
imageScWindow=new wxScrolledWindow(imagePanel,ID_IMAGESCWINDOW,wxDefaultPosition,wxDefaultSize,
wxVSCROLL|wxHSCROLL|wxALL|wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE);
imgArea = new ImagePanel(imageScWindow);
imageSizer->Add(imageScWindow,1,wxEXPAND,0);
scrollSizer = new wxBoxSizer(wxVERTICAL);
imageScWindow->SetSizer(scrollSizer);
scrollSizer->Add(imgArea,1,wxEXPAND,0);
Then image shows properly, but if I change the frame size or move splitter, scrollbars disappear, and I have to set them again somwhere.
Then i tried to do like this:
int prvx,prvy;
void ImagePanel::paintEvent(wxPaintEvent& event)
{
reinterpret_cast<wxScrolledWindow*>(this->GetParent())->GetViewStart(&prvx,&prvy);
reinterpret_cast<wxScrolledWindow*>(this->GetParent())->SetScrollbars(1,1,curBitmap.GetWidth(),curBitmap.GetHeight());
reinterpret_cast<wxScrolledWindow*>(this->GetParent())->Scroll(wxPoint(prvx,prvy));
wxBufferedPaintDC dc(this);
render(dc);
}
It shows properly, but lags while scrolling, even without wxFULL_REPAINT_ON_RESIZE in wxScrolledWindow. The reason why it is in paint event: if I add this into OnSize event, program crashes. What to do?

I'm not sure where to begin answering your question. Here's a minimal sample of a frame that has a splitter with a bitmap on the left and a panel on the right. I hope you can adapt this sample to do what you need.
// 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
#include <wx/scrolwin.h>
#include <wx/splitter.h>
#include <wx/dcbuffer.h>
class MyFrame : public wxFrame
{
public:
MyFrame( wxWindow* parent, int id = wxID_ANY, wxString title = "Demo",
wxPoint pos = wxDefaultPosition, wxSize size = wxDefaultSize,
int style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
private:
void OnScrollPaint( wxPaintEvent& event );
wxScrolledCanvas* m_canvas;
wxBitmap m_bitmap;
};
MyFrame::MyFrame( wxWindow* parent, int id, wxString title, wxPoint pos,
wxSize size, int style )
:wxFrame( parent, id, title, pos, size, style )
{
m_bitmap=wxBitmap ("test.png", wxBITMAP_TYPE_PNG );
wxSplitterWindow* m_splitter1
= new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxSP_LIVE_UPDATE );
m_canvas = new wxScrolledCanvas( m_splitter1, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxSTATIC_BORDER|wxHSCROLL|wxVSCROLL );
m_canvas->SetScrollRate( 5, 5 );
m_canvas->SetVirtualSize(m_bitmap.GetWidth(), m_bitmap.GetHeight());
m_canvas->SetBackgroundStyle(wxBG_STYLE_PAINT);
m_canvas->Bind( wxEVT_PAINT, &MyFrame::OnScrollPaint , this );
wxPanel* m_panel2 = new wxPanel( m_splitter1, wxID_ANY, wxDefaultPosition,
wxDefaultSize, wxSTATIC_BORDER|wxTAB_TRAVERSAL );
m_splitter1->SplitVertically( m_canvas, m_panel2, GetSize().x/2 );
}
void MyFrame::OnScrollPaint( wxPaintEvent& event )
{
wxAutoBufferedPaintDC dc(m_canvas);
m_canvas->DoPrepareDC(dc);
dc.Clear();
dc.DrawBitmap(m_bitmap,0,0);
}
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
wxInitAllImageHandlers();
MyFrame* frame = new MyFrame(NULL);
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(MyApp);
To run this, be sure to change "test.png" in line 35 to the name of an actual image file on your computer (and change wxBITMAP_TYPE_PNG if the image file isn't a png).
The important parts are:
Set the background style of the canvas to wxBG_STYLE_PAINT as shown in line 46.
In the paint handler, call the DoPrepareDC method on the paintdc.
By the way, the paint handler shown in my sample isn't very good. It draws the entire bitmap every time. A better approach would be to get the update region and only redraw the parts that are needed, but I wanted to keep this simple.

Related

wxWidgets - setting an image as background

I am trying to set an image as the background but I have no idea how to do it.
It has been hours. The first lines of code I copied from somebody and they seemed alright but it still doesn't work.
The error that I have appears in a separate window and says it cannot load/find the image.
#include "MainFrame.h"
#include <wx/wx.h>
#include "FrameTwo.h"
#include "wx/custombgwin.h"
#include <wx/dcclient.h>
enum IDs {
BUTTON_ID=2
};
wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
EVT_BUTTON(BUTTON_ID, MainFrame::OnLoginClicked)
wxEND_EVENT_TABLE()
MainFrame::MainFrame(const wxString& title) : wxFrame(nullptr, wxID_ANY, title) {
wxPanel* panel = new wxPanel(this);
wxClientDC dc(panel);
wxMemoryDC mdc;
int w, h;
w = 600;
h = 600;
dc.GetSize(&w, &h);
wxImage img(wxT("C:\\Users\\ALEX\\Desktop\\background_uno.jpeg"), wxBITMAP_TYPE_JPEG);
wxBitmap cat(img.Scale(w, h, wxIMAGE_QUALITY_HIGH));
mdc.SelectObject(cat);
dc.Blit(0, 0, cat.GetWidth(), cat.GetHeight(), &mdc, 0, 0, wxCOPY, 0);
mdc.SelectObject(wxNullBitmap);
//panel->SetBackgroundColour(wxColour(255, 102, 102)); //light orange-red
//panel->SetBackgroundColour(wxColour(155, 202, 62)); //fresh green
wxButton* login = new wxButton(panel, BUTTON_ID, "Log in", wxPoint(340, 350), wxSize(100, 35));
CreateStatusBar(); //creates a bar in the bottom of the frame
//wxBoxSizer* sizer = new wxBoxSizer(wxALIGN_CENTER_VERTICAL);
//sizer -> Add(login, 1, wxEXPAND | wxALL, 10);
wxButton* exit = new wxButton(panel, wxID_OK, "Exit", wxPoint(340, 390), wxSize(100, 35));
exit->Bind(wxEVT_BUTTON, &MainFrame::OnExitClicked, this);
panel->SetFont(panel->GetFont().Scale(2.5));
wxStaticText* staticText = new wxStaticText(panel, wxID_ANY, "UNO DELUXE", wxPoint(300, 40));
panel->SetFont(panel->GetFont().Scale(0.5));
wxStaticText* username = new wxStaticText(panel, wxID_ANY, "Enter username: ", wxPoint(180, 250));
wxTextCtrl* textCtrl = new wxTextCtrl(panel, wxID_ANY, " ", wxPoint(300, 250), wxSize(250, -1));
wxStaticText* password = new wxStaticText(panel, wxID_ANY, "Enter password: ", wxPoint(180, 290));
wxTextCtrl* textCtrl2 = new wxTextCtrl(panel, wxID_ANY, "", wxPoint(300, 290), wxSize(250, -1), wxTE_PASSWORD);
}
I can't help you with the program not being able to find the image - the image needs to exist either in the application's working folder or on an absolute path.
You can get around this by including the image in the executable. Unfortunately there is no consistent cross-platform way to do this - windows and mac have separate ways of doing this but GTK has no way at all. Here are some suggestions from the wiki for some possible workarounds.
Regardless of the method used to get the image into the application, you should not draw it with a client DC. Instead you should handle the paint event for the panel and draw the image in the handler for that event. Here's an example:
#include <wx/wx.h>
class ImageBgFrame: public wxFrame
{
public:
ImageBgFrame(wxFrame *frame, const wxString& title);
private:
void OnImagePanelPaint(wxPaintEvent&);
void OnExit(wxCommandEvent&);
void CreateScaledBg();
wxPanel* m_imagePanel;
wxImage m_image;
wxBitmap m_scaledBg;
};
ImageBgFrame::ImageBgFrame(wxFrame *frame, const wxString& title)
:wxFrame(frame, wxID_ANY, title)
{
::wxInitAllImageHandlers();
// Try to load the image.
m_image = wxImage("Thinking-of-getting-a-cat.png", wxBITMAP_TYPE_PNG);
if ( !m_image.IsOk() )
{
return;
}
// Create the controls.
m_imagePanel = new wxPanel(this, wxID_ANY);
CreateScaledBg();
wxButton* exit = new wxButton(m_imagePanel, wxID_OK, "Exit");
// Arrang the controls with a sizer.
wxBoxSizer* szr = new wxBoxSizer(wxVERTICAL);
szr->Add(exit,wxSizerFlags().Border(wxALL));
m_imagePanel->SetSizer(szr);
Layout();
// Bind Event Handlers
m_imagePanel->Bind(wxEVT_PAINT, &ImageBgFrame::OnImagePanelPaint, this);
exit->Bind(wxEVT_BUTTON, &ImageBgFrame::OnExit, this);
}
void ImageBgFrame::OnImagePanelPaint(wxPaintEvent&)
{
if ( m_imagePanel->GetSize() != m_scaledBg.GetSize() )
{
CreateScaledBg();
}
wxPaintDC dc(m_imagePanel);
dc.DrawBitmap(m_scaledBg,0,0);
}
void ImageBgFrame::OnExit(wxCommandEvent&)
{
Close();
}
void ImageBgFrame::CreateScaledBg()
{
wxSize sz = m_imagePanel->GetSize();
m_scaledBg = wxBitmap(m_image.Scale(sz.GetWidth(), sz.GetHeight(),
wxIMAGE_QUALITY_NORMAL));
}
class ImageBgApp : public wxApp
{
public:
bool OnInit()
{
ImageBgFrame* frame = new ImageBgFrame(NULL, "Image BG");
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(ImageBgApp);
This assumes that the image "Thinking-of-getting-a-cat.png" is in the application's working folder. On GTK it looks like this:
I've also made a few other changes to the code you gave:
I'm using Bind to connect the event handlers instead of static event tables.
I'm using default sizes for the controls instead of setting the size explicitly and laying out the controls in a sizer instead of setting explicit location.
Both of these changes are a more modern way of doing things.

wxButton covering entire client area C++

I have made an application using wxWidgets 3.1.5 in C++ and everything is working fine except a test button that I have on my main window.
Here's a pic:
The menubar, menus and their functions work perfectly but the button covers the entire client area.
Here's the code:
main.h
#pragma once
#include <wx\wx.h>
#include "mainFrame.h"
class main : public wxApp
{
private:
mainFrame* frame;
public:
virtual bool OnInit();
};
main.cpp
#include "main.h"
wxIMPLEMENT_APP(main);
bool main::OnInit()
{
frame = new mainFrame("Kill Me", wxPoint(15, 10), wxSize(640, 480));
frame->Show();
return true;
}
mainFrame.h
#pragma once
#include "About.h"
using str = std::string;
class mainFrame : public wxFrame
{
public:
mainFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
~mainFrame();
private:
About* abtF = NULL;
wxButton* hewwo = NULL;
wxMenuBar* mbar = NULL;
wxMenu* sett = NULL;
wxMenu* quitApp = NULL;
wxMenu* abt = NULL;
void onHewwo(wxCommandEvent& evt);
void onSett(wxCommandEvent& evt);
void quit(wxCommandEvent& evt);
void about(wxCommandEvent& evt);
wxDECLARE_EVENT_TABLE();
};
enum {
ID_SETT = 1,
ID_BTN = 2
};
mainFrame.cpp
#include "mainFrame.h"
wxBEGIN_EVENT_TABLE(mainFrame, wxFrame)
EVT_BUTTON(ID_BTN, onHewwo)
EVT_MENU(ID_SETT, onSett)
EVT_MENU(wxID_EXIT, quit)
EVT_MENU(wxID_ABOUT, about)
wxEND_EVENT_TABLE()
mainFrame::mainFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
:
wxFrame(nullptr, wxID_ANY, title, pos, size) {
hewwo = new wxButton(this, ID_BTN, "Hewwo World", wxPoint(15, 15), wxSize(70, 20));
sett = new wxMenu();
sett->AppendSeparator();
sett->Append(ID_SETT, "&Settings");
quitApp = new wxMenu();
quitApp->AppendSeparator();
quitApp->Append(wxID_EXIT, "&Quit this crap");
abt = new wxMenu();
abt->AppendSeparator();
abt->Append(wxID_ABOUT, "&About");
mbar = new wxMenuBar();
mbar->Append(sett, "&Settings");
mbar->Append(abt, "&About");
mbar->Append(quitApp, "&Quit");
SetMenuBar(mbar);
}
void mainFrame::onHewwo(wxCommandEvent& evt) {
wxMessageBox("Hewwo", "Hewwo", wxOK | wxICON_INFORMATION, this);
}
void mainFrame::onSett(wxCommandEvent& evt) {
wxMessageBox("Settings", "Settings", wxOK | wxICON_INFORMATION, this); // Just a test
}
void mainFrame::about(wxCommandEvent& evt) {
abtF = new About(wxPoint(10, 10), wxSize(480, 320));
abtF->Show();
}
void mainFrame::quit(wxCommandEvent& evt) {
Close(true);
}
mainFrame::~mainFrame() {
delete abtF;
}
I'm using Visual Studio 2019.
(I followed OneLoneCoder's (javidx9) youtube video on wxWidgets)
That is how a wxFrame with only one child behaves.
If you don't want that, use a wxSizer to layout your button (position, align, expand etc).
Reference:
if the frame has exactly one child window, not counting the status and toolbar, this child is resized to take the entire frame client area. If two or more windows are present, they should be laid out explicitly either by manually handling wxEVT_SIZE or using sizers
wxFrame docs -> Default event processing -> wxEVT_SIZE

Custom wxPanel problems

I'm writing a C++ wxWidgets application. I want my custom wxButton's that have a EXPANDABLE flag to open up a panel on top of them when I right click. Said panel is also supposed to automatically close when the cursor leaves it, or when the user clicks on one of the buttons it contains.
I created a custom wxPanel class for this job, but I'm having some trouble. The panel is successfully created when I right click on the button, but:
The panel is not removed when the cursor leaves it
There's an awkward graphical glitch when I move the cursor that cause the other interface elements to get on top of it (?)
Here's my code:
expandPanel.h
#pragma once
#include "wx/wx.h"
#include "ikeButton.h"
class expandPanel : public wxPanel
{
wxBoxSizer* sizer;
int type;
public:
expandPanel(wxWindow* parent, wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString & name = wxPanelNameStr);
~expandPanel();
void paintEvent(wxPaintEvent& evt);
void paintNow();
void Render(wxDC& dc);
void mouseLeftWindow(wxMouseEvent& evt);
DECLARE_EVENT_TABLE()
};
expandPanel.cpp
#include "expandPanel.h"
BEGIN_EVENT_TABLE(expandPanel, wxPanel)
EVT_LEAVE_WINDOW(expandPanel::mouseLeftWindow)
EVT_PAINT(expandPanel::paintEvent)
END_EVENT_TABLE()
expandPanel::expandPanel(wxWindow* parent, wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
wxPanel::Create(parent, id, pos, size, style, name);
sizer = new wxBoxSizer(wxHORIZONTAL);
SetSizer(sizer);
}
expandPanel::~expandPanel()
{
}
void expandPanel::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
Render(dc);
}
void expandPanel::paintNow()
{
wxClientDC dc(this);
Render(dc);
}
void expandPanel::Render(wxDC& dc)
{
dc.SetBrush(wxColour(80, 83, 111));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(0, 0, this->GetSize().GetWidth(), this->GetSize().GetHeight());
}
void expandPanel::mouseLeftWindow(wxMouseEvent& evt)
{
this->Close();
}
(I'm fairly new to this framework)
Ok, I tried switching to wxPopupTransientWindow, but the buttons appear on a different location on screen and sometimes disappear when I move the cursor, but the popup placed in the correct position do not disappear in any way. I feel like I'm doing this completely wrong.
expandMenu.h
#pragma once
#include "wx/wx.h"
#include "wx/popupwin.h"
#include "ikeButton.h"
class expandMenu : public wxPopupTransientWindow
{
wxBoxSizer* sizer;
public:
expandMenu(wxWindow* parent, wxPoint pos, wxSize size, int flags = wxBORDER_NONE);
~expandMenu();
void AddButton(ikeButton* btn);
};
expandMenu.cpp
#include "expandMenu.h"
expandMenu::expandMenu(wxWindow* parent, wxPoint pos, wxSize size, int flags)
: wxPopupTransientWindow(parent, flags)
{
this->SetPosition(pos);
this->SetSize(size);
this->SetBackgroundColour(wxColour(90, 93, 121));
sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Layout();
SetSizer(sizer);
}
expandMenu::~expandMenu()
{
}
void expandMenu::AddButton(ikeButton* btn)
{
unsigned int w = this->GetSize().GetWidth(), h = this->GetSize().GetHeight();
if (sizer->GetItemCount() > 0)
this->SetSize(wxSize(w, h + h / sizer->GetItemCount() ));
sizer->Add(btn, 0, wxEXPAND);
sizer->Layout();
}
Then I generate them like this:
void Main::OnExpandableRightClick(wxMouseEvent& evt)
{
expandMenu* menu = new expandMenu(this, wxGetMousePosition(), wxSize(50, 50));
for (int i = 0; i < 3; i++) menu->AddButton(new ikeButton(this, wxID_ANY, "TEST " + std::to_string(i), OP));
menu->Popup();
evt.Skip();
}
(This is a test scenario to see if everything is working)

How to show another frame after the event?

how to show another frame after button click event?
like this
My code here show window OnInit. but what to do next?
I did not find how to do this. little experience with this.
I comment the window that should be.
enum
{
wxID_First_Load = 5000,
wxID_First_Frame,
wxID_First_Panel
};
class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
void fileLoad(wxCommandEvent& event);
private:
int file_count = 0;
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_BUTTON(wxID_First_Load, MyFrame::fileLoad)
wxEND_EVENT_TABLE()
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame("Hello World", wxDefaultPosition, wxSize(450, 250));
frame->SetWindowStyle(wxCAPTION | wxSYSTEM_MENU );
frame->Show(true);
return true;
}
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, wxID_First_Frame, title, pos, size)
{
wxBoxSizer *first_sizer = new wxBoxSizer(wxVERTICAL);
wxPanel *firstPanel = new wxPanel(this, wxID_First_Panel);
wxButton *firstButton_Load = new wxButton(firstPanel, wxID_First_Load, "Choose file");
firstPanel->SetSizer(first_sizer);
first_sizer->Add(firstButton_Load, 1, wxEXPAND | wxALL, 10);
firstPanel->SetSizer(first_sizer);
}
void MyFrame::fileLoad(wxCommandEvent& WXUNUSED(event))
{
file_count = 2;
}
Second Frame or window:
wxPanel *firstPanel = new wxPanel(this, wxID_First_Panel);
wxBoxSizer *second_sizer = new wxBoxSizer(wxVERTICAL);
for (int i = 0; i < file_count; i++)
{
second_sizer->Add(new wxTextCtrl(firstPanel, wxWindowID(i), "Hello", wxDefaultPosition, wxSize(235, 60)), wxSizerFlags(0).Border(wxALL, 5));
}
firstPanel->SetSizer(second_sizer);
To create a new frame you need to create a new object of wxFrame class or a class deriving from it. Typically, you want to put some data and logic into your new frame, so you would create some class, e.g. MySecondaryFrame (but hopefully with a better name) , inheriting from wxFrame in a similar way to your existing MyFrame class.
Then to show it you would do the same thing that you do in MyApp::OnInit(), i.e. create a new object of this class and call Show() to actually show it.
P.S. Note that your SetWindowStyle(wxCAPTION | wxSYSTEM_MENU ) call is unnecessary, these styles are already on by default. Also, hard coding the frame size in pixels is a bad idea, consider using sizers to determine the best size suitable for the frame contents or just leave it unspecified if it really doesn't matter.

wxTextCtrl not aligning to center - wxSizerFlags not working in wxWidget

This code displays a single textbox and a button. When the user clicks the button, the window exits, however I want to put the textControl to the center of the window but it's not working. Here's my code:
// base.h
#ifndef base_h_
#define base_h_
#include <wx/app.h>
#include <wx/button.h>
#include <wx/string.h>
#include <wx/frame.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/panel.h>
class MainApp : public wxApp {
public:
virtual bool OnInit();
};
class MainFrame: public wxFrame {
public:
MainFrame( const
wxString& title, const wxPoint& pos, const wxSize& size );
wxBoxSizer *sizer;
void OnExit(wxCommandEvent& event);
DECLARE_EVENT_TABLE()
};
#endif
// base.cpp
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include "base.h"
IMPLEMENT_APP(MainApp)
bool MainApp::OnInit() {
MainFrame *MainWin = new MainFrame(_T("gui"), wxDefaultPosition, wxSize(5000, 5000));
MainWin->Show(TRUE);
SetTopWindow(MainWin);
return TRUE;
}
BEGIN_EVENT_TABLE ( MainFrame, wxFrame)
EVT_BUTTON ( 3, MainFrame::OnExit )
END_EVENT_TABLE()
MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size): wxFrame((wxFrame*)NULL,- 1, title, pos, size) {
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
wxPanel *panel = new wxPanel(this, wxID_ANY, wxPoint(0, 0));
sizer->Add(new wxTextCtrl(panel , 1, ""), wxSizerFlags().Center());
sizer->SetSizeHints(this);
SetSizer(sizer);
}
void MainFrame::OnExit( wxCommandEvent& event) {
Close(TRUE);
}
I don't know what I'm doing wrong here, shouldn't wxSizerFlags().Center do exactly what I want?
Your text control is wrapped inside a wxPanel. You add the text control to the sizer and set the sizer to the frame. This won't work and may even cause errors. You need to create two sizers, one for the panel and one for the frame. You have several options: You can have the panel expand to the size of the frame and have the text ctrl placed in the center of the panel, or you can center the panel and have the text ctrl expand to the size of the panel. Here's some code for the first option:
wxPanel* panel = new wxPanel(this, wxID_ANY);
wxTextCtrl* text = new wxTextCtrl(panel, 1, "");
wxBoxSizer* panelSizer = new wxBoxSizer(wxVERTICAL);
panelSizer->Add(text, wxSizerFlags().Center());
panel->SetSizer(panelSizer);
wxBoxSizer* frameSizer = new wxBoxSizer(wxVERTICAL);
frameSizer->Add(panel, wxSizerFlags().Expand());
SetSizer(frameSizer);
Note that I'm not familiar with wxSizerFlags, but I suppose that it should work like this. You may also have to set a size for the panel explicitly - right now it will use some default size.