Qt World Summit: Register Today!

Advice needed on custom buttons with different states and other special behavior.

  • Hello all.

    I am new to Qt and I'm in need of some guidance.

    The application that I'm working on will interface with some analog sensors, ie. luminosity, temperature, proximity, speed. Based on the sensor output, I need to have a few different states for buttons in the GUI.

    For example button "Speed" should be gray for all reported speeds under 50, however as soon as the value goes above 50, the button should change color to red. In addition the label of that button should be able to show the speed as reported by the sensor in real time for all speeds, ie: "Speed: 24 rpm".

    I tried playing around with ui forms, however it seems that I won't be able to achieve that behavior with the widgets available in Designer.

    So what exactly are my options? Based on my research I think there are only two:

    1. Coding the entire GUI and using algorithms and program logic to enable the display of different button states.
    2. Creating some custom widget, basically some extended QPushButton class that would implement the features that I need.

    What are your thoughts?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Can you explain why a QPushButton ?

  • This post is deleted!

  • @SGaist said in Advice needed on custom buttons with different states and other special behavior.:

    Hi and welcome to devnet,

    Can you explain why a QPushButton ?


    For every button, I need to be able click on it to open a new popup window with some additional detail for each of the sensor outputs.

    Like I said, I'm new to Qt, so not even sure if QPushButton is the best, or even a viable approach to this problem.


  • Lifetime Qt Champion

    It looks like you should rather have controls matching the sensors you want to monitor (for example look at Qwt and provide a button for showing additional informations.

  • @SGaist Thanks for the suggestion, unfortunately that won't work. The button is defined in software requirements, so I have to develop it according to that specification.

    So basically, I need to have sensor value displayed on top of a color changing button...

  • You can subclass QPushButton or even QAbstractButton base class and draw anything you want in the paintEvent() method.

    Look at the primitive drawing mehods of QPainter along with QPainterPath and QGradient.

    Basic Drawing Example

  • @parameter2
    Food for thought:
    I probably would implement via QPushButton, and follow @mpergand's advice to paint as desired.

    However, you don't have to use QPushButton just for functionality of your "click". Every widget has QWidget::mousePress/ReleaseEvent which can easily be used to recognise "click", so for example you could use a QLabel to get more control over what text/background/color etc. you want to show if QPushButton lacks, without necessarily going down the "paint" road if you don't fancy that....

  • Thank you all for suggestions. I would like to extend my original question without creating new topic.

    I need to provide near real time updates to my sensor data which is displayed in GUI. Assuming that the data is constantly written to a text file from another program, what would be the best approach to reading in that data and then updating various GUI elements? So far I read about QThread, but it seems that I won't be able to access GUI if I process all the data in a worker thread and try to modify my GUI from that process. Please give me some suggestions and short examples if possible.

  • @parameter2
    Well, your latest question is so different from the original topic title that it would be better as a new topic, but hey-ho.

    Some conceptuals:

    • Is your data arriving/needing to update the UI once per second or a million times per second? There's a big difference!

    • It's not ideal that the data is written to a file (rather than, say, a pipe), but there you are.

    • You'd better make sure that the other process is flushing its output to file immediately, else you won't see the data till it does!

    • I assume QIODevice::readyRead() gets emitted when new data is written to the file, even if you have previously read it to end. So that is what you want to attach your slot to. If not, there is https://doc.qt.io/qt-5/qfilesystemwatcher.html#fileChanged which says "This signal is emitted when the file at the specified path is modified", but you's have to check that happens every time new data is appended, and I don't know whether it imposes an efficiency overhead.

    • You could do the reading in another thread, and send signals to your UI when new data received. The main UI thread must do the UI updating.

    • However, assuming you use one of the signals I mentioned above you do not need a separate thread. You could do it the main UI, which will remain responsive since these are signals/slots, not blocking reads.

    • In either case, you will need to look at how many events arrive and how long it takes to update the UI. If there are many/long to update, your UI could become unresponsive or you could fail to keep up with the new data. In that case you might either need to thin the data/skip some items, or you might introduce a QTimer which picks up a certain, limited number of pending data updates and updates the UI with them, so as to keep responsive.

  • @JonB
    Let me backtrack a little bit.

    The other program is basically receiving messages over the network and saving them to a file. Upon checking the specification, it gets new message with data every 200ms, so it looks like my GUI should only be updated at most 5 times per second, which doesn't seem too bad. Not sure how difficult it is to do networking in Qt but perhaps my GUI application could process the messages directly skipping the whole file reading / writing.

  • Lifetime Qt Champion

    There's a whole Qt module dedicated to networking :-)

    Can you describe how the network related part is currently working ?

Log in to reply