改写ui-grid headerCellTemplate

本文介绍如何通过修改 UI Grid 的头部单元格模板实现自定义显示效果,并加入信任 HTML 过滤器确保安全呈现富文本内容。
改写ui-grid headerCellTemplate  myHeaderCellTemplate  中为uigrid表头模板,
此处copy过来,改写           

/**改写ui-grid myHeaderCellTemplate,注意必须增加 trustHtml过滤器(在模块中增加)
* 取代原有的 CUSTOM_FILTERS ***
     * myApp.filter('trustHtml', function ($sce) {
     *      return function (input) { 
     *          return $sce.trustAsHtml(input);
     *      }
     *  }); 
     * **/
    //原:<span class="ui-grid-header-cell-label" ui-grid-one-bind-id-grid="col.uid + '-header-text'"> {{ col.displayName CUSTOM_FILTERS }}</span>
    //现:<span class="ui-grid-header-cell-label" ui-grid-one-bind-id-grid="col.uid + '-header-text'" ng-bind-html="col.displayName | trustHtml"></span>
    var myHeaderCellTemplate =`<div role="columnheader" ng-class="{ 'sortable': sortable }"
        ui-grid-one-bind-aria-labelledby-grid="col.uid + '-header-text ' + col.uid + '-sortdir-text'"
        aria-sort="{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}">
        <div role="button" tabindex="0" class="ui-grid-cell-contents ui-grid-header-cell-primary-focus"
            col-index="renderIndex" title="TOOLTIP">
            <span class="ui-grid-header-cell-label" ui-grid-one-bind-id-grid="col.uid + '-header-text'" ng-bind-html="col.displayName | trustHtml">         
            </span> 
            <span ui-grid-one-bind-id-grid="col.uid + '-sortdir-text'"
            ui-grid-visible="col.sort.direction" aria-label="{{getSortDirectionAriaLabel()}}">
            <i ng-class="{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }"
            title="{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}"
            aria-hidden="true">
            </i>
            <sub ui-grid-visible="isSortPriorityVisible()" class="ui-grid-sort-priority-number">
                {{col.sort.priority + 1}}
            </sub>
            </span>
        </div> 
     <div role="button" tabindex="0" ui-grid-one-bind-id-grid="col.uid + '-menu-button'"
         class="ui-grid-column-menu-button"
         ng-if="grid.options.enableColumnMenus && !col.isRowHeader
&& col.colDef.enableColumnMenu !== false"
         ng-click="toggleMenu($event)"
         ng-class="{'ui-grid-column-menu-button-last-col': isLastCol}"
         ui-grid-one-bind-aria-label="i18n.headerCell.aria.columnMenuButtonLabel"
         aria-haspopup="true">
         <i class="ui-grid-icon-angle-down" aria-hidden="true">
          
        </i>
    </div> 
</div>`;
 function rebuildColumnDefs(data){
   var columnDefs = []; 
      if(data && data.length){
         data.forEach(function(val,idx){
           columnDefs.push({
                name: val.data,
                displayName: val.title, 
                minWidth: 150, 
           //headerCellTemplate: '<div class="">Name \n (editable)</div>'
//这种方式会改变表头样式和相关功能,只能在极其简单情况下使用
  //headerCellTemplate: '<div style="text-align:center;">'+val.title+'</div>'
               headerCellTemplate:myHeaderCellTemplate 
          });
      }); 
    }
    return columnDefs;
  }

void KeySelfSet::on_cBox_muteKey_currentIndexChanged(int index) { for(int i = 0; i < 8; ++i) { ui->cBox_muteAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_playAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); } if(index == ui->cBox_playKey->currentIndex()) { ui->cBox_muteAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_playAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(index == ui->cBox_EQKey->currentIndex()) { ui->cBox_muteAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(ui->cBox_playKey->currentIndex() == ui->cBox_EQKey->currentIndex()) { ui->cBox_playAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } } void KeySelfSet::on_cBox_playKey_currentIndexChanged(int index) { for(int i = 0; i < 8; ++i) { ui->cBox_muteAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_playAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); } if(index == ui->cBox_muteKey->currentIndex()) { ui->cBox_playAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_muteAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(index == ui->cBox_EQKey->currentIndex()) { ui->cBox_playAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(ui->cBox_muteKey->currentIndex() == ui->cBox_EQKey->currentIndex()) { ui->cBox_muteAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } } void KeySelfSet::on_cBox_EQKey_currentIndexChanged(int index) { for(int i = 0; i < 8; ++i) { ui->cBox_muteAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_playAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); ui->cBox_EQAct->setItemData(i, QVariant(-1), Qt::UserRole - 1); } if(index == ui->cBox_playKey->currentIndex()) { ui->cBox_EQAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_playAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(index == ui->cBox_muteKey->currentIndex()) { ui->cBox_EQAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_muteAct->setItemData(ui->cBox_EQAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } if(ui->cBox_playKey->currentIndex() == ui->cBox_muteKey->currentIndex()) { ui->cBox_playAct->setItemData(ui->cBox_muteAct->currentIndex(), QVariant(0), Qt::UserRole - 1); ui->cBox_muteAct->setItemData(ui->cBox_playAct->currentIndex(), QVariant(0), Qt::UserRole - 1); } } 简写
最新发布
09-26
<think> 我们有三段类似的代码,分别对应三个不同的QComboBox的currentIndexChanged信号处理函数。 这些函数的结构非常相似,只是操作的配置项不同。我们可以考虑将它们合并为一个函数,通过传递参数来区分不同的配置项。 但是,由于Qt的信号槽机制,当我们连接信号时,信号会传递当前索引(int类型),而我们需要知道是哪个ComboBox发出的信号。 一种方法是使用QSignalMapper,但在Qt5中,更推荐使用lambda表达式或直接连接并在槽函数中通过sender()获取发送者对象(但需注意sender()可能带来耦合问题)。 另一种方法是为每个ComboBox设置一个属性,然后在同一个槽函数中根据发送者对象和属性来判断。 然而,用户要求简写,即减少重复代码。我们可以这样做: 1. 创建一个通用的槽函数,该函数接收一个额外的参数(比如配置项的键),然后在槽函数中根据这个键来设置配置。 2. 使用lambda表达式在连接信号时捕获这个键,并将信号索引和键一起传递给一个公共的槽函数。 但是,原始代码中每个函数都是独立的,现在我们要改变连接方式。因此,我们需要在初始化连接时做修改。 假设原始代码片段如下(示例): connect(ui->cBox_muteKey, SIGNAL(currentIndexChanged(int)), this, SLOT(on_cBox_muteKey_currentIndexChanged(int))); connect(ui->cBox_playKey, SIGNAL(currentIndexChanged(int)), this, SLOT(on_cBox_playKey_currentIndexChanged(int))); connect(ui->cBox_EQKey, SIGNAL(currentIndexChanged(int)), this, SLOT(on_cBox_EQKey_currentIndexChanged(int))); 我们可以改为: 定义一个槽函数,例如:void onComboBoxIndexChanged(int index, const QString &configKey); 然后使用lambda表达式连接: connect(ui->cBox_muteKey, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index){ onComboBoxIndexChanged(index, "muteKey"); }); ... 其他类似 但是,注意原始信号可能是currentIndexChanged(int)或者是QString版本的,这里假设是int。 然而,考虑到代码的简洁性,我们也可以使用一个映射(map)来存储每个QComboBox对应的配置键,然后在槽函数中通过sender()获取发送者,再在映射中查找对应的键。 方法选择: 方法1(lambda表达式): 优点:直接,不需要映射,连接时明确指定配置键。 缺点:每个连接都要写lambda,但代码量还是比原来三个函数少。 方法2(使用映射和sender): 在类中定义一个QMap<QComboBox*, QString>,将每个ComboBox指针和对应的配置键关联。 然后连接所有ComboBox的currentIndexChanged信号到同一个槽函数(比如onComboBoxIndexChanged(int))。 在槽函数中,通过sender()得到QComboBox*,然后在映射中查找键,如果找到就进行设置。 我们选择方法2,因为这样连接信号时只需要写一次连接代码(可以使用循环),而且添加新的ComboBox时只需添加到映射中即可。 步骤: 1. 在头文件中声明槽函数:void onComboBoxIndexChanged(int index); 2. 在源文件中,定义一个私有成员:QMap<QComboBox*, QString> comboConfigMap; 3. 在初始化(比如构造函数)中,设置映射并连接信号。 示例: 在构造函数中: comboConfigMap[ui->cBox_muteKey] = "muteKey"; comboConfigMap[ui->cBox_playKey] = "playKey"; comboConfigMap[ui->cBox_EQKey] = "EQKey"; // 遍历映射的每个键(即QComboBox*),连接信号 for (auto it = comboConfigMap.begin(); it != comboConfigMap.end(); ++it) { connect(it.key(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MyClass::onComboBoxIndexChanged); // 注意:这里连接的是同一个槽 } 4. 实现槽函数: void MyClass::onComboBoxIndexChanged(int index) { QComboBox *combo = qobject_cast<QComboBox*>(sender()); if (combo && comboConfigMap.contains(combo)) { QString key = comboConfigMap.value(combo); // 然后根据key和index进行设置,比如: // config.setValue(...); // 原来的每个函数中的操作,现在统一到这里,根据key来区分 } } 注意:原来的三个函数中,除了设置配置项,可能还有特定的操作。如果它们除了配置项不同,其他操作都相同,那么这种方法很好。但如果每个函数有特殊逻辑,则需要在槽函数中根据key进行分支处理。 假设原来的三个函数结构如下: void on_cBox_muteKey_currentIndexChanged(int index) { config.setValue("muteKey", index); // 可能还有其他针对muteKey的操作 } ... 其他类似 那么,在公共槽函数中,我们可以: void MyClass::onComboBoxIndexChanged(int index) { QComboBox *combo = qobject_cast<QComboBox*>(sender()); if (!combo || !comboConfigMap.contains(combo)) return; QString key = comboConfigMap.value(combo); // 设置配置值 config.setValue(key, index); // 如果有针对不同key的特殊操作 if (key == "muteKey") { // 针对muteKey的操作 } else if (key == "playKey") { // ... } else if (key == "EQKey") { // ... } } 但是,如果每个特殊操作部分代码量较大,这样写会使得槽函数变得很长。我们可以考虑使用策略模式,将每个特殊操作封装成一个函数(或使用函数指针映射),但这样可能增加复杂度。 根据用户要求“简写”,我们假设这些函数除了配置项不同,其他操作都相同,那么就不需要分支。如果有不同,我们可以将特殊操作抽取成函数,然后通过一个映射(key到函数指针的映射)来调用,这样槽函数依然简洁。 然而,如果特殊操作部分比较简单,使用if-else也是可以接受的。 总结:将三个函数合并为一个,通过映射将发送者和配置项关联,在槽函数中统一处理。 如果用户希望更简洁,且特殊操作部分可以忽略,那么我们可以只保留设置配置项的操作。 因此,我们提供以下改写方案(假设没有特殊操作,或者特殊操作可以统一处理): 1. 删除原来的三个槽函数声明和定义。 2. 在类中增加一个私有槽函数:void onComboBoxIndexChanged(int index); 3. 在类中增加一个私有成员:QMap<QComboBox*, QString> comboConfigMap; 4. 在类的初始化函数(如构造函数)中初始化映射并连接信号。 注意:如果配置项的值不是直接使用index,而是需要转换(比如获取当前文本),那么在槽函数中需要调整。但原函数使用的是index,所以我们假设使用index。 如果原始函数中并不是直接使用index作为设置的值,比如: config.setValue("muteKey", ui->cBox_muteKey->currentData().toString()); 那么我们就不能在槽函数中直接使用index,而是需要从combo中获取currentData。所以,在槽函数中,我们通过combo对象获取需要的数据。 因此,槽函数可以这样写: void MyClass::onComboBoxIndexChanged(int index) { QComboBox *combo = qobject_cast<QComboBox*>(sender()); if (!combo || !comboConfigMap.contains(combo)) return; QString key = comboConfigMap.value(combo); QVariant data = combo->currentData(); // 如果原始函数使用的是currentData // 或者使用currentText(),根据原始函数而定 // 假设原始函数使用的是index,那么: // config.setValue(key, index); // 但为了通用,我们可能需要知道原始函数使用的值是什么。 所以,我们需要回顾原始函数。由于原始函数没有给出,我们假设它们都是使用index。 因此,我们按照使用index来设置配置项。 如果原始函数中每个函数使用的值不同,我们可以扩展映射,不仅存储key,还存储一个获取值的函数(比如std::function<QVariant(QComboBox*)>)。但这样会复杂一些。为了简化,我们先按照index处理。 如果实际情况不是这样,请根据具体需求调整。 综上所述,我们改写后的代码: 在头文件中: private slots: void onComboBoxIndexChanged(int index); private: QMap<QComboBox*, QString> comboConfigMap; // 存储每个组合框对应的配置键 在源文件中(构造函数部分): // 初始化映射 comboConfigMap[ui->cBox_muteKey] = "muteKey"; comboConfigMap[ui->cBox_playKey] = "playKey"; comboConfigMap[ui->cBox_EQKey] = "EQKey"; // 连接信号 for (auto it = comboConfigMap.begin(); it != comboConfigMap.end(); ++it) { connect(it.key(), QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MyClass::onComboBoxIndexChanged); } 槽函数实现: void MyClass::onComboBoxIndexChanged(int index) { QComboBox *combo = qobject_cast<QComboBox*>(sender()); if (combo && comboConfigMap.contains(combo)) { QString key = comboConfigMap[combo]; // 这里假设设置整数 config.setValue(key, index); // 如果有其他统一操作,可以在这里添加 } } 这样,我们用一个槽函数代替了原来的三个槽函数,并且连接代码也通过循环简化。 注意:如果配置项的值不是整数index,而是其他数据(如currentData),那么需要修改槽函数,从combo中获取相应的数据。同时,如果每个组合框需要获取的数据类型不同(比如有的要文本,有的要数据),那么可能需要为映射的值部分增加一个函数指针或lambda,但这会增加复杂度。因此,具体实现需要根据原始函数的具体逻辑调整。 由于问题中没有给出原始函数的具体内容,我们只能给出一个通用的简化方案。 如果原始函数中除了设置配置项还有不同的逻辑,我们可以在槽函数中根据key进行分支处理,或者使用策略模式,将不同的逻辑封装成函数并存储在另一个映射中(key到函数的映射)。 最后,注意使用sender()在多线程中可能不安全,但在单线程GUI程序中是常用的。 因此,我们提供上述方案作为简写方法。 </think> 要简化处理多个`QComboBox`的`currentIndexChanged`信号的C++代码,可以采用以下方法: ### 简化方案 1. **创建通用处理函数** 定义一个统一的槽函数,通过`QObject::sender()`识别信号源: ```cpp void YourClass::handleComboBoxChange(int index) { QComboBox* comboBox = qobject_cast<QComboBox*>(sender()); if (!comboBox) return; const QString objName = comboBox->objectName(); if (objName == "cBox_muteKey") config.setValue("muteKey", index); else if (objName == "cBox_playKey") config.setValue("playKey", index); else if (objName == "cBox_EQKey") config.setValue("EQKey", index); } ``` 2. **统一连接信号** 在初始化代码中批量连接信号(例如在构造函数中): ```cpp connect(ui->cBox_muteKey, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &YourClass::handleComboBoxChange); connect(ui->cBox_playKey, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &YourClass::handleComboBoxChange); connect(ui->cBox_EQKey, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &YourClass::handleComboBoxChange); ``` 3. **删除冗余槽函数** 移除原始的三个独立槽函数: ```cpp // 删除以下声明和定义: void on_cBox_muteKey_currentIndexChanged(int index); void on_cBox_playKey_currentIndexChanged(int index); void on_cBox_EQKey_currentIndexChanged(int index); ``` ### 优化说明 - **代码量减少**:从3个槽函数合并为1个,减少66%重复代码 - **可扩展性**:新增`QComboBox`时只需: 1. 添加一个`connect()`调用 2. 在`handleComboBoxChange`中添加一个判断分支 - **类型安全**:使用`qobject_cast`确保安全的对象类型转换 - **Qt5语法**:`QOverload<int>::of`确保正确匹配信号重载[^1] ### 注意事项 1. 确保每个`QComboBox`设置了正确的`objectName`: ```cpp ui->cBox_muteKey->setObjectName("cBox_muteKey"); // 其他组合框同理 ``` 2. 如需处理特殊逻辑(如某些组合框需要额外操作),可在对应的`if`分支中添加代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值