I am trying to understand how EVT_KILL_FOCUS and SetFocus on a combobox works .Here is the following code:
import wx
class MainWindow(wx.Frame):
count = 1
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(150,150), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
panel = wx.Panel(self, -1)
self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
btn = wx.Button(panel, label="Test")
MainFrameSizer = wx.BoxSizer(wx.VERTICAL)
MainFrameSizer.Add(self.Calc_Display, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)
MainFrameSizer.Add(btn, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)
panel.SetSizer(MainFrameSizer)
panel.Fit()
self.Show()
def OnKillFocus(self, event):
print ('EVT_KILL_FOCUS was called %i times' %MainWindow.count)
MainWindow.count += 1
# self.Calc_Display.SetFocus()
event.Skip()
app = wx.App(False)
frame = MainWindow(None, "Test")
app.MainLoop()
If run this, you will get a print every time the combobox loses focus, which is expected.
If you uncomment line 28, that's when it gets weird. The EVT_KILL_FOCUS gets called over and over. That is the behavior I am trying to understand. In the program I am writing, I want to force the combobox to maintain focus in case a condition is not satisfied. Are there any ways around this behavior?
I found this link on the issue, but I did not quite understand it: http://wiki.wxpython.org/Surviving%20with%20wxEVT%20KILL%20FOCUS%20under%20Microsoft%20Windows
Thanks for any help
After reading the link posted in your question, and playing around with your code, I came to the conclusion that calling SetFocus() on the combobox is apparently triggering the EVT_KILL_FOCUS in Windows. I had noticed that on running the program, it prints the statement once, although It shouldn't since the combobox is not losing focus.
I tried two things:
First was to move the combo box code after the button code. In this case when the program is run the Focus is on the button, and sure enough the statement is not printed!
Here's the edit:
btn = wx.Button(panel, label="Test")
self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
Second was to try binding the btn to a handler which sets the focus on the combobox
btn.Bind(wx.EVT_BUTTON, self.On_Button)
def On_Button(self, event):
self.Calc_Display.SetFocus()
In this case the statement was being printed twice every time the button was being clicked. I guess this is once for when the focus is lost and once for setting back the focus. Note that the SetFocus() is still commented out in the OnKillFocus in this case.
Back to your code: If the SetFocus is "uncomment-ed" the statement is printed many times because it keeps setting the focus which in turn triggers the event and it goes on in a loop. This may be a wrong explanation, but nevertheless it is the only thing I could think of.
Related
I am using Combobox widget and have that widget observe on a give function call. However the issue I ran into, is as I/user type the "input" in the combobox, the function got called multiple times.
Ideally I would only want the Observe function be called after I complete the input and press "enter".
Here is an example:
example_widget = widgets.Combobox( options = ['A','A1','A10','A101'],
ensure_option = True, description ='Example')
and here is the observe; call back
example_widget.observe(foo, 'value')
def foo(,_):
print('call back got triggered')
so as one type "A10" progressively, the call back was triggered three times, namely as A, A1, A10 were typed.
The ideal behaviour is that I input A10, and then press "enter", the call back function foo() only got executed once.
Thanks
example_widget = widgets.Combobox( options = ['A','A1','A10','A101'],
ensure_option = True, description ='Example', continuous_update = False)
need to set continuous_update to False.
I'm trying to make simple FoxPro application with two buttons. First button starts while-loop and works correctly. Second button must break this loop. But I can't find any correctly working solution.
There are loop code:
DO WHILE !thisForm.cancelpressed
IF thisForm.cancelpressed
EXIT
ENDIF
randNum=VAL(TRIM(STR(ROUND( 3*RAND(), 1))))
&&oneVar=VAL("1")
IF randNum = VAL("1")
ThisForm.shape1.BackColor = greenColor
ThisForm.shape2.BackColor = orangeColor
ThisForm.shape3.BackColor = redColor
ENDIF
cs = seconds()
IF abs(cs - seconds()) >= 15
doevents
cs = seconds()
ENDIF
IF thisForm.cancelpressed
EXIT
ENDIF
DOEVENTS
WAIT TIMEOUT 1
ENDDO
This code is in the first button Click method. Form object have user-defined 'cancelpressed' property. In the second button click method I put this:
thisForm.cancelpressed = .T.
Thisform.Release()
Clear Events
But it not work. When loop started it dont want to listen any commands and clicks, and it dont let to close the program. Please help if you can
You could try setting
Application.AutoYield = .T.
as per https://msdn.microsoft.com/en-us/library/aa977324(v=vs.71).aspx
But if that doesn't work then I think you are stuck as VFP is not a true multithreaded application. You might be able to get around the problem using a timer object as per http://fox.wikis.com/wc.dll?Wiki~TimerExample or using a multi threading workaround from https://blogs.msdn.microsoft.com/calvin_hsia/2006/05/16/create-multiple-threads-from-within-your-application/ but you would be very much on your own.
I have to say that starting a new application in VFP today probably isn't the best idea. There are plenty of current alternatives.
The problem is with your wait window. Remove it.
Local greenColor, orangeColor, redColor
m.greenColor = 0x00FF00
m.orangeColor = 0x3060FF
m.redColor = 0xFF0000
Do While !Thisform.cancelpressed
randNum=Val(Trim(Str(Round( 3*Rand(), 1))))
If m.randNum = Val("1")
Thisform.shape1.BackColor = m.greenColor
Thisform.shape2.BackColor = m.orangeColor
Thisform.shape3.BackColor = m.redColor
Endif
Doevents
Enddo
(I don't understand why you are doing such a weird randNum setting and check nor the purpose of setting the same colours again and again but it is not the point in this question)
Normally you should prefer using a Timer with a code like this.
And BTW this has nothing to do with multithreading neither in VFP nor in another language. You are simply doing a loop with a cancel flag check. Updating the UI, say in C#, with the same approach wouldn't be any easier.
I use an instance of UITextField in which the text is normally aligned to the right, but switches to left alignment when being edited. This is done by calling setTextAlignment: on the editingDidBegin event. Since the update to iOS 6 this behaves strangely: The text alignment is changed correctly from right to left, but the cursor remains at the far right of the text field until some input is performed.
Does anybody know how to restore the expected behaviour so that the cursor moves as well when the alignment is changed?
To give some context: I use the text field to show a value with a unit. The unit is removed during editing and then displayed again after the user hits enter.
Method called on event editingDidBegin:
- (IBAction)textEditingDidBegin:(UITextField *)sender
{
[sender setTextAlignment:NSTextAlignmentLeft];
[sender setText:[NSString stringWithFormat:#"%.0f", width]];
}
Method called on event editingDidEnd:
- (IBAction)textEditingDidEnd:(id)sender
{
[sender setTextAlignment:UITextAlignmentRight];
[sender setText:[NSString stringWithFormat:#"%.0f m", width]];
}
Try resigning the textView as first responder, then make it first responder right after that.
textView.textAlignment = NSTextAlignmentCenter;
[textView resignFirstResponder];
[textView becomeFirstResponder];
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
textField.textAlignment = NSTextAlignmentLeft ;
return YES ;
}
Change the textAlignment before editing did begin. The best place I know to do this is in the UITextFieldDelegate method textFieldShouldBeginEditing.
The ShowDialog method of the PrintDialog class in WPF is declared to return nullable bool (i.e. bool?), which is consistent with the documentation details:
"true if a user clicks Print; false if a user clicks Cancel;
or null if a user closes the dialog box without clicking Print or Cancel." from http://msdn.microsoft.com/en-us/library/system.windows.controls.printdialog.showdialog.aspx
However, in the code below, no matter how I close the dialog, (I tried the X and Alt-F4) I can never make it return null. Unless I press the Print button, it is always false. This is my test code:
PrintDialog pd = new PrintDialog();
bool? result;
result = pd.ShowDialog();
Do you get the same behaviour? Is the documentation wrong or am I misinterpreting it or not testing correctly? Perhaps this is OS related, I am running Windows 7 Enterprise.
Thank you.
L
I have the following method that is executing twice every time it is called:
public static void ChangeToRepository(RepositoryTextBox textBox, int repositoryNumber)
{
MessageBox.Show("you");
int indexOfLastRepository = (textBox.RepositoryCollection.Count - 1);
if (repositoryNumber > indexOfLastRepository)
{
AddTextRepositoriesThrough(textBox, repositoryNumber, indexOfLastRepository);
}
textBox.RepositoryCollection[textBox.CurrentRepositoryNumber].CurrentText = textBox.Text;
textBox.PreviousRepositoryNumber = textBox.CurrentRepositoryNumber;
textBox.CurrentRepositoryNumber = repositoryNumber;
textBox.Text = textBox.RepositoryCollection[textBox.CurrentRepositoryNumber].CurrentText;
}
The first time that the method executes, it executes all of the code except for its last line:
textBox.Text = textBox.RepositoryCollection[textBox.CurrentRepositoryNumber].CurrentText;
The second time, it executes all of the code. What's up?
When you assign to CurrentRepositoryNumber on the text box, it probably triggers an event handler that calls back to this function again. This seems likely because the property name suggests that it controls the current repository, which this method then is responsible for displaying somehow.
You might want to temporary delist, assign to the property and then re-enlist that event handler. Or maybe you need more of a redesign to get the responsibilities clear - often with GUI frameworks that is hard to do, and the simplest option is to just delist, assign, re-enlist, with this kind of pattern:
textBox.TextChange -= YourHandler;
textBox.Text = newValue;
textBox.TextChange += YourHandler;