Making Menus with wxPerl
by Roberto Alamos
|
Pages: 1, 2, 3, 4, 5, 6
Example
With all of that explained, I can show a full, working example. As before, add this code to the base code in the blank spot in the WxPerlComExampleFrame constructor.
# Create menus
# Action's sub menu
my $submenu = Wx::Menu->new();
$submenu->Append($id[2], "New normal item");
$submenu->Append($id[3], "Delete normal item");
$submenu->AppendSeparator();
$submenu->Append($id[4], "New check item");
$submenu->Append($id[5], "Delete check item");
$submenu->AppendSeparator();
$submenu->Append($id[6], "New radio item");
$submenu->Append($id[7], "Delete radio item");
# Disable items for this submenu
for(2..7) {
$submenu->Enable($id[$_], 0);
}
# Actions menu
my $actionmenu = Wx::Menu->new();
$actionmenu->Append($id[0], "Create Menu"); # Create new menu
$actionmenu->Append($id[1], "Delete Menu"); # Delete New Menu
$actionmenu->AppendSeparator();
$actionmenu->AppendSubMenu($id[100], "New Item", $submenu); # Create item submenu
$actionmenu->AppendSeparator();
$actionmenu->Append(wxID_EXIT, "Exit\tCtrl+X"); # Exit
# At first, disable the Delete Menu option
$actionmenu->Enable($id[1], 0);
# Create menu bar
$self->{MENU} = Wx::MenuBar->new();
$self->{MENU}->Append($actionmenu, "Actions");
# Attach menubar to the window
$self->SetMenuBar($self->{MENU});
$self->SetAutoLayout(1);
# Handle events
EVT_MENU($self, $id[0], \&MakeActionMenu);
EVT_MENU($self, $id[1], \&MakeActionMenu);
EVT_MENU($self, $id[2], \&MakeActionNormal);
EVT_MENU($self, $id[3], \&MakeActionNormal);
EVT_MENU($self, $id[4], \&MakeActionCheck);
EVT_MENU($self, $id[5], \&MakeActionCheck);
EVT_MENU($self, $id[6], \&MakeActionRadio);
EVT_MENU($self, $id[7], \&MakeActionRadio);
EVT_MENU($self, wxID_EXIT, sub {$_[0]->Close(1)});
This code creates a menu called Actions with the following options inside:
- Create Menu: When a user clicks this option, the program creates a new menu called New Menu at the right side of the Actions menu. The Create Menu option is enabled by default, but creating the menu disables this option.
- Delete Menu: Deletes the menu created with Create Menu. This option is disabled by default and is enabled when New Menu exists.
- New normal item: This option creates the Normal item option on New Menu when it exists. It is disabled by default.
- Delete normal item: Deletes Normal item when it exists. It is disabled by default.
- New check item: Creates the Check item option on New Menu when it exists. It is disabled by default. Check item is unchecked by default.
- Delete check item: Deletes Check item when it exists. It is disabled by default.
- New radio item: Creates the Radio item option on New Menu when it exists. It is disabled by default. Radio item is checked by default.
- Delete radio item: Deletes Radio item when it exists. It is disabled by default.
- Exit: Exits the program.
Once the code has created the menu, it attaches the menu to the menu bar saved on $self->{MENU}, then calls the EVT_MENU subroutine eight times to handle all of the menu events from Action's menu items. Add the following code to the base code where it says ### PUT SUBROUTINES HERE ###:
# Subroutine that handles menu creation/erasure
sub MakeActionMenu {
my($self, $event) = @_;
# Get Actions menu
my $actionmenu = $self->{MENU}->GetMenu(0);
# Now check if we have to create or delete the New Menu
if ($self->{MENU}->GetMenuCount() == 1) {
# New Menu doesn't exist
# Create menu
my $newmenu = Wx::Menu->new();
$self->{MENU}->Append($newmenu, "New Menu");
# Disable and Enable options
$actionmenu->Enable($id[0], 0); # New menu
$actionmenu->Enable($id[1], 1); # Delete menu
$actionmenu->Enable($id[2], 1); # New normal item
$actionmenu->Enable($id[3], 0); # Delete normal item
$actionmenu->Enable($id[4], 1); # New check item
$actionmenu->Enable($id[5], 0); # Delete check item
$actionmenu->Enable($id[6], 1); # New radio item
$actionmenu->Enable($id[7], 0); # Delete radio item
} else {
# New Menu exists
# Remove menu
$self->{MENU}->Remove(1);
# Enable and disable options
$actionmenu->Enable($id[0], 1);
for(1..7) {
$actionmenu->Enable($id[$_], 0);
}
}
return 1;
}
# Subroutine that handles normal item creation/erasure
sub MakeActionNormal {
my($self, $event) = @_;
# Check if New Menu exists
if($self->{MENU}->GetMenuCount() == 2) {
# New menu exists
# Get Action menu
my $actionmenu = $self->{MENU}->GetMenu(0);
my $newmenu = $self->{MENU}->GetMenu(1);
# Check if we have to create or delete a menu item
if($actionmenu->IsEnabled($id[2])) {
# Create normal menu item
$newmenu->Append($id[50], "Normal item");
# Disable and Enable options
$actionmenu->Enable($id[2], 0);
$actionmenu->Enable($id[3], 1);
} else {
# Delete menu item
$newmenu->Delete($id[50]);
# Enable and disable options
$actionmenu->Enable($id[2], 1);
$actionmenu->Enable($id[3], 0);
}
}
return 1;
}
# Subroutine that handles check item creation/erasure
sub MakeActionCheck {
my($self, $event) = @_;
# Check if New Menu exists
if($self->{MENU}->GetMenuCount() == 2) {
# New menu exists
# Get Action menu
my $actionmenu = $self->{MENU}->GetMenu(0);
my $newmenu = $self->{MENU}->GetMenu(1);
# Check if we have to create or delete a menu item
if($actionmenu->IsEnabled($id[4])) {
# Create check item
$newmenu->AppendCheckItem($id[51], "Check item");
# Disable and Enable options
$actionmenu->Enable($id[4], 0);
$actionmenu->Enable($id[5], 1);
} else {
# Delete menu item
$newmenu->Delete($id[51]);
# Enable and disable options
$actionmenu->Enable($id[4], 1);
$actionmenu->Enable($id[5], 0);
}
}
return 1;
}
# Subroutine that handles radio item creation/erasure
sub MakeActionRadio {
my($self, $event) = @_;
# Check if New Menu exists
if($self->{MENU}->GetMenuCount() == 2) {
# New menu exists
# Get Action menu
my $actionmenu = $self->{MENU}->GetMenu(0);
my $newmenu = $self->{MENU}->GetMenu(1);
# Check if we have to create or delete a menu item
if ($actionmenu->IsEnabled($id[6])) {
# Create radio item
$newmenu->AppendRadioItem($id[52], "Radio item");
# Disable and Enable options
$actionmenu->Enable($id[6], 0);
$actionmenu->Enable($id[7], 1);
} else {
# Delete menu item
$newmenu->Delete($id[52]);
# Enable and disable options
$actionmenu->Enable($id[6], 1);
$actionmenu->Enable($id[7], 0);
}
}
return 1;
}
The MakeActionMenu subroutine handles events for the New Menu and Delete Menu items. It first gets the Actions menu and checks whether the New Menu exists by retrieving the number of menus attached to the $self->{MENU} menu bar. If the new menu doesn't exist, the number of menus in the menu bar is equal to 1, and the subroutine then creates New Menu. If it exists, the subroutine deletes New Menu.
The MakeActionNormal, MakeActionCheck, and MakeActionRadio subroutines are almost identical. They differ only in the involved identifier numbers. These subroutines handle events for New normal item, Delete normal item, New check item, Delete check item, New radio item, and Delete radio item, respectively. They first check if New Menu exists (the number of menus attached to the menu bar is equal to 2). If so, they check if the options to create normal, check, or radio items are enabled, respectively. If the corresponding option is enabled, then the corresponding item doesn't exist on New Menu, and the subroutine creates it. If the option to create an item is disabled, then that item exists on New Menu and hence it must be deleted. If New Menu doesn't exist, the subroutines do nothing. Figure 3 shows how there are no options available if New Menu does not exist, and Figure 4 shows New Menu with two options added.

Figure 3. No available options without New Menu

Figure 4. New Menu has menu options
Conclusion
As this article has shown, menu programming with wxPerl is an extremely simple task. Wx::MenuBar and Wx::Menu's methods are very easy to use and remember. If you understood this article, you can do anything possible with menus in your wxPerl programs.
I have covered almost all of the available methods in Wx::Menu and Wx::MenuBar. I left out some methods related to pop-up menus, but I hope to cover these topics in future articles. WxPerl is a really great module, but its lack of adoption is due to its severe lack of documentation. This situation must be reversed, and this article is a small contribution to that cause.
See Also
- WxMenu tutorial and WxMenuBar tutorial by Julian Smart, Robert Roebling, Vadim Zeitlin, Robin Dunn, et al.
- "Adding a Menu Bar," by David Beech.
- "wxPerl: Another GUI for Perl," by Jouke Visser.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 2 of 2.
- Problem with mac os x dialog
2005-12-17 10:23:50 coohen [Reply]
I am new to wxPerl and Perl in general. It seems the ShowDialog(), and Exit menu code doesn't seem to work on Mac OS X. Is wxPerl still not usable in Mac OS X ?
- Wx::XRC
2005-10-19 22:32:00 lichtkind [Reply]
thats the easy way make menus with wx. write just an XML file and let em parse with with one instruction. inside the XML you define ID which you can late searchfor and glue a sub to it. making a GUI ist what MSFT proposes as its new great thing. WxPerl has this already crossplatform for 2 years.



