代码之家  ›  专栏  ›  技术社区  ›  remi

QT从QTableWidgetItem继承到小部件并覆盖“<”操作符

  •  3
  • remi  · 技术社区  · 7 年前

    我想要一个 QTableWidget 使用自定义的特定单元格 QProgressBar s、 我希望能够对包含这些内容的列进行排序。

    我的自定义 QProgressBar 从两者继承 QProgressBar QTableWidgetItem ,而我正在过度渲染 '<' 操作员允许排序。

    下面是一个自定义 QTableWidget ( QTableWidget_custom ),则, QTableWidgetItem ( QTableWidgetItem_double )以及 QProgressBar ( QProgressBar_custom )。填充表后,我只能对包含 QTableWidgetItem\u双精度 s

    QTableWidgetItem\u双精度

    class QTableWidgetItem_double : public QTableWidgetItem
    {    
    public:
       QTableWidgetItem_double(const double _d = 0.0) :QTableWidgetItem(){
          d = _d;
          this->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
          setText(QString::number(d, 'f', 4));
       }
    
       double d = 0.0;
    
       bool operator <(const QTableWidgetItem& other) const{
          QTableWidgetItem_double const *qtwd = dynamic_cast<QTableWidgetItem_double const *>(&other);
          return d < qtwd->d;
       }
    };
    

    QProgressBar\u自定义

    class QProgressBar_custom : public QProgressBar, public QTableWidgetItem
    {    
    public:
       QProgressBar_custom() : QProgressBar(){
          setTextVisible(true);
          setStyleSheet(" QProgressBar { border: 1px solid grey; border-radius: 0px; text-align: right;} QProgressBar::chunk { background-color: rgba(0,255,0,100); width: 1px;}");
          setAlignment(Qt::AlignCenter);
       }    
       QProgressBar_custom(const QString txt) : QTableWidgetItem(txt){}
    
       bool operator <(const QTableWidgetItem& other) const{
          QProgressBar const *p = dynamic_cast<QProgressBar const*>(&other);
          return value() < p->value();
       }
    
    private:
       double d1 = 0.0;
       double d2 = 0.0;
       QString txt1 = "";
       QString txt2 = "";    
    public:
       void setText(){
          QString txtfield = QString::number(d1, 'f', 2) + " " + txt1 + " \t" + QString::number(d2, 'f', 4) + " " + txt2 + " ";
          setFormat(txtfield);
       }    
       void setTxt1(const QString& txt){ txt1 = txt; }
       void setTxt2(const QString& txt){ txt2 = txt; }
       void setAmount1(double d){ d1 = d; }
       void setAmount2(double d){ d2 = d; }
       void setPercentage(double p){
          setValue(int(100.0*p));
          setText();
       }   
    };
    

    QTableWidget\u自定义

    class QTableWidget_custom : public QTableWidget
    {
    public:
       QTableWidget_custom(QWidget *parent) : QTableWidget(parent){}
    
       void addCustomProgressBarCell(int row, int col, double d1, double d2, const QString& txt1, const QString& txt2, double p){
          QProgressBar_custom* qprbar = new QProgressBar_custom();
          qprbar->setAmount1(d1);
          qprbar->setAmount2(d2);
          qprbar->setTxt1(txt1);
          qprbar->setTxt2(txt2);
          qprbar->setPercentage(p);
          setCellWidget(row, col, qprbar);
       }
       void addCustomDoubleCell(int row, int col, double d){
          QTableWidgetItem_double* qtwd = new QTableWidgetItem_double(d);
          setItem(row, col, qtwd);
       }
    };
    

    填充表格

    void QTWidgetTableItem::testCustomTableWidgetItem(){        
       //Some random data:
       double data1[10] = { 1.0, 2.0, 34.4, 32.02, 1000.0, 2002.0, 0.0001, 0.02, 0.009, 10.0 };
       double data2[10] = { -1.01, 22.3, 54.4, 1232.02, 0.0, -22.0, 0.1231, -0.02, 10.009, 5.0 };
       double data3[10] = { 5.0, 201.0, 434.4444, 32.32, 1234.231, 2002.232, 0.111, 0.0422, 0.212, -10.0 };
       double data4[10] = { 1.0, 2.0, 5.0, 25.00, 12.2, 100.0, 0.0, 50.0, 65.03, 0.9 };
       QString txt1[10] = { "abc", "abc", "abc", "eur", "usd", "php", "cpp", "xxx", "yyy", "zzz" };
       QString txt2[10] = { "aaa", "bbb", "ccc", "ddd", "asd", "qwe", "trt", "tr1", "tr2", "tr3" };
    
       //Prepare table:
       QTableWidget_custom* table = ui.tableWidget;
       table->insertColumn(0); table->setColumnWidth(0, 70);
       table->insertColumn(1); table->setColumnWidth(1, 70);
       table->insertColumn(2);   table->setColumnWidth(2, 170);
       table->setSortingEnabled(false);
    
       //Add data to table:
       for (int i = 0; i < 10; i++){
          table->insertRow(i);
    
          table->addCustomDoubleCell(i, 0, data1[i]);
          table->addCustomDoubleCell(i, 1, data2[i]);          
          table->addCustomProgressBarCell(i, 2, data3[i], data4[i], txt1[i], txt2[i], data4[i] / 100.0);
    
       }
       table->setSortingEnabled(true);    
    }
    

    后果

    Resulting table

    如果单击第1列或第2列的水平标题,则使用 QTableWidgetItem\u双精度 。如果我点击第三个标题,什么都不会发生。永远不会调用重载函数。

    2 回复  |  直到 7 年前
        1
  •  2
  •   eyllanesc Yonghwan Shin    7 年前

    只有 QTableWidgetItem 在订购时调用,在您的情况下 QProgressBar_custom 添加为 cellWidget s、 但不是 QTableWidgetItem s、 您必须按以下步骤执行:

    void addCustomProgressBarCell(int row, int col, double d1, double d2, const QString& txt1, const QString& txt2, double p){
        QProgressBar_custom *qprbar = new QProgressBar_custom;
        qprbar->setAmount1(d1);
        qprbar->setAmount2(d2);
        qprbar->setTxt1(txt1);
        qprbar->setTxt2(txt2);
        qprbar->setPercentage(p);
        setCellWidget(row, col, qprbar);
        setItem(row, col, qprbar); // add this line
    }
    

    enter image description here

        2
  •  1
  •   Kuba hasn't forgotten Monica    7 年前

    一些评论:

    • 如果有许多项,使用委托将比为每个项实例化小部件更有效。代表的 paint 方法可以使用 QStyle::drawControl 。稍后将提供完整的示例。它不是特别复杂,而且工作得很好。

    • 更喜欢 QString 为提高性能和可读性,将字符串格式化为串联。使用 QStringLiteral 而不是使用C字符串。

      auto const txtField = QStringLiteral("%1 %2 \t%3 %4 ")
                            .arg(d1, 'f', 2) .arg(txt1)
                            .arg(f2, 'f', 4) .arg(txt2);
      
    • 对于 QObject -派生类, qobject_cast 是另一种选择。为了使其健壮,并且不可能破坏表视图中的内部数据结构,比较运算符必须始终返回一致的结果(或者根本不返回结果,即断言):

      bool operator <(const QTableWidgetItem& other) const {
         auto const *p = qobject_cast<const QProgressBar*>(&other);
         if (true)
            // let's always succeed
            return p ? value() < p->value() 
                     : static_cast<const QTableWidgetItem*>(this) < &other;
         else {
            // catch errors
            Q_ASSERT(p);
            return value() < p->value();
         }
      }
      
    推荐文章