How to data-bind a label text to an underlying object's property?

江枫思渺然 提交于 2019-12-11 13:55:21

问题


We're building a Qt4.8/C++ application (no QML) that will run on an embedded ARM device. This device constantly receives values of a lot of datapoints that need to be held in an object. Now I want to bind UI elements to specific properties of this model object in order to automatically always show the current and up-to-date values in the UI.

Is there a mechanism in Qt that I can use? Or do I have to keep track of any changes and manually update the UI? It would be great if someone could give me a very basic example on how to, for example, data-bind a label text to a double value property of an object. Thanks in advance!


回答1:


Here is my solution. Let's assume you have some data receiver class and identifiers for your data sources:

enum SourceIds
{
    SourceCamera,
    SourcePort,
    SourceMagic
}

class DataReceiver : public QObject
{
    Q_OBJECT

public:
    DataReceiver(QObject *parent = 0);

    void updateValue(int sourceId, const QVariant &value);

signals:
    void valueChanged(int sourceId, const QVariant &newValue);

private:
    QHash<int, QVariant> data;
};

void DataReceiver::updateValue(int sourceId, const QVariant &value)
{
    QVariant oldValue = data.value(sourceId);

    data[sourceId] = value;

    if (oldValue != value)
    {
        emit valueChanged(sourceId, value);
    }
}

Then you can create a data mapper class that will listen to your receiver valueChanged signal:

class DataMapper : public QObject
{
    Q_OBJECT

public:
    DataMapper(QObject *parent = 0);
    void registerLabel(int sourceId, QLabel *label);

public slots:
    void updateLabel(int sourceId, const QVariant &value);

private:
    QHash<int, QLabel*> labels;
};

void DataMapper::registerLabel(int sourceId, QLabel *label)
{
   labels[sourceId] = label;
}

void DataMapper::updateLabel(int sourceId, const QVariant &value)
{
   QLabel *label = labels.value(sourceId, NULL);
   if (label != NULL)
   {
       label->setText(value.toString());
   }
}

You create a receiver and a mapper objects and connect them:

DataReceiver *receiver = new DataReceiver;

QLabel *cameraLabel = new QLabel;
QLabel *portLabel = new QLabel;
QLabel *magicLabel = new QLabel;

DataMapper *mapper = new DataMapper;
mapper->registerLabel(SourceCamera, cameraLabel);
mapper->registerLabel(SourcePort, portLabel);
mapper->registerLabel(SourceMagic, magicLabel);

connect(receiver, SIGNAL(valueChanged(int, QVariant)), mapper, SLOT(updateLabel(int, QVariant)));

I hope this will be usefull for you.




回答2:


You might want to use Qt signal/slot mechanism, if you are not concerned with performance. I an example sketch would be:

class MyModel: public QObject
{
    Q_OBJECT
public:
    void setElement(int newValue);
signals:
    void elementUpdated(int newValue);
private:
    int element;
}

void MyModel::setElement(int newValue)
{
    element = newValue;
    emit elementUpdated(newValue);
}

Then you can connect this signal to a slot on you QMainWindow and update the corresponding label in it.

If the number of updates is more than a few per second, perhaps it is better to look at the problem backwards: Instead of changing QLabel text on every update, use a QTimer to update the QLabel text on a periodic interval.



来源:https://stackoverflow.com/questions/21091229/how-to-data-bind-a-label-text-to-an-underlying-objects-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!