2024-11-24 02:43 PM
Hi
I am using the TouchGFX keyboard to input data into fields on a number of settings screens. Since the screens are small, I cannot afford the option of Cancel and Enter buttons as used in the demo. Instead I have added 2 buttons to the keyboard for Enter and Cancel. The former leaves the buffer intact, while the latter clears it before returning. However, the function that contains the keyboard container continues executing while the keyboard is in use. The result is that the data is never entered into the field.
One workaround I have used is to add an 'Add/Edit' flex button that loads the keyboard and writes the returned buffer to the model. Flex buttons over the data fields, that are made visible at the time the keyboard container is loaded, then cause the screen to reload, which then draws and displays the data from the model. It works, but it is too clunky.
I have tried using a while loop to pause while the keyboard is visible, but this does nothing.
Has anyone any suggestions on how to pause the code until the user has finished entering data via the keyboard? I'm probably missing something extremely obvious.
Solved! Go to Solution.
2024-11-26 02:50 AM
Hi Funky
However, this is the problem. When the user presses <enter>, the keyboard disappears and the user is returned to the originating screen. At that point the data is in the keyboard buffer. There is no way to directly enter this into the text area, or transfer it to the model. Lines 14 onwards (by the way, not my actual code, just wishful thinking) have already been executed while the keyboard is displayed and the screen is sitting waiting for user input. 'Nothing' has helpfully been copied into the text field and also transferred to the model.
The only way is to transfer it to the model and get it returned in a screen refresh. However, adding a screen refresh at the end of the function in the first code example results in the screen displaying for only a brief moment. This is why I have taken the approach illustrated in the second code block.
It works, but it is not ideal.
What do I mean by 'the system moves on'? Not a programming term. But for a user. They click on a text box. A keyboard launches. They type in some characters and press <enter>. The text box is empty. In fact the screen is unresponsive and their only choice is to click the Home button. This is why all the examples you find online use buttons external to the keyboard for <enter> and <cancel> (ergonomically unsatisfactory). Maybe it is the only way and I am basically doing the same.
In the approach I use, I 'helpfully' add text saying 'Please select the text field' and they think 'Why couldn't I have done that in the first place and just typed it in?'
It's a user interface issue. I want them to be able to click on the text field, enter the data, press enter and there it is neatly displayed on-screen. The code can then propagate the text to the model for when the screen is reloaded later. There must be some way of doing it, but if the keyboard is not running in another RTOS task, then everything dies if the task takes a semaphore and waits for itself to give it. No more GUI.
Each screen currently transfers the keyboard buffer relevant to that screen's text fields to the model, so no issue there. It works.
2024-11-26 03:01 AM
Hmm
Maybe what I want is 'modeless'. I want to interrupt the workflow in the main window. I know everyone thinks I don't, but I am not interrupting the workflow of the rest of the system (I am using an RTOS), just the lines of code in this task that are meaningless until the keyboard buffer is filled.
Any ideas on how to achieve this in code?
2024-11-26 03:14 AM
@Kenbit wrote:I am not interrupting the workflow of the rest of the system (I am using an RTOS), just the lines of code in this task that are meaningless until the keyboard buffer is filled.
Surely that's just about handling the 'keyboard buffer is filled' event?
The task has a 'waiting for keyboard buffer to fill' state?
Just like any other state that waits on an event?
2024-11-26 03:31 AM
I'm not actually sure I tried this. I tried waiting while keyboard.isVisible() equal to true. The difficulty might be determining what 'full' is. Waiting while empty is futile, as one character would deem that to be false. Thanks, I'm not at my main computer at the moment, but will see if I can determine a means of assessing 'fullness'. I can't see anything in the keyboard class documents.
2024-11-26 04:04 AM
Hello @Kenbit ,
Ok, I see which one it is.
I have answered another question regarding this keyboard here .
He wanted to display '*' instead of the characters but keep the data entered by the user.
So we went for 2 buffers, a new one to save the data and the one provided in the original code to display the *.
I am still not sure what the issue is.
You want to be able to press the "V" button and save the string entered by the user?
In that case, is there anything blocking you from first sending/copying/printing the buffer and then deleting the keyboard?
Reading you question again, I do not understand this :
"However, lines 14 onwards are all executed while the keyboard is visible, so nothing is copied into the text area. I want this function to wait until the keyboard is cleared and the buffer contains the entered text. Waiting for the keyboard to clear and the buffer filled would not be an issue as the RTOS scheduler could switch to other tasks if needed. "
The keyboard example do not use textArea, so the textArea you are referring to must be the one you created yourself. But I do not understand why nothing would be copied, the keyboard being visible or not should not affect that.
I do not know what a semaphore would change, to me this is not part of the problem.
If you want to go in "modeless", it means that everything can be clicked right?
Because modal is when a sub windows open, only that windows can be clicked but you want the opposite.
So in your case, the window is the keyboard I guess.
TouchGFX is already in modeless. Because if you add a small widget in a big screen, all the other visible widgets can be interacted with.
So I think I still don't understand the issue. :grinning_face_with_sweat:
Regards,
2024-11-26 04:26 AM - edited 2024-11-26 04:26 AM
me neither.
i think one of the conceptual problems where you need to wrap your head arround is: there is no active waiting. there are no user do- while-for() loops in your gui code.
you just react to events . in this case: on every key onClicked() event you want to decide what to do.
for the keyboard it seems to be setKeyListener() where you can set a callback and then you will be notified on every keypress and can decide if it was the enter/exit button or just transfer the text already entered to the model. (but this only works if the addational keys are part of the keyboard)
if the two buttons are seperate buttons than handle it in their event onClick() handlers. so in the onClicked() handler of your ok button you can check if your requirements are met, propagate the text already entered to where ever you want, etc
but at the moment it seems like we are talking different languages ;)
2024-11-26 05:34 AM
Hello @Kenbit ,
I have made an example where I change the behavior of the CapsLock button to print the current text to the MainView.
You could do the same but instead of printing it to a textArea like I did, you could sent it to the model since this is something you were trying to achieve.
Once you have your data in the model, you can anything you want with it.
Regards,
2024-11-26 05:39 AM
Hi Gaetan
Yes, I want to copy the keyboard buffer into the textArea when the tick is pressed. However, in the first block of code I posted above this will not happen. I had initially assumed that when the keyboard is opened, the keyboard code will be executed, filling the buffer, until <enter> is pressed, at which point lines 14 to 16(?) copy the buffer into the text Area. However, this is not the case. The keyboard is opened, line 14 runs and this continues until the end of the function. Meanwhile the user is typing away. On pressing the tick they are returned to the screen, with the keyboard buffer full but with no instructions left to do anything with it.
The example code in the online demo uses two buttons external to the keyboard. When clicked, these either take the buffer and copy it into the textArea, or clear it. I am using an adaptation of this in my code. However, if you look at my workaround code in the second code block, you can see that it is a multi-step process. Click one button to open keyboard (the AddEdit function). enter text and press enter. Click on a flex button (the ?Edit1? function) to select the destination textArea. Finally reload screen to get text into textArea. I have to use a 320*240 display and a keyboard smaller than this is too small, so I cannot follow the demo example, with its on-main-screen buttons. I am starting to accept that my working version is as good as it gets.
I see a number of approaches.
I can live with the first option. The keyboard is heavily customised and is working perfectly, displaying up to 100 characters in a scrollable container on the keyboard 'display'. TextAreas on the sending screen are contained in draggable containers to allow scrolling. I am very impressed with the performance of the STM32F429; the scrolling is very fast.
But...
I am making users take multiple steps to achieve what should be a simple
I had hoped there would be a simple solution I was missing, some hidden C++ gem I had overlooked.
Can you suggest that gem?
Ken
2024-11-26 05:45 AM
Which keyboard are you using?
I used the keyboard example from TouchGFX Designer. Didn't you?
Regards,
2024-11-26 05:51 AM
maybe you are handling your input in the wrong place. in the onclicked() handler of the flexdatafieldinput() you only want to make visible/hide your keyboard. the handling of the input data should happen in the keyboard onClicked handler. There you know which keys were pressed and can do the proper actions. Update the model, check if enter or cancel was pressed etc