迅猛支付QCombox以及专门的学问样式自定义,qcombox样式自定义

by admin on 2019年4月28日

 那是自身在项目实战中的个人计算,写的仓促,有个别东西也不必然规范,有个别是协和预计的,还盼望各位多多指教,多多商酌。

 那是本人在类型实战中的个人总计,写的匆匆,某些东西也不料定标准,有个别是协和揣摸的,还期待各位多多指教,多多商酌。

急迅支付QCombox以及工作样式自定义,qcombox样式自定义

 那是本身在品种实战中的个人总计,写的皇皇,有个别东西也不必然标准,有个别是和睦推测的,还盼望各位多多指教,多多商量。

 关于QCombox假若不须要自定义,其实写UI是相当粗略的。

创立实例:QComboBox*  m_pMicrophoneCombox = new QComboBox;

自身是用的QSS去的写样式,那里用了1个命名函数:m_pMicrophoneCombox->setObjectName(“DeviceCombox”);

假如是用的setstylesheet直接在代码里去写就好了。

上边说多少个属性函数:

m_pMicrophoneCombox->set马克斯VisibleItems(2);//最大可知区域为展现两条。

m_pMicrophoneCombox->setEditable(false); //设置QComboBox可编辑。

m_pMicrophoneCombox->setFocusPolicy(Qt::NoFocus);//设置QCombox未有失常态。

m_pMicrophoneCombox->setLine艾德it(edit);//edit是2个lineedit,就是说QCombox的Line艾德it能够自定义,而QT的源码中,顶端也是3个Line艾德it。

m_pMicrophoneCombox->setCurrentIndex(0); // 设置当前入选的目录。

m_pMicrophoneCombox->setCurrentText(TR_TALK_DEVICE_COMBOX);//设置QCombox当前的彰显text,作者是用宏封装的,满意早先时期修改。

m_pMicrophoneCombox->setItemData(i,
list[i]);//QCombox也能够和谐传入三个链表,并且本人定义索引,当然,你想传一条数据,并且本身定义索引。

QListWidget* pListWidget = new QListWidget();//new一个widget的实例。

m_pMicrophoneCombox->setModel(pListWidget->model());//塞进widget的model。
m_pMicrophoneCombox->setView(pListWidget);//将widget装进Combox。

m_pMicrophoneCombox->count();//用来计算combox下拉窗体的尺寸。

m_pMicrophoneCombox->addItems(list);//插入四个列表。

m_pMicrophoneCombox->addItem(“11一”);//插入单条数据。

以上函数基本满意工作要求,如若交互的样式比较复杂,必要自定义样式,那样的话,大家就要谐和去写每2个item的体裁。

分析下QCombox的源码,其实他的兑现正是3个Line艾德it和二个ListWidget,知道啊那几个就能够本身去重新写2个ListWidget。

Item *pItem = new Item();
//item是团结自定义写的布局,每三个item的自定义样式就可以写在那些里面。
QListWidgetItem *pListWidgetItem = new
QListWidgetItem(list[i],pListWidget);//作者是将链表的数据塞进QCombox里。
pItem->setItemData(list[i]);//给每一个item塞进多少
迅猛支付QCombox以及专门的学问样式自定义,qcombox样式自定义。pListWidget->setItemWidget(pListWidgetItem,
pItem);//关于这些函数小编的知情是:在底下一层上边再覆盖壹层。

接下来在QSS的体制里写hover、pressed鼠标事件,就有鼠标的互动。

那种方式就算实惠,不过多少不与UI分离,都搅在1团。

最好的方案正是:

迅猛支付QCombox以及专门的学问样式自定义,qcombox样式自定义。  既然QT的combox援救listwidget,那么全部都用自个儿定制的listwidget。

 在itemwidget里写布局,自身搞1个delegate,在代理去管理UI,数据在model里去操作,那里的model或者要团结包裹一层,满意combox的竞相须求。

pListWidget->m_pModel->Append(list[i]);//将每1个数量塞进model,剩下的数码操作就由model去管理。

格外注意的是:那一年,qt原生的那么些接口都不见效了,举个例子:setcurrenttext还有setcurrentindex,查看源码发掘都以依照索引来操控,而实际,大家用本身的model

去管理的数据,并不会变动一个索引来满意combox管理的数量,所以那一个对外的接口可能也要协和去封装出来,能够说基本上是放任了combox,本人去组装Line艾德it和ListWidget。

实质上代码量是广大的,公司业务能够去封装成控件,方便开垦。

    最终,假使大神们有越来越好的点子,接待评论。

 

 

那是本身在项目实战中的个人计算,写的匆匆,有些东西也不自然规范,有个别是上下一心推…

笔录下利用QListView境遇的各个主题素材

 关于QCombox假诺不要求自定义,其实写UI是相当粗略的。

 关于QCombox借使不供给自定义,其实写UI是很轻易的。

QListView能够用来以列表的花样体现数据,在Qt中央银行使model/View结构来治本数据与视图的关系,model担当数据的存取,数据的互动通过delegate来完成。

始建实例:QComboBox*  m_pMicrophoneCombox = new QComboBox;

开创实例:QComboBox*  m_pMicrophoneCombox = new QComboBox;

丰硕数据模型

QT提供了1部分现有的models用于拍卖数量项:
QStringListModel 用于存款和储蓄轻巧的QString列表。
Q斯坦dardItemModel
管理复杂的树型结构数据项,每项都足以涵盖自由数据。
QDirModel 提供当麻芋果件系统中的文件与目录音讯。
QSqlQueryModel, QSqlTableModel,QSqlRelationTableModel用来访问数据库。

行使Qt自带的模型类QStandardItemModel就能够。模型中的每一种数据项都有3个与之相应的role来存款和储蓄某一类数据。须求存取自定义数据能够利用UserRole,UserRole+1…

对此自定义数据类型,借使要运用QVariant,就务须利用Q_DECLARE_METATYPE注册。

struct ItemData{
    QString name;
    QString tel;
};

Q_DECLARE_METATYPE(ItemData)

本身是用的QSS去的写样式,那里用了二个命名函数:m_pMicrophoneCombox->setObjectName(“DeviceCombox”);

笔者是用的QSS去的写样式,那里用了2个命名函数:m_pMicrophoneCombox->setObjectName(“DeviceCombox”);

单纯性数据存取

//存
Item->setData(itemStatus,Qt::UserRole);  // 单一存取

//取
ItemStatus status = (ItemStatus)(index.data(Qt::UserRole).toInt());

万一是用的setstylesheet直接在代码里去写就好了。

若果是用的setstylesheet直接在代码里去写就好了。

结构体数据存取

//存
Item->setData(QVariant::fromValue(itemData),Qt::UserRole+1);//整体存取

//取
QVariant variant = index.data(Qt::UserRole+1);
ItemData data = variant.value<ItemData>();

上边说几天性子函数:

上面说多少个特性函数:

自定义delegate

模型的相互和制图通过自定义delegate来兑现,暂且没用到交互,先说下item的绘图。继承了QStyledItemDelegate后,重写paint函数管理item的体裁,以及sizeHint函数重返item的尺寸:

m_pMicrophoneCombox->set马克斯VisibleItems(二);//最大可知区域为呈现两条。

m_pMicrophoneCombox->set马克斯VisibleItems(贰);//最大可知区域为显示两条。

绘制item

void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{


    if(index.isValid())
    {
        painter->save();

        ItemStatus status = (ItemStatus)(index.data(Qt::UserRole).toInt());

        QVariant variant = index.data(Qt::UserRole+1);
        ItemData data = variant.value<ItemData>();

        QStyleOptionViewItem viewOption(option);//用来在视图中画一个item

        QRectF rect;
        rect.setX(option.rect.x());
        rect.setY(option.rect.y());
        rect.setWidth( option.rect.width()-1);
        rect.setHeight(option.rect.height()-1);

        //QPainterPath画圆角矩形
        const qreal radius = 7;
        QPainterPath path;
        path.moveTo(rect.topRight() - QPointF(radius, 0));
        path.lineTo(rect.topLeft() + QPointF(radius, 0));
        path.quadTo(rect.topLeft(), rect.topLeft() + QPointF(0, radius));
        path.lineTo(rect.bottomLeft() + QPointF(0, -radius));
        path.quadTo(rect.bottomLeft(), rect.bottomLeft() + QPointF(radius, 0));
        path.lineTo(rect.bottomRight() - QPointF(radius, 0));
        path.quadTo(rect.bottomRight(), rect.bottomRight() + QPointF(0, -radius));
        path.lineTo(rect.topRight() + QPointF(0, radius));
        path.quadTo(rect.topRight(), rect.topRight() + QPointF(-radius, -0));

        if(option.state.testFlag(QStyle::State_Selected))
        {
            painter->setPen(QPen(Qt::blue));
            painter->setBrush(QColor(229, 241, 255));
            painter->drawPath(path);
        }
        else if(option.state.testFlag(QStyle::State_MouseOver))
        {
            painter->setPen(QPen(Qt::green));
            painter->setBrush(Qt::NoBrush);
            painter->drawPath(path);
        }
        else{
            painter->setPen(QPen(Qt::gray));
            painter->setBrush(Qt::NoBrush);
            painter->drawPath(path);
        }

        //绘制数据位置
        QRect NameRect = QRect(rect.left() +10, rect.top()+10, rect.width()-30, 20);
        QRect circle = QRect(NameRect.right(), rect.top()+10, 10, 10);
        QRect telRect = QRect(rect.left() +10, rect.bottom()-25, rect.width()-10, 20);


        switch (status) {
        case S_RED:
            painter->setBrush(Qt::red);
            painter->setPen(QPen(Qt::red));
            break;
        case S_BLUE:
            painter->setBrush(Qt::blue);
            painter->setPen(QPen(Qt::blue));
            break;
        case S_YELLOW:
            painter->setBrush(Qt::yellow);
            painter->setPen(QPen(Qt::yellow));
            break;
        }

        painter->drawEllipse(circle);     //画圆圈

        painter->setPen(QPen(Qt::black));
        painter->setFont(QFont("Times", 12, QFont::Bold));
        painter->drawText(NameRect,Qt::AlignLeft,data.name); //绘制名字

        painter->setPen(QPen(Qt::gray));
        painter->setFont(QFont("Times", 10));
        painter->drawText(telRect,Qt::AlignLeft,data.tel); //绘制电话

        painter->restore();
    }
}

QSize ItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    return QSize(160, 60);
}

m_pMicrophoneCombox->setEditable(false); //设置QComboBox可编辑。

m_pMicrophoneCombox->setEditable(false); //设置QComboBox可编辑。

设置item差异景色下的体裁

在paint函数中,还能收获当前item的图景,并设置区别的体裁:

 if(option.state.testFlag(QStyle::State_Selected)) //选中状态
        {
            painter->setPen(QPen(Qt::blue));
            painter->setBrush(QColor(229, 241, 255));
            painter->drawPath(path);
        }
        else if(option.state.testFlag(QStyle::State_MouseOver))//鼠标划过状态
        {
            painter->setPen(QPen(Qt::green));
            painter->setBrush(Qt::NoBrush);
            painter->drawPath(path);
        }
        else{
            painter->setPen(QPen(Qt::gray));
            painter->setBrush(Qt::NoBrush);
            painter->drawPath(path);
        }

设置好模型后,再对QListView实行下属性设置:

    ui->listView->setItemDelegate(m_delegate);       //为视图设置委托
    ui->listView->setSpacing(15);                   //为视图设置控件间距
    ui->listView->setModel(m_model);                  //为委托设置模型
    ui->listView->setViewMode(QListView::IconMode); //设置Item图标显示
    ui->listView->setDragEnabled(false); 

模型的多少和展现都管理好后,运营效果如下:

listview展示

m_pMicrophoneCombox->setFocusPolicy(Qt::NoFocus);//设置QCombox未有规范。

m_pMicrophoneCombox->setFocusPolicy(Qt::NoFocus);//设置QCombox没异常。

过滤item

Qt中提供了三个有利于管理模型排序和过滤的类QSortFilterProxyModel,通过她能够十一分便宜的拍卖我们的model。将QListView显示的model设置成代理模型:

    ui->listView->setItemDelegate(m_delegate);       //为视图设置委托
    ui->listView->setSpacing(15);                   //为视图设置控件间距
    m_proxyModel = new QSortFilterProxyModel(ui->listView);
    m_proxyModel->setSourceModel(m_model);
    m_proxyModel->setFilterRole(Qt::UserRole);
    m_proxyModel->setDynamicSortFilter(true);
    ui->listView->setModel(m_proxyModel);                  //为委托设置模型
    ui->listView->setViewMode(QListView::IconMode); //设置Item图标显示
    ui->listView->setDragEnabled(false);            //控件不允许拖动

其中,m_proxyModel->setFilterRole(Qt::UserRole);安装依照模型的某壹项数据来管理模型的过滤。proxyModel可以安装过滤的法子,依照QString也许正则表明式来过滤:

m_proxyModel->setFilterFixedString(QString::number(S_RED));//根据字符串过滤
m_proxyModel->setFilterRegExp(QRegExp("^[0|2]$")); //根据正则表达式过滤

过滤模型

m_pMicrophoneCombox->setLine艾德it(edit);//edit是一个lineedit,正是说QCombox的Line艾德it能够自定义,而QT的源码中,顶端也是多个LineEdit。

m_pMicrophoneCombox->setLine艾德it(edit);//edit是1个lineedit,正是说QCombox的Line艾德it能够自定义,而QT的源码中,顶端也是1个Line艾德it。

获得选中item

对于列表中item的操作,能够是在delegate中管理互相事件,也足以由此QListView获取到具备入选item的QModelIndex,然后对模型本身实行改变。这里作者采用的后人:

QModelIndexList modelIndexList = ui->listView->selectionModel()->selectedIndexes();

m_pMicrophoneCombox->setCurrentIndex(0); // 设置当前当选的目录。

m_pMicrophoneCombox->setCurrentIndex(0); // 设置当前入选的目录。

安装多选

将QListView的selectionBehavior设置成MultiSelection即可。

对于多选的时候,模型的改造有一个坑。在安装了代办模型后,由于开启了动态排序形式,假如改变代理模型的多寡,在首先个item修改数据后或者就不在当前过滤模型中,会被过滤掉,后边的item的QModelIndex就会变卦,导致持续的修改败北。

dynamicSortFilter : bool
This property holds whether the proxy model is dynamically sorted and
filtered whenever the contents of the source model change.
Note that you should not update the source model through the proxy
model when dynamicSortFilter is true. For instance, if you set the
proxy model on a QComboBox, then using functions that update the
model, e.g., addItem(), will not work as expected. An alternative is
to set dynamicSortFilter to false and call sort() after adding items
to the QComboBox.
The default value is true.

有几个方法管理这么些坑,一是不改换代理模型,修改源模型的数量。二是在修改模型数据的时候关闭代理模型的动态排序功用。

m_pMicrophoneCombox->setCurrentText(TR_TALK_DEVICE_COMBOX);//设置QCombox当前的体现text,笔者是用宏封装的,满意前期修改。

m_pMicrophoneCombox->setCurrentText(TR_TALK_DEVICE_COMBOX);//设置QCombox当前的彰显text,笔者是用宏封装的,满意中期修改。

修改数据

QModelIndexList sourceIndexList;
    foreach (QModelIndex modelIndex, modelIndexList){
        sourceIndexList<<m_proxyModel->mapToSource(modelIndex); //获取源model的modelIndex
    }

//    g_proxyModel->setDynamicSortFilter(false);
    foreach (QModelIndex sourceIndex, sourceIndexList){
        ItemStatus status = (ItemStatus)(sourceIndex.data(Qt::UserRole).toInt());
        qDebug() << "Index : " << sourceIndex.row();

        switch (status) {
            case S_RED:
                redNum--;
                break;
            case S_BLUE:
                blueNum--;
                break;
            case S_YELLOW:
                yellowNum--;
                break;
        }

        status = S_RED;
        redNum++;

        m_model->setData(sourceIndex,status,Qt::UserRole);
    }
//    g_proxyModel->setDynamicSortFilter(true);

弄完大约是酱紫的:

最终效果

Demo在这里:->Github链接地址。

m_pMicrophoneCombox->setItemData(i,
list[i]);//QCombox也能够友善传入三个链表,并且自个儿定义索引,当然,你想传一条数据,并且本身定义索引。

m_pMicrophoneCombox->setItemData(i,
list[i]);//QCombox也足以团结传入八个链表,并且本人定义索引,当然,你想传一条数据,并且本身定义索引。

QListWidget* pListWidget = new QListWidget();//new一个widget的实例。

QListWidget* pListWidget = new QListWidget();//new一个widget的实例。

m_pMicrophoneCombox->setModel(pListWidget->model());//塞进widget的model。
m_pMicrophoneCombox->setView(pListWidget);//将widget装进Combox。

m_pMicrophoneCombox->setModel(pListWidget->model());//塞进widget的model。
m_pMicrophoneCombox->setView(pListWidget);//将widget装进Combox。

m_pMicrophoneCombox->count();//用来计量combox下拉窗体的轻重。

m_pMicrophoneCombox->count();//用来计量combox下拉窗体的大大小小。

m_pMicrophoneCombox->addItems(list);//插入二个列表。

m_pMicrophoneCombox->addItems(list);//插入2个列表。

m_pMicrophoneCombox->addItem(“11一”);//插入单条数据。

m_pMicrophoneCombox->addItem(“11一”);//插入单条数据。

上述函数基本满意工作要求,假设交互的体裁比较复杂,供给自定义样式,那样的话,大家将在和睦去写每三个item的体制。

上述函数基本满意事业要求,如若交互的体裁相比较复杂,供给自定义样式,那样的话,大家将要团结去写每三个item的体制。

浅析下QCombox的源码,其实她的得以完毕就是贰个Line艾德it和二个ListWidget,知道啊这一个就能够和谐去重新写一个ListWidget。

分析下QCombox的源码,其实她的兑现就是贰个Line艾德it和四个ListWidget,知道啊这一个就能够团结去重新写二个ListWidget。

Item *pItem = new Item();
//item是和煦自定义写的布局,每1个item的自定义样式就足以写在这个里面。
QListWidgetItem *pListWidgetItem = new
QListWidgetItem(list[i],pListWidget);//笔者是将链表的数量塞进QCombox里。
pItem->setItemData(list[i]);//给每一种item塞进多少
pListWidget->setItemWidget(pListWidgetItem,
pItem);//关于那几个函数小编的精晓是:在上面一层上边再覆盖1层。

Item *pItem = new Item();
//item是温馨自定义写的布局,每3个item的自定义样式就能够写在这么些里面。
QListWidgetItem *pListWidgetItem = new
QListWidgetItem(list[i],pListWidget);//作者是将链表的数码塞进QCombox里。
pItem->setItemData(list[i]);//给每1个item塞进多少
pListWidget->setItemWidget(pListWidgetItem,
pItem);//关于这些函数小编的明亮是:在底下一层下面再覆盖1层。

接下来在QSS的样式里写hover、pressed鼠标事件,就有鼠标的互相。

然后在QSS的体制里写hover、pressed鼠标事件,就有鼠标的互动。

这种情势就算实惠,不过数量不与UI分离,都搅在一团。

home88一必发,那种艺术纵然实惠,不过数量不与UI分离,都搅在1团。

极品的方案正是:

至上的方案正是:

  既然QT的combox扶助listwidget,那么全部都用自身定制的listwidget。

  既然QT的combox帮助listwidget,那么全部都用本人定制的listwidget。

 在itemwidget里写布局,自个儿搞3个delegate,在代理去管理UI,数据在model里去操作,那里的model恐怕要本人包装壹层,知足combox的相互供给。

 在itemwidget里写布局,自身搞一个delegate,在代理去管理UI,数据在model里去操作,那里的model恐怕要团结包裹壹层,满意combox的相互必要。

pListWidget->m_pModel->Append(list[i]);//将每3个数码塞进model,剩下的多少操作就由model去管理。

pListWidget->m_pModel->Append(list[i]);//将每三个数量塞进model,剩下的数目操作就由model去管理。

破例注意的是:那一年,qt原生的那么些接口都不奏效了,举例:setcurrenttext还有setcurrentindex,查看源码开采都以根据索引来操控,而实在,大家用本人的model

特殊注意的是:那个时候,qt原生的那么些接口都不见效了,举个例子:setcurrenttext还有setcurrentindex,查看源码开掘都是依据索引来操控,而实际,大家用本人的model

去管理的多寡,并不会变动叁个索引来满意combox管理的数量,所以那么些对外的接口恐怕也要本身去封装出来,能够说基本上是放任了combox,自身去组装Line艾德it和ListWidget。

去管理的数量,并不会扭转三个索引来知足combox管理的数目,所以那几个对外的接口可能也要本身去封装出来,能够说基本上是放弃了combox,本身去组装Line艾德it和ListWidget。

实际代码量是众多的,集团工作能够去封装成控件,方便开辟。

事实上代码量是许多的,集团事情能够去封装成控件,方便开辟。

    最后,若是大神们有更加好的诀窍,迎接商酌。

    最后,若是大神们有更加好的不2诀要,接待商酌。

 

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图