Skip navigation.
Home
The QNX Community Portal

View topic - How to implement Progress bar

How to implement Progress bar

Isn't the name clear?

How to implement Progress bar

Postby hello » Mon Dec 24, 2012 7:55 am

Hi,
I am new to photon GUI programming. Could you please help me to get implement a progress bar. How to update the status of progress dynamically from program ? Please help.

Regards,
hello
hello
Senior Member
 
Posts: 101
Joined: Tue May 08, 2012 1:09 pm

Re: How to implement Progress bar

Postby sieudot » Mon Dec 24, 2012 9:02 am

You can create a ProgressBar widget and give it a name, ex: PtProgress1.

In your code, you can set it status by a value (it's minimum value is 0 and maximum is 100):

long i;
for (i=0;i<100;i++)
{
PtSetResource( ABW_PtProgress1, Pt_ARG_GAUGE_VALUE, i, 0);
PgFlush();
}
sieudot
Active Member
 
Posts: 45
Joined: Thu Mar 17, 2005 8:14 am
Location: VietNam

Re: How to implement Progress bar

Postby maschoen » Tue Dec 25, 2012 7:56 pm

sieudot wrote:You can create a ProgressBar widget and give it a name, ex: PtProgress1.

In your code, you can set it status by a value (it's minimum value is 0 and maximum is 100):

long i;
for (i=0;i<100;i++)
{
PtSetResource( ABW_PtProgress1, Pt_ARG_GAUGE_VALUE, i, 0);
PgFlush();
}


Yes, but this code will not work. It has two flaws. For starters, even if using PtSetResource() and PgFlush() could be used this way, you would only see the result of i=99, and nothing in between. You might think that putting a delay() in the loop would solve the problem, but it would not. After a delay of 100 x delay-amount you would again see the result of i=99. I'm stressing all this because it is confusing to the neophyte and fundamental to understanding how the Photon GUI API works.

For the most part, to see the screen updated, you have to return from your callback.

There is a way around this in QNX 6. Create a thread and use the following code:

void *mythread(void x)
{
int i;
int ret;

for(i=0;i<100;i++)
{
ret = PtEnter();
PtSetResource( ABW_PtProgress1, Pt_ARG_GAUGE_VALUE, i, 0);
PtLeave(ret);
delay(200);
}
return(NULL);
}

Having learned the hard way I recommend against this type of coding and using PtLeave() and PtEnter() except in very limited circumstances where the convenience justifies it. Unless you are very disciplined, you will get weird thread related crashes that can be difficult to debug. Instead I think it is better to signal the main thread by sending a message or a pulse, and have a callback in the main thread call PtSetResource(). This is much cleaner.

If the progress bar it to be updated periodically, then you can just use a timer.
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Re: How to implement Progress bar

Postby hello » Wed Dec 26, 2012 5:03 am

Thank you all.

Regards,
hello
hello
Senior Member
 
Posts: 101
Joined: Tue May 08, 2012 1:09 pm

Re: How to implement Progress bar

Postby _KB_ » Mon Jul 22, 2013 9:20 am

maschoen wrote:Having learned the hard way I recommend against this type of coding and using PtLeave() and PtEnter() except in very limited circumstances where the convenience justifies it. Unless you are very disciplined, you will get weird thread related crashes that can be difficult to debug. Instead I think it is better to signal the main thread by sending a message or a pulse, and have a callback in the main thread call PtSetResource(). This is much cleaner.


I am very interested in learning more about that if you don't mind.
In my application I have Two processes. One for general processing (we'll call it process A) and one for my photon GUI (process B).

Whenever the user hits a button from my GUI, I have a callback attached to the button which sends a pulse to a thread (in process B) dedicated to IPC. This thread MsgSend process A which MsgReply to it whith up to date data.

Then in the thread dedicated to IPC in process B, I do a PtEnter/PtLeave to refresh my GUI with new data.
It works fine so far but I have a case where Process A sends huge amount of data to Process B (1 or 2 seconds of processing). In this case my GUI is stuck.

I would like to follow your advice and to send a pulse from my thread dedicated to IPC, to the main thread (I assume the one which has launched PtMainLoop). But I don't know where to start. How do I add a callback in main thread ? And what kind of callback? And how do I receive pulses in the main thread ?
A small guideline would be great :P

Thanks a lot.

KB.
_KB_
Active Member
 
Posts: 24
Joined: Mon Oct 15, 2012 6:36 pm

Re: How to implement Progress bar

Postby hello » Tue Jul 23, 2013 3:58 am

GUI can be stuck if PtEnter()/PtLeave() is not handled properly. So ensure that you check the return of PtEnter().

int s32_eval = 0;
s32_eval = PtEnter(0);
if ((s32_eval >= 0) || (s32_eval == -EDEADLK))
{
/* Do action on PtEnter */

if (s32_eval >= 0)
{
PtLeave(s32_eval);
}
}
hello
Senior Member
 
Posts: 101
Joined: Tue May 08, 2012 1:09 pm

Re: How to implement Progress bar

Postby _KB_ » Tue Jul 23, 2013 8:07 am

Thanks for the tip but I've already performed that check.
When I said that my GUI was stuck, I mean during the time elapsed to respond. In the case an operation takes few seconds, the user can't play with the GUI anymore unless the operation is over.

maschoen proposes to let the main thread do the job instead.

I think he means to use an input handler but I'm a little confuse with that.

In my application the GUI sends cookie to the server process with the event encapsulated. The server then periodically delivers events to GUI. This was done in another thread in my Photon application. I tried to adapts this mechanism with an input handler.
The server still receives the cookie from the client (GUI), but I never enter the input handler.

Code: Select all
int lchidPulse = -1;
int lcoidServer = -1;

int
msg_handler( void *data, int rcvid,
             void *message, size_t size)
{
printf("ack\n");

    return( Pt_CONTINUE );
}


  //int (*p)(void *, int, void *, size_t) = msg_handler;
int InitPhotonGui(int argc, char *argv[])

{

  /* eliminate 'unreferenced' warnings */
  argc = argc, argv = argv;


#if 1
  int status;
  int lchidPulse = -1;
  int lcoidServer = -1;

  /** Create a channel-connection link within this process, to receive messages
   */
  status = CreateChannelConnectionLink(&lchidPulse, &gcoidPulseGui);

  if (status == OK) {
    /** Try to reach the server and retry every second
     */
    WaitForServerAndConnect(PROCESSING_CHANNEL_NAME, &lcoidServer);
    /** Send to the server a cookie event for asynchronous message passing
     */
    status
        = SendPulseCookieToServer(lcoidServer, gcoidPulseGui, MSG_COOKIE_GUI);

    PtAppAddInput(NULL, 0, msg_handler, NULL);
  }
#endif
  return (Pt_CONTINUE);

}

int WaitForServerAndConnect(const char *srv_name, int *srv_coid) {
  /** find the server */
  *srv_coid = name_open(srv_name, 0);
  while (*srv_coid == -1) {
    perror("WaitForServerAndConnect: name_open");
    fprintf(stderr, "Retry in 1 second...\n");
    sleep(1); /* wait 1s before trying a reconnection */
    *srv_coid = name_open(srv_name, 0);
  }
  printf("WaitForServerAndConnect: server has been found!\n");
  return (OK);
}

int CreateChannelConnectionLink(int *chid, int *coid){
  /** Create a channel for communication between Photon app and this thread (pulses)
   */
  *chid = ChannelCreate(0);
  /** Check for errors while creating the channel
   */
  if (*chid == -1) {
    perror("CreateChannelConnectionLinkForPulses: ChannelCreate");
    return (ERROR);
  } else {
    *coid = ConnectAttach(ND_LOCAL_NODE, getpid(), *chid,
        _NTO_SIDE_CHANNEL, 0);
    if (*coid == -1) {
      perror("CreateChannelConnectionLinkForPulses: ConnectAttach");
      return (ERROR);
    }
  }
  return (OK);
}


InitPhotonGui function is placed in an AppBuilder Init function.
I miss something here. My initial thread from client-side had a thread which was received block. Now I have an input handler instead. How is it suppose to work ? I never had a chance to enter my input handler and print in the standard output "ack"
Still, the server sends events to the client every seconds.

What am I missing here ?

Thanks.
_KB_
Active Member
 
Posts: 24
Joined: Mon Oct 15, 2012 6:36 pm

Re: How to implement Progress bar

Postby maschoen » Tue Jul 23, 2013 1:27 pm

Whenever the user hits a button from my GUI, I have a callback attached to the button which sends a pulse to a thread (in process B) dedicated to IPC. This thread MsgSend process A which MsgReply to it whith up to date data.

Then in the thread dedicated to IPC in process B, I do a PtEnter/PtLeave to refresh my GUI with new data.
It works fine so far but I have a case where Process A sends huge amount of data to Process B (1 or 2 seconds of processing). In this case my GUI is stuck.


Why do you need a second thread in Process B to do the MsgSend() to Process A? Is the response slow?

I would like to follow your advice and to send a pulse from my thread dedicated to IPC, to the main thread (I assume the one which has launched PtMainLoop). But I don't know where to start.


Try looking through the manual or the Help viewer for a Pt...() routine that attaches a callback to a specific message. The pulse looks like a message, but you don't need to reply to it.
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Re: How to implement Progress bar

Postby maschoen » Tue Jul 23, 2013 1:29 pm

_KB_ wrote:Thanks for the tip but I've already performed that check.
maschoen proposes to let the main thread do the job instead.

I think he means to use an input handler but I'm a little confuse with that.


What are you confused about?
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Re: How to implement Progress bar

Postby _KB_ » Tue Jul 23, 2013 1:49 pm

maschoen wrote:Why do you need a second thread in Process B to do the MsgSend() to Process A? Is the response slow?


The response is not slow but I did this to regroup message passing between server and client into one single thread, just in case the process is send blocked...

maschoen wrote:What are you confused about?


Can you have a look at the code I've posted above and tell me what am I doing wrong ?
Process A delivers event every seconds to B, but I'm not entering my input handler whereas with my previous architecture (a thread which waits for events or pulses and msgsend to server, it works like a charm)

Thanks for the support !
_KB_
Active Member
 
Posts: 24
Joined: Mon Oct 15, 2012 6:36 pm

Re: How to implement Progress bar

Postby maschoen » Tue Jul 23, 2013 5:18 pm

_KB_ wrote:The response is not slow but I did this to regroup message passing between server and client into one single thread, just in case the process is send blocked...


maschoen wrote:What are you confused about?


I can't really respond in a helpful way here. The server should be written so that it will not block the client. Once that is done you can put the MsgSend back in the main thread where it belongs. That solves the problem.

Can you have a look at the code I've posted above and tell me what am I doing wrong ?


I looked at the code. It seems very confused, incomplete and unrelated to the issue at hand.
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Re: How to implement Progress bar

Postby _KB_ » Wed Jul 24, 2013 7:01 am

maschoen wrote:I can't really respond in a helpful way here. The server should be written so that it will not block the client. Once that is done you can put the MsgSend back in the main thread where it belongs. That solves the problem.


I suppose I wrote it that way as the server has a thread which is received block until a client msgsend to it
For the moment the client msgsend from a thread apart from the main thread (this thread waits for a pulse which is sent from any callback in photon). In addition to this the server deliver an event to the client to signal that data processing are up to date. The same thread in the client, receive the event and refresh the GUI (with PtEnter/PtLeave).
You say that I can put the MsgSend back in the main thread where it belongs. My question is, how can I do that (apart to send within a callback) ? And furthermore, how can I receive events from the server in the main thread...

I figure that an input handler will do the job but it seems that i'm off topic that's why my code seems confused (if this not the reason just tell me why in order to improve myself).

Maybe if you can just point out the paragraph in the documention which is related to the issue... It will help a lot!

Thanks maschoen for your time!
_KB_
Active Member
 
Posts: 24
Joined: Mon Oct 15, 2012 6:36 pm

Re: How to implement Progress bar

Postby maschoen » Thu Jul 25, 2013 6:05 pm

For the moment the client msgsend from a thread apart from the main thread (this thread waits for a pulse which is sent from any callback in photon).


I see no reason for using pulses here

In addition to this the server deliver an event to the client to signal that data processing are up to date.


I don't know what you mean by an event here? Do you mean a signal? This is not necessary.

The same thread in the client, receive the event and refresh the GUI (with PtEnter/PtLeave).


This is the issue I told you in the first reply to avoid. You only need PtEnter/PtLeave because you are running in a separate thread, which you DON'T need to do.

You say that I can put the MsgSend back in the main thread where it belongs. My question is, how can I do that (apart to send within a callback) ?


Yes, that is what I mean, put the MsgSend() in the callback that is called when the user presses the button. Since the Server will not block (for very long), your GUI should not block either.

And furthermore, how can I receive events from the server in the main thread...


Well you've lost me here. This has nothing to do with events of the Photon kind, eg mouse events, keyboard events etc. Here, once more, as clearly as I can:

User presses button
Photon Callback is called (main thread)
Message sent to Server (main thread), GUI is blocked
Server Reply's response, GUI is unblocked
Update screen with PtSetResource()

If you want some other program to send updates to the GUI program, look at PtAddInput();

Maybe if you can just point out the paragraph in the documention which is related to the issue... It will help a lot!


PtAppAddInput()
Add an input processing function
Description:
This routine adds a function to a PtMainLoop() input-event processing chain.
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Re: How to implement Progress bar

Postby _KB_ » Fri Jul 26, 2013 9:41 am

First I would like to thank you again for your time.
With your last answer I can see that there was a misunderstanding. I'm aware that my english could be confused and it could explain a lot :|

I understand that I have to avoid pulses to a thread and to use Ptenter/ptLeave. This is is a good point and I will correct this part.

However:

maschoen wrote:
And furthermore, how can I receive events from the server in the main thread...


Well you've lost me here. This has nothing to do with events of the Photon kind, eg mouse events, keyboard events etc.


Yes you're right it has nothing to do with events of the Photon kind. My server process updates data and delivers an event (which is a pulse but server does not know which kind of event it sends to the client, as the cliend first sends a "cookie" whith the type of event it wants to receive, but this is off topic here :mrgreen: )

maschoen wrote:If you want some other program to send updates to the GUI program, look at PtAddInput();


This is exactly what I want and I've post earlier a snippet of code with this function (see above).
But I suppose that because of my architecture (with the cookie and so on) I'm missing something. I know that the code I've posted is incomplete (the function basically do a printf), but I never get a chance to receive an event from the server (whatever event) and print into the console something.

Anyway I'll look into it, you confirm that this is the right function for my purpose !

To conclude ... :twisted:

For the moment my separate thread does the job. It receives pulses from the server to signal that new data are available. It MsgSend to the server and PtEnter/PtLeave to refresh the GUI.

My only problem here (which is not related to message passing) is that I have a MultiText to update with 1000 events (approx. 60 characters for each events) and it takes a long time to refresh the GUI (1 or 2 seconds). So when I do a PtEnter/PtLeave for this my GUI does not respond to user's commands during this short period of time.

I have another problem with this MultiText which is not related to message passing. I have a button to mask/unmask my events (basically it realizes or unrealizes the widget). When the widget contains all the events, It takes almost two seconds to realize it and my GUI is blocked during this time :x

Anyway thanks for the good advices.

KB
_KB_
Active Member
 
Posts: 24
Joined: Mon Oct 15, 2012 6:36 pm

Re: How to implement Progress bar

Postby maschoen » Mon Jul 29, 2013 6:48 am

_KB_ wrote:My only problem here (which is not related to message passing) is that I have a MultiText to update with 1000 events (approx. 60 characters for each events) and it takes a long time to refresh the GUI (1 or 2 seconds). So when I do a PtEnter/PtLeave for this my GUI does not respond to user's commands during this short period of time.


Have you considered the possibility that with your current processor, rendering 60,000 characters from a font might just take 1-2 seconds. Maybe you need a strategy for displaying the 60,000 characters other than just throwing them into a MultiText?
maschoen
QNX Master
 
Posts: 2640
Joined: Wed Jun 25, 2003 5:18 pm

Next

Return to GUI Programming

Who is online

Users browsing this forum: No registered users and 2 guests

cron