It's been a while since I used GTK+, and the last time I did was in C, not using gtkmm and C++ as I am now. Anyway, I have what I think should be an easy problem to solve:
I have a pop-up menu consisting of a list of radio buttons, and when I click one of them I want some action to occur. The code goes like this:
Gtk::RadioMenuItem::Group group;
for ( size_t i = 1; i < LH_MAX; ++i )
{
Gtk::RadioMenuItem* pItem = new Gtk::RadioMenuItem( group, names[i], names[i] );
pItem->set_name( names[i] );
pItem->signal_activate().connect( sigc::mem_fun(*this, &MyClass::on_item_activated) );
pItem->show();
m_Menu.append( *Gtk::manage(pItem) );
}
The only problem I see is that MyClass::on_item_activated gets called twice when a previously-unselected radio button is chosen from the menu. It's called only once when the already-selected radio button is clicked.
I'm guessing that the first firing is to say "something is no longer activate," and the second is for the new radio button activation. Whether I'm right or wrong, the question is the same: how best can I have my handler only take action once per click? Either I need the handler to get called only once, or I need something to check from inside it to know if the callback is a "duplicate" or not.
You could use sigc::bind to supply the item as a argument to the callback function.
pItem->signal_activate().sigc::bind(sigc::mem_fun(*this,&MyClass::on_item_activated),pItem));
Then you can use item->get_active() in the callback to respond to activations only.
void MyClass::on_item_activated(Gtk::RadioMenuItem* item) {
if (item->get_active()) {
// Do some stuff
}
}
That's what I do too, connect to signal_toggled() and check if get_active() is true.
I don't know exactly what you're trying to accomplish (or what MyClass is and what base classes it inherits from), but connecting to signal_toggled() might be more useful than signal_activate()
/Agree with Johannes. Check if the item is activated when receiving the signal.
Related
I have a program like this
...
$self->{bn1}=Wx::Button->new( $tb1, -1, 'Start');
EVT_BUTTON( $self, $self->{bn1}, \&on_click_start );
...
...
sub on_click_start
{
my( $this, $event ) = #_;
$this->{bn1}->SetLabel("Cancel");
$event->Skip;
for (...) {
long_time_operation();
last if ( Cancel_clicked );
}
}
...
My problem is when I click the Start button, on_click_start() will be called, and I want change the label of Start button to Cancel, that allow I to click the button to break out the long_time_operation() loop.
How do I make right code for it?
The only real solution is to use multiple threads and perform the long operation in a background thread. If you want to keep your code simple, you can use wxYield() to handle the events from inside this event handler, but be aware that this may (and will) result in difficult to debug problems due to reentrancy, so at the very least you need to disable the rest of your UI if you're doing it like this.
Try with a wxTimer and start it in your on_click_start function. Put the long time operation code under the event of the timer (ensure that it dont trigger repeteadly, just stop the timer there too).
Inside your long operation function use some global var to know if you want to cancel. In the event of your button now change the value of your global var so your long term code knows about that and cancels/break from the loop.
I am not sure if a loop under the event of the timer can hang your UI, but it appears to use threads, so that may not happen. Try it anyway, i always use wxTimer when I need something like that (dont hanging the UI and not using threads directly).
I am currently trying to mimic the enyo.Popup behavior. I looked at the source at github but having a hard time to understand it.
Especially that is the code I have trouble with:
handlers: {
//...
onRequestShow: "requestShow",
onRequestHide: "requestHide"
},
//* #public
events: {
//* Fires after the popup is shown.
onShow: "",
//* Fires after the popup is hidden.
onHide: ""
},
And some where else in the code, there are calls to this.show().
Firstly, I did not found a declaration for this.show(). Secondly, though I assume that it must be inside this.show() and this.hide() respectively, where are the onShow and onHide events called?
And lastly, I defined a kind of myself, containing also the above code. But despite the show() and hide() methods are working, my own requestShow() and requestHide() methods were not called.
What am I missing?
Firstly, show is a function declared on enyo.Control: http://enyojs.com/api/#enyo.Control::show
onShow and onHide are events that can be subscribed to by the popup's owner (hence, their declaration in the events block). They are called in the showingChanged function. The method for calling events is do{EventNameWithoutOn}. In this case: doShow.
Check this documentation on events: https://github.com/enyojs/enyo/wiki/Event-Handling
(Or, you could buy my nice Enyo book! http://roysutton.com/2013/01/31/print-book-now-available/ )
The handlers block is a way for a control to subscribe to messages it (or its children) generate. Having said that, I don't see any place in the code that generates onRequestHide events.
I hope that helps!
Here's my code:
...
if($("input:checked").length > 0) {
chrome.tabs.create(
{url:"http://www.multiculturalyp.com/multiculturalypnewtab.crx"},
function(tab) {
chrome.management.onInstalled.addListener(function(info){alert("Installed A");});
chrome.management.onEnabled.addListener(function(info){alert("Enabled A");});
}
);
chrome.tabs.create(
{url:"instructions.html"},
function(tab) {
chrome.management.onInstalled.addListener(function(info){alert("Installed B");});
chrome.management.onEnabled.addListener(function(info){alert("Enabled B");});
}
);
}
...
So what is happening: I wrote an extension, and if a user so chooses from with that extension's options, a second extension is installed, so I launch instructions in the form of html to tell the user what to click if they really want it installed. I want to hide the instructions (close the instructions tab) automatically ones the second extension installs. The problem is that it appears that neither the onInstalled nor the onEnabled events are triggered. My example above is a simplified version of the logic that just alerts when the events are triggered but so far I can't get the onInstalled event for extension B to be triggered in extension A. I registered the events twice each when they didn't work the first time. The alerts end in A or B just to tell me whether the first registered listener, the second or both get triggered, but the should all get triggered in extension A.
So can this be done? If so, what am I doing wrong.
Thanks in advance.
My suggestion - try to bind events before executing a url with extension. Bind event once and check its type to make action (in the background page!):
chrome.management.onInstalled.addListener(function(info){
if(info.id == MY_EXTENSION_ID){
alert("Installed");
}
});
chrome.management.onEnabled.addListener(function(info){
if(info.id == MY_EXTENSION_ID){
alert("Enabled");
}
});
chrome.tabs.create({url:"http://www.multiculturalyp.com/multiculturalypnewtab.crx"},
function(tab) {alert('tab was opened')});
I'm writing a messaging application in GWT, and have a fairly difficult problem to find a solution for. I'm working with a GWT CellList. In my cell list I'm displaying all the recent contacts a user has had recent communication with. But lets say that a user is writing a message to a person not on that list. I temporarily add them to the recentContacts list, and update the CellList so that it shows..
But then let's say that they end up not sending the message. I need to be able to detect that, and remove them from the list. The obvious place to do that is in the selection change handler. It actually turns out though that within a selection change handler, if can modify the list of data objects that represent the cell list, but when you actually push them to the cell list, I get an index out of bounds error.
I've verified that this is the issue. So basically I'm stuck. The obvious place to check this is when your selecting a different contact to view. I can then check if any messages were sent to this other contact, and if not, get rid of the contact, but I need to somehow not do it in the selectionChangeHandler. Does anyone have any solution/ideas? I tried a mouse up event, but that ends up happening before the selection event takes place.
Thanks for any help in advance :-)
selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
public void onSelectionChange(SelectionChangeEvent event) {
ContactDO selectedContact = selectionModel.getSelectedObject();
//Check if we want to remove a contact from the list
if ( we want to remove a contact in the list that is not the currently selected contact. ) {
//remove contact
recentContacts.remove(contactThatisNotSelected);
//Refresh the contact cell list
contactCellList.setVisibleRange(0, recentContacts.size());
contactCellList.setRowCount(recentContacts.size(), true);
contactCellList.setRowData(0, recentContacts);
}
}
});
The solution that I implemented was just to use a Timer, and then do the work about 100ms later. Not really a fan of this solution. I'm still looking for another.
I am using Galasoft MVVMLight. I have a button bound to a command which sends a message to the view to display a messagebox asking for confirmation. If I click either the Yes or No on the messagebox it performs the necessary actions then shows up again. However if I step through the program instead I only get the messagebox once. Is this a bug or is something else going on?
EDIT: I modified the messagebox.show line by adding an Icon and default result and now I can't reproduce this behavior... I'm stumped... if it happens again I'll try a counter like airplaneman19 suggested.
Try tracking the amount of times the MessageBox shows up with an integer, like so:
int counter = 0;
if(counter == 0){
MessageBox.Show();
counter++;
}
else if (counter == 1)
/*Do something that won't alter the program just to escape the if....else statement
like "x++";
I had a similar problem once, I mean, with MessageBox firing twice. It was due to focus changes, and ListView in WinForms fired another selection changed event when running the app; but when debugging - some focus change was missing, and there was no bug :)
I hope this atleast gives you some ideas...