【问题标题】:Qt designer -- set style sheet -- hard coded now -- want to set programaticallyQt 设计器——设置样式表——现在硬编码——想以编程方式设置
【发布时间】:2017-04-27 19:41:28
【问题描述】:

我正在使用 Qt 设计器创建一组 32 个状态“灯”。我的灯是 QLabels。因此,将我的空白 Qlabel 初始化为具有黄色样式表,然后根据布尔数据的文本文件输入将每个灯设置为红色或绿色。我的问题是每次我都必须对其进行硬编码,因为设计器语法是 ui->color_0->setStyleSheet("background-color: rgb(0, 255, 0);");

color_0、color_1 等是 QLabel 对象。我想编写一个 for 循环并将循环增量器连接(附加)到颜色,但这不起作用,因为它不是 QLabel 类型。下面的代码,让我知道您将如何清理此代码并使其更高效。

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

} //结束按钮点击

【问题讨论】:

  • 为什么不直接创建一个带有 2 个参数 qlabel* 和 qcolor 的函数。
  • 我会不会遇到和以前一样的问题,我必须传递诸如 color_xxx 之类的对象???如果我在函数中需要它成为 QLabel,我不相信我可以传递一个 QString color_xxx。

标签: c++ qt qt-creator qt-designer


【解决方案1】:

您可以将标签的背景设置为调色板角色,然后通过调色板轻松操作它。例如,在每个标签上设置以下样式表:

"background-color: window"

然后您可以通过调色板设置标签的背景颜色:

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

您还可以按名称查找子小部件,避免重复代码以显式访问ui 成员的字段:

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

因此,您的两个大开关减少为:

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);
}

然后,从二进制字符串中获取:

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, ' ');
}

您不应通过消息向用户报告代码中的逻辑错误。请改用qWarning()

您也不必将字符串从QString 转换为QByteArray。没有意义。

【讨论】:

  • 这相当复杂。我正在尝试遵循您的逻辑,我想我得到了一般概念。你能给我解释一下这段代码吗? QWidget *getColor(int n) { return qobject_cast(findChild(QStringLiteral("color_%1").arg(n))); }
  • 这是一种通用方法。它避免了重复。这是最简单的方法,无需在每次更改背景时都强制重新解析新样式表。或者,您可以使用自定义 QWidget,它会更简单。
  • 它找到一个命名的子部件。 QStringLiteral 是它在盒子上写的:它是一个 QString 文字。正如"foo" 将是一个C 字符串文字。 QString 通过arg 方法提供内置格式。例如。 QStringLiteral("color_%1").arg(5) 的值与QString("color_5") 相同。然后调用QObject::findChild 来查找名为"color_5" 的第一个孩子。最后,孩子的类型从QObject* 转换为QWidget*
  • QStringLiteral(...) 的另一个优点是相关的字符串被标记为不是要进行翻译的内容 {cf tr(...) 包装器,其内容将 如果您应该声明 QT_NO_CAST_FROM_ASCIIQT_NO_CAST_TO_ASCII 以便编译器对每个原始字符串文字 {Qt 将其源文件视为 Utf-8 编码但如果它需要转换到/来自const char * 字符串存在可能发生错误的 8 位转换的危险} 您可以检测到需要放入一个或另一个包装器中的每个字符串!
【解决方案2】:

如果你愿意,你也可以有一个哈希表。这是一个示例,如果您想使用样式表而不是 kubas 答案。

#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);
}

【讨论】:

    【解决方案3】:

    在包含的小部件上设置单个样式表可能是最简单的,然后使用动态属性来打开或关闭每个小部件,如下所示:

    #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"
    

    请注意,我们必须重新抛光小部件以使其与属性的新值匹配 - 请参阅 changing stylesheet dynamically。此外,QSpinBox 仅限于有符号的 32 位值。

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2012-04-12
      • 1970-01-01
      • 2020-10-06
      • 2011-03-09
      • 2014-09-20
      • 1970-01-01
      • 2015-07-04
      相关资源
      最近更新 更多