I am using wxHyperLink. OnHyperlinkClicked(wxHyperlinkEvent&) is called when user clicks on the link. OnHyperlinkClicked() helps to switch between 2 screens. I want to call this function explicitly - without user interaction.
I am using the following code for that:
BEGIN_EVENT_TABLE(UserRegistrationFrame, wxFrame)
EVT_HYPERLINK(wxID_ANY, UserRegistrationFrame::OnAuthCodeOptionLinkClicked)
END_EVENT_TABLE()
void MyClass::MyFunction()
{
wxHyperlinkEvent event;
OnAuthCodeOptionLinkClicked(event);
}
void MyClass::OnAuthCodeOptionLinkClicked(wxHyperlinkEvent& event)
{
// code to switch
}
Is this the correct way to achieve my goal? Or do I have to use something different?
The code is not correct, because with EVENT_TABLE you are setting a handler that doesn't exist.
When the user clicks on the control the event is fired, and the static table will call UserRegistrationFrame::OnAuthCodeOptionLinkClicked, not MyClass::OnAuthCodeOptionLinkClicked
I'd better forget EVENT_TABLES and go with Dynamic Event Handling. Using Bind() gives you more features.
Now, you want to call the event-handler function directly, not coming from a user action. Then you need to create an event just to pass it to the handler. That's what you do in MyClass::MyFunction(), right?
Don't mix jobs. If both your direct-call and the event-handler use a common feature, put it in a different function and call it directly or from the event-handler.
But the question is Why do you use a wxHyperlinkCtrl for a task like screen switching? Do you want also the default browser to be launched?
Related
I am learning wxWidgets and i came across the following example that uses static event table:
EVT_SCROLLWIN(VScrollWindow::OnScroll)
EVT_MOUSE_EVENTS(VScrollWindow::OnMouse)
Now I want use dynamic event table using Bind but I could not find any macro corresponding the EVT_SCROLLWIN and EVT_MOUSE_EVENTS that can be used inside Bind. I also searched in the documentation page but there also it is written only that:
EVT_SCROLLWIN(func):
Process all scroll events.
As we can see the above doesn't specify something like wxEVT_SCROLLWIN.
This is what I have tried:
Bind(/*what should come here*/, VScrollWindow::OnScroll, this);
Bind(/*what should come here*/, VScrollWindow::OnMouse, this);
My question is what should come in the comment part in the above snippet. Basically I want to have the same effect using Bind as was done using static event table.
EVT_SCROLLWIN and EVT_MOUSE_EVENTS are special event macros that handle all mouse or scroll events. The idea was that in the handler method, you would check for all the event types you were interested in and handle them in sub-blocks.
if ( ev.GetEventType() != wxEVT_MOTION )
{
...
}
else if ( ev.GetEventType() != wxEVT_LEFT_DOWN )
{...
There are no equivalent for those macros when using Bind. The only option is to bind handlers for the individual event types separately. For example:
Bind(wxEVT_LEFT_DOWN, VScrollWindow::OnMouseLeftDown, this);
Bind(wxEVT_SCROLLWIN_THUMBTRACK, VScrollWindow::OnThumb, this);
...
It might seem like more work, but really you're just moving control flow for event handling from one long event handler to a series of Bind calls.
I'm creating my first C++ wxWidgets application. I'm trying to create some kind of split button where the options are displayed in a grid. I have a custom button class which, when right-clicked on, opens a custom wxPopupTransientWindow that contains other buttons.
When I click on the buttons in the popup, I want to simulate a left click on the main button. I'm trying to achieve this through events, but I'm kinda confused.
void expandButton::mouseReleased(wxMouseEvent& evt)
{
if (pressed) {
pressed = false;
paintNow();
wxWindow* mBtn = this->GetGrandParent();
mBtn->SetLabel(this->GetLabel());
mBtn->Refresh();
wxCommandEvent event(wxEVT_BUTTON);
event.SetId(GetId());
event.SetEventObject(mBtn);
mBtn-> //make it process the event somehow?
wxPopupTransientWindow* popup = wxDynamicCast(this->GetParent(), wxPopupTransientWindow);
popup->Dismiss();
}
}
What is the best way to do this?
You should do mBtn->ProcessWindowEvent() which is a shorter synonym for mBtn->GetEventHandler()->ProcessEvent() already mentioned in the comments.
Note that, generally speaking, you're not supposed to create wxEVT_BUTTON events from your own code. In this particular case and with current (and all past) version(s) of wxWidgets it will work, but a cleaner, and guaranteed to also work with the future versions, solution would be define your own custom event and generate it instead.
I have a doubt about CheckBoxes and click events. I have some button which executes a function OnClick, something like this on code:
SomeButton->OnClicked.AddDynamic(this, &ClassName::FunctionToExecute);
For style reasons, I thought that I should use a Toggle Button, implemented with a CheckBox, instead of a regular Button. However, I am having trouble finding the correct method to bind the function to each click. So far, I tried something like this, but it doesn't work. I also tried declaring a delegate, but it won't work either.
SomeCheckBox->OnCheckStateChanged.Add(&ClassName::FunctionToExecute);
What is the correct way to bind the function to the OnCheckStateChanged() event?
Thanks a lot in advance :smile:
If you are using a UMG Check box (which it sounds like you are), than we can look at the delegate declaration:
// In Checkbox.h
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FOnCheckBoxComponentStateChanged, bool, bIsChecked );
and notice that we need a bool input parameter for our callback function.
So that means that our callback function has to look like this:
void UYourWidget::OnCheckboxChanged(bool bIsChecked) {}
You can then bind your widget like this:
if(CheckBox)
{
CheckBox->OnCheckStateChanged.AddDynamic(this, &UTextChatWidget::Test);
}
If you are using a slate check box, then the callback function declaration is a bit different. It uses the ECheckBoxState enum instead of a boolean.
SNew(SCheckBox)
.OnCheckStateChanged(this, &SFoo::OnStateChanged)
void SFoo::OnStateChanged(ECheckBoxState NewState) {}
My typical approach for figuring this stuff out is to simply do a CTRL+SHIFT+F search for the delegate in Visual Studio to find other examples of it.
I'm new to Meteor, I could not find a sufficient answer to this but how does one go about referencing a Template's event handlers programmatically.
For example I would like to add or update or trigger an event defined in a template without actually as an example (pressing or clicking a button).
In the Template object I can see the events object below and can I access it but is this the right way?
Template.myTemplate._tmpl_data.events[]
Thanks!
You can define the handler outside the event map and call it as a function:
someHandler = function(this, evt,tpl) {
// do something with this, evt, and tpl
}
Template.myTemplate.events({
'click .myButton': function(event,template) {
var self = this;
return someHandler(self, event,template);
}
});
// Call someHandler whereever you want passing in whichever args you want
This is not a complete example, but should be able to get you going on some workable direction. If it works, please edit this answer to reflect a more complete example.
I am writing an application using gtkmm 3 (running Ubuntu 12.04 LTS) and working right now with the Gtk::Entry control.
I cannot find the correct signal to capture so that I can grab the Gtk::Entry buffer text before it is changed, and persist it to maintain a record of changes. I know that in some other tool-kits, there is a hook provided that facilitates such. (I believe using a "shadow buffer".)
What signal do I have to grab to do this? What is the slot's signature for this signal? Is this functionality supported at all?
Since you are changing the behaviour, it's better to inherit from Gtk::Entry:
class ValidatedEntry : public Gtk::Entry {
Glib::ustring last_valid;
virtual void on_changed()
{
Glib::ustring text = get_text();
if (... validation here ...)
set_text(last_valid); // WARNING: will call this on_changed() again
else
last_valid = text;
Gtk::Entry::on_changed(); // propagate down
}
};
BUT
This goes against usability, that's why it's not a built-in behaviour. Users won't like the text reverting back just because they miss-typed something; they might hit backspace before they realize the entry threw the wrong character away.
You should at least wait until the user presses the Enter key (i.e. signal_activate or override on_activate()), or do something less drastic, like showing a warning icon.
You could give a try to GObject's "notify" signal. It is used in conjunction with the property to spy. Connecting to "notify::text" will call your callback for each modification of the "text" property, but the first change may be the setter that will set the initial value, that you could then store. Worth a try.
Otherwise, you could try to store it on the first triggering of the "insert-text" or "delete-text" signals. Please give use some feedback if that seems to work.
I also agree with DanielKO: on an usability point of view, modifying user input is just annoying and bad practice. Better to tell her which field is wrong, put the focus there, and/or have a button to reset to defaults, but not enforce any change on user input.