How to set the size of a toolbar button - c++

I am trying to make a toolbar with some radio buttons. The Problem is that when I add a button in the toolbar, the button is too big,bigger than the height of the toolbar. I have already tried to set the size of the bitmap with not any result. However there is not any function to set the size of the tool itself. Is there any way to make it?
this->m_ToolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxNO_BORDER | wxTB_TEXT | wxTB_NOICONS);
this->m_ToolBar->AddRadioTool(this->LastToolBarId, Name, wxNullBitmap, wxNullBitmap, toolTip, wxT(""), Data);
this->m_ToolBar->ToggleTool (this->LastToolBarId, true);
this->m_ToolBar->Realize();

Ok I found it. I didn't know that there is a white bitmap(16x15) over the text of the tool. So the answer is quite simple. I use SetToolBitmapSize with size (1,1)
this->m_ToolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxNO_BORDER | wxTB_TEXT | wxTB_NOICONS);
this->m_ToolBar->SetToolBitmapSize(wxSize(1,1));
this->m_ToolBar->AddRadioTool(this->LastToolBarId, Name, wxNullBitmap, wxNullBitmap, toolTip, wxT(""), Data);
this->m_ToolBar->ToggleTool (this->LastToolBarId, true);
this->m_ToolBar->Realize();

Related

Why does the second wxSizer fail to center the button?

I created a global panel and called a method that creates a sizer and a button. The button clears the sizer (i.e., also the panel), and then deletes is. Then, another method is called, using the same logic, it creates another sizer and another button. This time they don't work.
my code(windows, vs studio):
#include "MainFrame.h"
#include <wx/wx.h>s
MainFrame::MainFrame(const wxString& title) : wxFrame(nullptr, wxID_ANY, title)
{
panel = new wxPanel(this);
StartParty(panel);
}
void MainFrame::ClearButtonClicked(wxCommandEvent& evt)
{
panel->GetSizer()->Clear(true);
panel->SetSizerAndFit(nullptr);
ChooseMode(panel);
}
void MainFrame::StartParty(wxPanel* parent)
{
wxButton* start_button = new wxButton(parent, wxID_ANY, "Start the Party!", wxDefaultPosition, wxSize(200, 70));
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->AddStretchSpacer(1);
sizer->Add(
start_button,
0,
wxALL | wxALIGN_CENTER,
0);
sizer->AddStretchSpacer(1);
parent->SetSizerAndFit(sizer);
start_button->Bind(wxEVT_BUTTON, &MainFrame::ClearButtonClicked, this);
}
void MainFrame::ChooseMode(wxPanel* parent)
{
wxButton* select_button = new wxButton(parent, wxID_ANY, "Choose", wxDefaultPosition, wxSize(200, 70));
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->AddStretchSpacer(1);
sizer->Add(
select_button,
0,
wxALL | wxALIGN_CENTER,
0);
sizer->AddStretchSpacer(1);
parent->SetSizer(sizer);
}
You do need Layout(), as mentioned in the comments, as this is what actually repositions the windows -- SetSizer() just specifies the sizer to use for doing it, but doesn't do anything on its own immediately (it will when the window is resized the next time, as this results in a call to Layout()).
However, even if it's somewhat unrelated to the question itself, I think you shouldn't be doing this at all and use wxSimplebook instead. This simple (sic) class allows you to add a few pages to it and then easily switch between them.

How can I make a sizer expand to the whole wxNotebook page?

I have a wxNotebook with two added pages. Each page uses a wxFlexGridSizer to manage the various widgets on each page.
The first page has three columns of widgets, the second page only two. The first page is wider than the second page.
The notebook is resized to the size of its widest page (the first one). However, on the second page I would like to have the sizer expand to fill the entire page, too. Instead, it just resizes to fit the widgets on that page.
So my question is:
How can I make the sizer of the second page expand to the whole notebook width, which is determined by the width of the first page?
I have tried calling the Layout() function of the parent wxNotebook, but that did not help.
Edit:
wxNotebook *notebook = new wxNotebook(this, wxID_ANY);
wxPanel* pageOne = new wxPanel(notebook, wxID_ANY);
wxFlexGridSizer* sizer = new wxFlexGridSizer(3);
wxSizerFlags flags = wxSizerFlags().Align(wxLEFT).Border(wxRIGHT, 5);
wxStaticText* label = new wxStaticText(pageOne, wxID_ANY, wxT("Label 1"));
sizer->Add(label, flags);
label = new wxStaticText(pageOne, wxID_ANY, wxT("Label 2"));
sizer->Add(label, flags);
wxSpinCtrlDouble* value = new wxSpinCtrlDouble(pageOne, wxID_ANY, wxT("50.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
sizer->Add(value, flags);
pageOne->SetSizer(sizer);
notebook->AddPage(pageOne, wxT("Page 1"));
wxPanel* pageTwo = new wxPanel(notebook, wxID_ANY);
sizer = new wxFlexGridSizer(2);
flags = wxSizerFlags().Align(wxLEFT).Border(wxRIGHT, 5);
label = new wxStaticText(pageTwo, wxID_ANY, wxT("Label 1"));
sizer->Add(label, flags);
value = new wxSpinCtrlDouble(pageTwo, wxID_ANY, wxT("50.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
sizer->Add(value, flags);
pageTwo->SetSizer(sizer);
notebook->AddPage(pageTwo, wxT("Page 2"));
topLevelSizer->Add(notebook);
this->SetSizerAndFit(topLevelSizer);
You just need to make 2 small changes. First with the flex grid sizer on the second page you need to call AddGrowableCol(1). This means that the second column can expand. (The indicies start at 0, so column 1 is the second column.)
Second, you need to use slightly different sizer flags when adding the spin control double. For example, something like
sizer->Add(value, wxSizerFlags(0).Expand().Border(wxRIGHT, 5));
Here's the snippet you posted with these two changes:
wxNotebook *notebook = new wxNotebook(this, wxID_ANY);
wxPanel* pageOne = new wxPanel(notebook, wxID_ANY);
wxFlexGridSizer* sizer = new wxFlexGridSizer(3);
wxSizerFlags flags = wxSizerFlags().Align(wxLEFT).Border(wxRIGHT, 5);
wxStaticText* label = new wxStaticText(pageOne, wxID_ANY, wxT("Label 1"));
sizer->Add(label, flags);
label = new wxStaticText(pageOne, wxID_ANY, wxT("Label 2"));
sizer->Add(label, flags);
wxSpinCtrlDouble* value = new wxSpinCtrlDouble(pageOne, wxID_ANY, wxT("50.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
sizer->Add(value, flags);
pageOne->SetSizer(sizer);
notebook->AddPage(pageOne, wxT("Page 1"));
wxPanel* pageTwo = new wxPanel(notebook, wxID_ANY);
sizer = new wxFlexGridSizer(2);
sizer->AddGrowableCol(1);
flags = wxSizerFlags().Align(wxLEFT).Border(wxRIGHT, 5);
label = new wxStaticText(pageTwo, wxID_ANY, wxT("Label 1"));
sizer->Add(label, flags);
value = new wxSpinCtrlDouble(pageTwo, wxID_ANY, wxT("50.0"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
sizer->Add(value, wxSizerFlags(0).Expand().Border(wxRIGHT, 5));
pageTwo->SetSizer(sizer);
notebook->AddPage(pageTwo, wxT("Page 2"));
topLevelSizer->Add(notebook);
will let the spin control expand to take up all the remaining space while matching the border from the first page.

Interaction between wxPanel and wxFrame

I am trying to understand how wxFrame and wxPanel work together. I am having a hard time explaining the following code behavior:
I am trying to set up the GUI for my application. I have a function that creates a form for data entry:
void MyFrame::Initialize_Project_Info() {
//Info_Panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(600, 1000), wxTAB_TRAVERSAL, _T(""));
//Info_Panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T(""));
Info_Box = new wxBoxSizer(wxHORIZONTAL);
Info_Staticbox = new wxStaticBoxSizer(wxHORIZONTAL, Info_Panel, _T("Project Information"));
Info_Grid = new wxFlexGridSizer(4, 2, 0, 0);
//Note wsSize(width,height).
Project_Name = new wxStaticText(Info_Panel, wxID_ANY, _T("Project:"));
Engineer_Name = new wxStaticText(Info_Panel, wxID_ANY, _T("Engineer:"));
CrossSection_Name = new wxStaticText(Info_Panel, wxID_ANY, _T("Cross Section ID:"));
Additional_Notes = new wxStaticText(Info_Panel, wxID_ANY, _T("Additional Notes:"));
Enter_PN = new wxTextCtrl(Info_Panel, ENTER_PN, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_EN = new wxTextCtrl(Info_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_CSN = new wxTextCtrl(Info_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB, wxDefaultValidator, _T(""));
Enter_AN = new wxTextCtrl(Info_Panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, 100), wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB | wxTE_MULTILINE, wxDefaultValidator, _T(""));
Info_Grid->Add(Project_Name,
wxSizerFlags().Align(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL)
.Border(wxTOP | wxBOTTOM | wxLEFT));
Info_Grid->Add(Enter_PN, wxSizerFlags().Expand().Border(wxALL));
Info_Grid->Add(Engineer_Name,
wxSizerFlags().Align(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL)
.Border(wxBOTTOM | wxLEFT));
Info_Grid->Add(Enter_EN, wxSizerFlags().Expand().Border(wxBOTTOM | wxLEFT | wxRIGHT));
Info_Grid->Add(CrossSection_Name,
wxSizerFlags().Align(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL)
.Border(wxBOTTOM | wxLEFT));
Info_Grid->Add(Enter_CSN,
wxSizerFlags().Expand().Border(wxBOTTOM | wxLEFT | wxRIGHT));
Info_Grid->Add(Additional_Notes,
wxSizerFlags().Align(wxALIGN_LEFT).Border(wxBOTTOM | wxLEFT));
Info_Grid->Add(Enter_AN, wxSizerFlags().Expand().Border(wxBOTTOM | wxLEFT | wxRIGHT));
Info_Staticbox->Add(Info_Grid);
Info_Box->Add(Info_Staticbox, wxSizerFlags().Border(wxALL));
Info_Panel->SetSizer(Info_Box);
}
This code works if I append all the objects to a wxPanel when only defined in the scope of the function. If I define the wxPanel in the scope of the constructor of the wxFrame derived class, it does not work.
For example, doing this does not generate the form as intended:
MyFrame::MyFrame() : wxFrame(NULL,wxID_ANY,"Cross Sectional Beam Properties",wxDefaultPosition,wxSize(1200,600),wxDEFAULT_FRAME_STYLE & ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX)) {
Info_Panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T(""));
Initialize_Project_Info();
}
So, my question is how does wxPanel interface with wxFrame. Why would one moving one line of code (i.e. wxPanel initialization) change the outcome?
From the wx docs:
A frame is a window whose size and position can (usually) be changed
by the user. It usually has thick borders and a title bar, and can
optionally contain a menu bar, toolbar and status bar.
A panel is a window on which controls are placed. It is usually
placed within a frame. Its main feature over its parent class wxWindow
is code for handling child windows and TAB traversal.
wxWindow is a generic class used by any type of window. wxDialog is mainly used as a form where the user enters data.
Usually an application shows a frame as the main window of the app.
==> While you can place controls directly in a wxFrame, because of 'TAB traversal' and a OS's typical background features you better use a wxPanel.
This panel is a child of the main wxFrame and you can buid it at wxFrame's ctor.
Because in wxWidgets if a wxFrame has an unique child then this child is expanded to fit the whole client size of the wxFrame, then you don't use wxsizers for this panel-to-frame fitting.
When you create the controls (e.g. at wxPanel ctor) you set this wxPanel as the parent of the controls. And use sizers to layout them into the panel.
So each control has your panel as parent; an your panel has the frame as parent. Don't forget that 'this' pointers may be used as parents, or pass the parent as a parameter in the function that creates the windows (panel, controls).
Finally, the pointers to any wxWindow-derived class are created with "new", but you don't need to delete them, wxWigets internals takes care of their deletion.

How to resize frame after hiding a component in wxwidgets

I have a frame which has 4 textboxes and one link(change no of textboxes). when user clicks on link I am hiding 4th textbox. but what happens is after hiding 4th textbox, it's space remains blank. I don't want to keep its space blank. That space should disappear and frame should get resized. Is there any way that I can achieve this? when user again clicks on the link(change no of textboxes I am again displaying 4th textbox.
code:
m_ComputerNameText1 = new wxTextCtrl(m_panel, wxID_ANY, "computerName", wxDefaultPosition, wxSize(250, wxDefaultSize.GetHeight()));
m_ComputerNameText2 = new wxTextCtrl(m_panel, wxID_ANY, "computerName1", wxDefaultPosition, wxSize(250, wxDefaultSize.GetHeight()));
m_ComputerNameText3 = new wxTextCtrl(m_panel, wxID_ANY, "computerName3", wxDefaultPosition, wxSize(250, wxDefaultSize.GetHeight()));
m_ComputerNameText4 = new wxTextCtrl(m_panel, wxID_ANY, "computerName4", wxDefaultPosition, wxSize(250, wxDefaultSize.GetHeight()));
m_hyperLinkOption = new wxHyperlinkCtrl(m_panel, wxID_ANY, "Change no of textboxes", wxT(""), wxDefaultPosition, wxSize(135, wxDefaultSize.GetHeight()));
m_userPassSizer->Add(m_ComputerNameText1, 0, wxALIGN_LEFT | wxALL, 0);
m_userPassSizer->Add(m_ComputerNameText2, 0, wxALIGN_LEFT | wxALL, 0);
m_userPassSizer->Add(m_ComputerNameText3, 0, wxALIGN_LEFT | wxALL, 0);
m_userPassSizer->Add(m_ComputerNameText4, 0, wxALIGN_LEFT | wxALL, 0);
m_userPassSizer->Add(m_hyperLinkOption , 0, wxALIGN_LEFT | wxALL, 0);
Following function executes when hyperlink is clicked.
void OnAuthCodeOptionLinkClicked(wxHyperlinkEvent& event)
{
if (!m_hyperlinkOptionSelected)
{
m_hyperlinkOptionSelected= true;
m_ComputerNameText4->Hide();
m_hyperLinkOption->SetLabel("Go back");
}
else
{
m_hyperlinkOptionSelected= false;
m_ComputerNameText4->Show();
m_hyperLinkOption->SetLabel("change no of textboxes");
}
}
in this way I have to hide and show 4th textbox. After hiding some blank space remains. How can I avaoid that blank space and take link in the place of 4th textbox ?
Whenever I need to dynamically update the size of a control, I always call Layout() and Refresh().
You can find more info about Layout here:
http://docs.wxwidgets.org/3.1/classwx_window.html#a1b143c3e72bd0af533b76db4830a6113
As well as some good info on window sizing in general here:
http://docs.wxwidgets.org/3.1/overview_windowsizing.html
Calling Layout assumes that your class where you construct and manage your textboxes, etc. is a wxWindow derived control itself (like a panel, frame, whatever). If not, like you are making the changes on a view-model, you will need to call Layout and Refresh on the owning window:
void UpdateView()
{
view->Layout();
view->Refresh();
}
You may need to play around with your sizers, minimum size of windows, etc. to get the exact behavior you want.

wxWidgets ribbonBar taking up entire window

I've spent the past day figuring out how to get a wxRibbon bar. It took some work, but I finally got a ribbon bar working. Except that the ribbon bar takes up the entire window, except for a tiny space on the right side of my application.
The code I'm using to test in my main window is as follow:
Win_app::Win_app(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(640, 480))
{
wxRibbonBar* mainMenu = new wxRibbonBar(this,-1,wxDefaultPosition,wxSize(20,40));
wxRibbonPage* home = new wxRibbonPage(mainMenu, wxID_ANY, wxT("Home"));
wxRibbonPanel *test_panel1 = new wxRibbonPanel(home, wxID_ANY, wxT("Panel 1"),
wxNullBitmap, wxDefaultPosition, wxSize(320,60));
wxRibbonPanel *test_panel2 = new wxRibbonPanel(home, wxID_ANY, wxT("Panel 2"),
wxNullBitmap, wxDefaultPosition, wxSize(320,60));
wxRibbonPage* page = new wxRibbonPage(mainMenu, wxID_ANY, wxT("Another Page"));
wxRibbonPanel *test_panel3 = new wxRibbonPanel(page, wxID_ANY, wxT("Panel 3"),
wxNullBitmap, wxDefaultPosition, wxSize(640,60));
mainMenu->Realize();
Centre();
}
I'm using wxWidgets 2.9.4. Any help would be much appreciated! Thanks for reading.
I would suggest taking a look at the ribbon sample in your wxWidgets install located at wxdir\samples\ribbon. It looks to be doing roughly the same as your code with a key difference in that it adds the wxRibbonBar to a sizer:
wxSizer *s = new wxBoxSizer(wxVERTICAL);
s->Add(m_ribbon, 0, wxEXPAND);
s->Add(m_logwindow, 1, wxEXPAND);
s->Add(m_togglePanels, wxSizerFlags().Border());
SetSizer(s);
You need to do this because if there is a single control on a dialog it automatically fills the dialog, which in your case is unwanted behaviour.