0
votes

I am using Qt designer to create a set of 32 status "lights." My lights are QLabels. So initialize my blank Qlabel to have a yellow style sheet and then i set each light to red or green based upon the text file input of Boolean data. My problem is that each time I have to hard code it because the designer syntax is ui->color_0->setStyleSheet("background-color: rgb(0, 255, 0);");

color_0, color_1, etc are QLabel objects. I wanted to write a for loop and concatenate (append) the loop incrementer to color but that does not work because it will not be of type QLabel. Code below, let me know how you would clean up this code and make it more efficient.

void static2::on_pushButtonNext_clicked()
{
if (incrementer == 0)
{
    int tot_size = text.size();
    const char *str;  
    QByteArray array; //http://www.qtcentre.org/threads/22711-Converting-QString-to-char-array
    array = text.toLatin1();
    str = array.data();
}

//write an if statement here that prevents from running past the total stream. run if less than num_events_dec to end.
if (incrementer*num_events_dec <= tot_size - num_events_dec)
{
    incrementer++;
    ui->lcdNumber->display(incrementer);  //updates display

    int step = (incrementer-1)*num_events_dec; //this is the code that goes bit by bit on the stream
    for (int i = step; i < step+num_events_dec; i++){

        //PLACE COLOR SETTING COMMANDS HERE
        //http://stackoverflow.com/questions/2749798/qlabel-set-color-of-text-and-background
        //http://www.qtcentre.org/archive/index.php/t-5944.html

        if (str[i] == '1'){
            //make label background green

            //qDebug() << "high";

            //QLabel* color = new QLabel; //[num_events_dec]; //allocates an array of objects called color which is of the user specified size

            /*QString color = "color_" + QString::number(i);
            qDebug() << i;
            qDebug() << color;
             */

            /* As of right now i have string values that are of the proper name
             * I need those same names as Qlabels in order for ui->xxx to recognize them
             * The class mainwindow has an object ui which has an object called color_[i]
             */

            //ui->color->setStyleSheet("background-color: rgb(0, 255, 0);");
            switch (i-step){
            case 0: ui->color_0->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 1: ui->color_1->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 2: ui->color_2->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 3: ui->color_3->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 4: ui->color_4->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 5: ui->color_5->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 6: ui->color_6->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 7: ui->color_7->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 8: ui->color_8->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 9: ui->color_9->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 10: ui->color_10->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 11: ui->color_11->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 12: ui->color_12->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 13: ui->color_13->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 14: ui->color_14->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 15: ui->color_15->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 16: ui->color_16->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 17: ui->color_17->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 18: ui->color_18->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 19: ui->color_19->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 20: ui->color_20->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 21: ui->color_21->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 22: ui->color_22->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 23: ui->color_23->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 24: ui->color_24->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 25: ui->color_25->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 26: ui->color_26->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 27: ui->color_27->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 28: ui->color_28->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 29: ui->color_29->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 30: ui->color_30->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            case 31: ui->color_31->setStyleSheet("background-color: rgb(0, 255, 0);"); break;
            } //end switch case
         } //end if

        else if (str[i] == '0'){
            //make label background red

            //qDebug() << "low";

            switch (i-step){
            case 0: ui->color_0->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 1: ui->color_1->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 2: ui->color_2->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 3: ui->color_3->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 4: ui->color_4->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 5: ui->color_5->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 6: ui->color_6->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 7: ui->color_7->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 8: ui->color_8->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 9: ui->color_9->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 10: ui->color_10->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 11: ui->color_11->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 12: ui->color_12->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 13: ui->color_13->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 14: ui->color_14->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 15: ui->color_15->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 16: ui->color_16->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 17: ui->color_17->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 18: ui->color_18->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 19: ui->color_19->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 20: ui->color_20->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 21: ui->color_21->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 22: ui->color_22->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 23: ui->color_23->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 24: ui->color_24->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 25: ui->color_25->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 26: ui->color_26->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 27: ui->color_27->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 28: ui->color_28->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 29: ui->color_29->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 30: ui->color_30->setStyleSheet("background-color: rgb(255, 0, 0);"); break;
            case 31: ui->color_31->setStyleSheet("background-color: rgb(255, 0, 0);"); break;

            } //end switch case

        } //end else if

        else {
            QMessageBox::warning(this,"Error", "A non-binary number has been read -- Check input stream");

        } //end else
    } //end for loop
} //end if

else  //dont allow to increment
{
    QMessageBox::warning(this,"Error", "Stream Ended, No more data to view");
} //end else

} //end push button click

3
why not just create a function that takes 2 parameters qlabel* and qcolor.rafael gonzalez
Will i not run into the same exact problem as before where i have to pass it objects such as color_xxx??? I do not believe I can pass a QString color_xxx if i need it to be a QLabel once I am in the function.mjordan290

3 Answers

1
votes

You could set the label's background to a palette role, and then easily manipulate it via the palette. E.g set the following stylesheet on each label:

"background-color: window"

You can then set the background color for the label via the palette:

void MyWidget::setColor(QWidget *w, const QColor &c) {
  pal = w->palette();
  pal.setBrush(QPalette::Window, {c});
  w->setPalette(pal);
}

You can also find the child widgets by name, obviating the repetitive code to explicitly access the fields of the ui member:

QWidget *MyWidget::getColor(int n) {
  return qobject_cast<QWidget*>(findChild(QStringLiteral("color_%1").arg(n)));
}

Thus, your two big switches reduce to:

void MyWidget::setColorState(int n, QChar c) {
  auto widget = getColor(n);
  if (!widget) return;
  setColor(widget, c == QLatin1Char('1') ? Qt::green :
                   c == QLatin1Char('0') ? Qt::red : 
                                           Qt::black);
}

Then, to get those from a binary string:

void MyWidget::setColors(const QString &str) {
  int i = 0;
  for (i < str.length() && i < 32; ++i) {
    if (str[i] != QLatin1Char('1') && str[i] != QLatin1Char('0'))
      qWarning() << "str contains non-binary digit:" << str;
    setColorState(i, str[i]);
  }
  for (i < 32; ++i)
    setColorState(i, ' ');
}

You shouldn't report logic errors in your code to the user via messages. Use qWarning() instead.

You also don't have to convert the string from QString to QByteArray. It's pointless.

0
votes

you could have a hash table also if you wanted to. here is an example if you want to use stylesheets instead of kubas answer.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLabel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void customize(QLabel* label,QString color);

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::MainWindow *ui;
    QHash<int,QLabel*> hash;
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    hash[1] = ui->label_1;
    hash[2] = ui->label_2;
    hash[3] = ui->label_3;

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::customize(QLabel *label, QString color)
{
    QString colorstring("background-color:");
    colorstring.append(color);
    colorstring.append(";");
    label->setStyleSheet(colorstring);
}


void MainWindow::on_pushButton_clicked()
{
    QString color("rgb(255,0,0)");
    customize(hash[1],color);
}

void MainWindow::on_pushButton_2_clicked()
{
    QString color("rgb(0,255,0)");
    customize(hash[1],color);
}
0
votes

It's probably easiest to set a single stylesheet on the containing widget, and then use a dynamic property to switch each widget on or off, like this:

#include <QApplication>
#include <QBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QStyle>
#include <QWidget>

#include <array>

class BinaryIndicator : public QWidget
{
    Q_OBJECT
    Q_DISABLE_COPY(BinaryIndicator)

    std::array<QLabel*, 32> labels;

public:
    BinaryIndicator(QWidget *parent = nullptr)
        : QWidget(parent)
    {
        setStyleSheet("QLabel[state='on']  { background-color: red; }"
                      "QLabel[state='off'] { background-color: green; }");

        auto layout = new QHBoxLayout();
        for (auto& l: labels) {
            l = new QLabel(this);
            layout->addWidget(l);
        }
        setLayout(layout);
        setValue(0);
    }

public slots:
    void setValue(uint32_t value)
    {
        int i = 32;
        for (auto *label: labels) {
            label->setProperty("state", value & 1<<--i ? "on" : "off");
            // we need to re-polish the widget to pick up the changed
            // style selector
            label->style()->unpolish(label);
            label->style()->polish(label);
        }
    }
};  

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QWidget w;
    auto layout = new QVBoxLayout();
    w.setLayout(layout);
    auto indicator = new BinaryIndicator(&w);
    layout->addWidget(indicator);
    auto spinbox = new QSpinBox(&w);
    spinbox->setRange(0, 0x7fffffff);
    layout->addWidget(spinbox);
    QObject::connect<void(QSpinBox::*)(int)>(spinbox, &QSpinBox::valueChanged, indicator, &BinaryIndicator::setValue);
    w.show();
    app.exec();
}

#include "41109349_moc.cpp"

Note that we must re-polish the widget to make it match against the new value of the property - see changing stylesheet dynamically. Also, the QSpinBox is limited to signed 32-bit values.