当前位置: 首页 > wzjs >正文

深圳网站设计深圳设计公司个体户做网站是怎么备案

深圳网站设计深圳设计公司,个体户做网站是怎么备案,微信公众平台内做网站,大连网站排名网络推广公司Qt 中,QComboBox 默认只支持单选,但实际使用过程中,我们经常会碰到需要多选的情况,但是通过一些直接或者曲折的方法还是可以实现的。 1、通过 QListWidget 间接实现 这种方式是网上搜索最多的一种方式,也是相对来说比…

Qt 中,QComboBox 默认只支持单选,但实际使用过程中,我们经常会碰到需要多选的情况,但是通过一些直接或者曲折的方法还是可以实现的。

1、通过 QListWidget 间接实现

这种方式是网上搜索最多的一种方式,也是相对来说比较简单的一种方法。

首先,自定义ComboBox类并继承自 QComboBox,在类内并定义一个QListWidget对象。

class MultiWdgComboBox : public QComboBox
{Q_OBJECT
public:using QComboBox::QComboBox;MultiComboBox(QWidget* parent = nullptr);void addItem(const QString &text, const QVariant &userData /* = QVariant() */);private:QListWidget* m_view_ptr{ nullptr };QString m_text{ QString() };
};

如上所示,定义好自定义之后,在其构造函数中对ComboBox的 view 和 model 重新设置。因为多选情况下控件显示的内容可能需要自定义,QComboBox默认是不支持的,所以我们可以使用QComboBox自带的QLineEdit 来实现自定义格式的数据显示。

MultiWdgComboBox::MultiWdgComboBox(QWidget* parent) : QComboBox(parent)
{m_view_ptr = new QListWidget;m_view_ptr->setContentsMargins(QMargins(15, 0, 0, 0));setEditable(true);lineEdit()->setReadOnly(true);setModel(m_view_ptr->model());setView(m_view_ptr); }

紧接着,我们需要重写基类的 addItem 函数,让其能满足我们自定义的类。下面的这种方式也就是在我们定义的 QListWdiget 对象中 insert 一个item,并对 item 设置对应的QWidget

void MultiWdgComboBox::addItem(const QString &text, const QVariant &userData)
{QListWidgetItem *pItem = new QListWidgetItem;QCheckBox* checkBox = new QCheckBox(this);checkBox->setText(text);pItem->setData(Qt::UserRole, userData);m_view_ptr->addItem(pItem);m_view_ptr->setItemWidget(pItem, checkBox);...
}

为了方便我们在点击 QCheckBox 时能实时改变显示的数据,我们需要实现一个信号槽的连接。

void MultiWdgComboBox::addItem(const QString &text, const QVariant &userData)
{...QCheckBox* checkBox = new QCheckBox(this);...connect(checkBox, &QCheckBox::clicked, this, [this](bool checked){auto box = static_cast<QCheckBox*>(sender());QStringList texts = m_text.isEmpty() ? QStringList() : m_text.split(";");if (checked){texts.append(box->text());}else{texts.removeOne(box->text());}m_text = texts.join(";");this->setEditText(m_text);});
}

有了上面的步骤,基本上一个简单的多选 ComboBox 控件就初具雏形了。

如果初始状态下,已经有部分的item被选中了,那我们该如何设置对应的item状态呢?

void MultiWdgComboBox::setData(const QVariant& data)
{QStringList text;QVariantList datas = data.value<QVariantList>();for (int index = 0; index < m_view_ptr->count(); ++index){auto item = m_view_ptr->item(index);auto ptr = static_cast<QCheckBox*>(m_view_ptr->itemWidget(item));if (datas.contains(item->data(Qt::UserRole))){if (ptr != nullptr && ptr->isEnabled()){ptr->setChecked(true);text.push_back(ptr->text());}}}m_text = text.join(";");
}

上面的这个函数是根据item的userData来进行设置的,当然也可以通过item的text来进行设置。

同理,获取已经选中的item数据是一样的道理。

QVariant MultiWdgComboBox::data() const
{QVariantList datas;for (int index = 0; index < m_view_ptr->count(); ++index){auto item = m_view_ptr->item(index);auto ptr = static_cast<QCheckBox*>(m_view_ptr->itemWidget(item));if (ptr != nullptr && ptr->isChecked()){datas.push_back(item->data(Qt::UserRole));}}return datas;}

当然如果 item 的 userData 没有实际的意义,只是想标识一下被勾选的item,也可以用 二进制的方式来实现,最后可通过循环右移一位的方式遍历获得勾选的全部item项。也可以使用 Qt 的 QFlags 属性来实现。

根据上面的内容,我们基本上已经实现了一个ComboBox 的基本功能,但是由于使用了 QComboBox的edit属性,所以存在一个不好的体验,就是在点击下拉的时候,响应区域只有下拉箭头表示的那部分范围,而在 其 QLineEdit 所在的范围并不响应。

所以,根据以前 《QComboBox文字居中的几种实现方式》这篇文章的内容,对自定义ComboBox的显示部分做了重新绘制。

重写 paintEvent 事件函数即可。

void MultiWdgComboBox::paintEvent(QPaintEvent* e)
{QStylePainter painter(this);painter.setPen(palette().color(QPalette::Text));QStyleOptionComboBox opt;initStyleOption(&opt);painter.drawComplexControl(QStyle::CC_ComboBox, opt);if (opt.editable){painter.drawControl(QStyle::CE_ComboBoxLabel, opt);return;}QRect editRect = this->style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);QStyleOptionButton buttonOpt;buttonOpt.initFrom(this);buttonOpt.direction = Qt::LeftToRight;buttonOpt.rect = editRect;buttonOpt.text = m_text;buttonOpt.icon = opt.currentIcon;buttonOpt.iconSize = opt.iconSize;painter.drawControl(QStyle::CE_CheckBoxLabel, buttonOpt);}

2、另辟蹊径,使用 QPushBututon 的 setMenu 方法,set一个 自定义Action的Menu。

这种方法呢,是我在做其他需求的时候偶然发现的,原来一些比较复杂的控件都可以用原生的控件可以实现。
首先,自定义一个继承自 QPushButton的子类 MultiButtonComboBox

class MultiButtonComboBox : public QPushButton
{Q_OBJECT
public:MultiButtonComboBox(QWidget* parent = nullptr);void addItem(const QString& text, const QVariant& data = QVariant());void setData(const QVariant& data);QVariant data() const;private:MultiListWidget* m_ptr{ nullptr };
};

如上所示,定义好自定义之后,在其构造函数中设置一个自定义界面的menu。

MultiButtonComboBox::MultiButtonComboBox(QWidget* parent) : QPushButton(parent)
{auto menu = new QMenu(this);m_ptr = new MultiListWidget(this);QWidgetAction *action = new QWidgetAction(this);action->setDefaultWidget(m_ptr);menu->addAction(action);setMenu(menu);connect(m_ptr, &MultiListWidget::signal_text, this, [this](const QString& text){setText(text);});}

设置好自定义的菜单界面之后,只需要根据需要实现自定义的菜单界面就行了。可以用 QListWidget, 也可以用 QListView,我这边用的是 QListView 和 自定义listviewitem 代理实现的。

class MultiListWidget : public QWidget
{Q_OBJECTpublic:MultiListWidget(QWidget *parent = nullptr);~MultiListWidget();void addItem(const QString& text, const QVariant& userData);void setData(const QVariant& data);QVariant data() const;private:void initPage();signals:void signal_text(const QString& text);private:Ui::MultiListWidget *ui;QStandardItemModel* m_pModel{ nullptr };QString m_text{ QString() };};

这种方式的实现是比较简单的,对 QListView 设置 item 代理及 model 之后,后续的操作只是对 model 的数据操作。为了图方便,使用了标准的 QStandardItemModel 类,当然可以自定义 model 类,通过重写 自定义类的 data 函数,能更好的满足自定义功能的需求。

void MultiListWidget::initPage()
{m_pModel = new QStandardItemModel();auto *delegate = new CmbBoxItemDelegate(this);ui->listView->setItemDelegate(delegate);ui->listView->setModel(m_pModel);...
}

自定义 QListView 的 item 代理后,可以通过重写它的 editorEvent 函数来控制item的编辑事件。那我们就可以通过实现 代理与 当前类的信号槽来实现我们已经选择、显示的item 数据。

void MultiListWidget::initPage()
{...auto *delegate = new CmbBoxItemDelegate(this);...connect(delegate, &CmbBoxItemDelegate::signal_btn_clicked, this, [this](const QModelIndex& index){QStringList texts = m_text.isEmpty() ? QStringList() : m_text.split(";");bool checked = !index.data(Qt::UserRole + 1).toBool();m_pModel->setData(index, checked, Qt::UserRole + 1);if (checked){texts.append(index.data(Qt::DisplayRole).toString());}else{texts.removeOne(index.data(Qt::DisplayRole).toString());}m_text = texts.join(";");emit signal_text(m_text);});
}

紧接着,实现 addItem 函数。

void MultiListWidget::addItem(const QString& text, const QVariant& userData)
{QStandardItem *pItem = new QStandardItem;pItem->setData(false, Qt::UserRole + 1);pItem->setData(text, Qt::DisplayRole);pItem->setData(userData, Qt::UserRole);m_pModel->appendRow(pItem);
}

setData函数。

void MultiListWidget::setData(const QVariant& data)
{QStringList texts;auto datas = data.toList();for (int index = 0; index < m_pModel->rowCount(); ++index){auto mIndex = m_pModel->index(index, 0);if (datas.contains(mIndex.data(Qt::UserRole))){m_pModel->setData(mIndex, true, Qt::UserRole + 1);texts.append(mIndex.data().toString());}}m_text = texts.join(";");emit signal_text(m_text);
}

data 函数。

QVariant MultiListWidget::data() const
{QVariantList datas;for (int index = 0; index < m_pModel->rowCount(); ++index){auto mIndex = m_pModel->index(index, 0);if (mIndex.data(Qt::UserRole + 1).toBool()){datas.append(mIndex.data(Qt::UserRole));}}return datas;
}

3、自定义QComboBox 的 item delegate

这种方式跟上面第二种来说是差不多的,只不过上面的第二种方法实现的比较曲折,而QComboBox的view也可以是个ListView。所以我们取了第一种方法的绘制显示text的方法和第二种的item代理,结合就有了第三种方法。相对来说,这种方法更简单直接些。

首先自定义继承自QComboBox的类并设置代理,实现代理的信号槽函数。

MultiWdgComboBox::MultiViewComboBox(QWidget* parent) : QComboBox(parent)
{auto delegate = new CmboBoxItemDelegate(this);setItemDelegate(delegate);connect(delegate, &CmboBoxItemDelegate::signal_btn_clicked, this, [this](const QModelIndex& index){auto checked = !index.data(Qt::UserRole + 1).toBool();this->model()->setData(index, checked, Qt::UserRole + 1);QStringList texts = m_text.isEmpty() ? QStringList() : m_text.split(";");if (checked){texts.append(index.data().toString());}else{texts.removeOne(index.data().toString());}m_text = texts.join(";");});
}

这种方式也是唯一一种不需要重写 addItem 方法的实现形式,后面的 setData 和 data 与上面第二种方式的完全一样。

这种方式要避免多次设置item的代理,否则代理可能不生效。

如果我们使用的是第一种方法,鼠标点击的范围如果超过了每行QCheckBox的实际范围,实际效果下来是,既没有选中某行,comboBox的下拉框也会收起。

同样的,如果使用的是第三种,自定义了QComboBox的 item 代理,点击起哄一行也会将下拉框收起,这样我们要完成多选的话就得点击好几次。

所以,我们可以通过重写hidePopup函数来避免这个问题。

void MultiViewComboBox::hidePopup()
{QWidget *popup = this->findChild<QFrame*>();if(!popup->geometry().contains(QCursor::pos())){QComboBox::hidePopup();}
}

4、注意事项

在第一种使用 QListWidget 的时候,测试时出现了下面这种情况。

在这里插入图片描述
这个问题的原因是我们给QListWidget设置了model,为什么呢?因为根据Qt已经有的那种 model/view的结构,QListWidget已经是对应的结构了,它有自己的model,如果想要通过重写自己的model来实现数据的话,建议使用QlistView

但是在这个里面,我们已经选择了QListWidget,那有没有什么解决办法。

其实我们只需要在给ComboBox设置view之前设置model就可以了,也就是说,下面的这两行代码顺序不能互换。

MultiComboBox::MultiComboBox(QWidget* parent) : QComboBox(parent)
{...setModel(m_view_ptr->model());setView(m_view_ptr); }

测试代码


文章转载自:

http://jNllAjh0.mxhgy.cn
http://7p0krdKH.mxhgy.cn
http://A0sVAxHt.mxhgy.cn
http://lry3U5bG.mxhgy.cn
http://4EO5uwhJ.mxhgy.cn
http://b8AO8eHF.mxhgy.cn
http://3dGwaCcy.mxhgy.cn
http://NzJY5r1a.mxhgy.cn
http://uM7pCdHY.mxhgy.cn
http://pYTkX8yM.mxhgy.cn
http://5TcxlQ1t.mxhgy.cn
http://DqdGrInw.mxhgy.cn
http://25XzbSOY.mxhgy.cn
http://avO01Nbw.mxhgy.cn
http://3q0rKamu.mxhgy.cn
http://L952lBUp.mxhgy.cn
http://dAtZO239.mxhgy.cn
http://AGoOkMQ2.mxhgy.cn
http://3koPRRET.mxhgy.cn
http://Eeuxt6ZR.mxhgy.cn
http://oT2CoRXs.mxhgy.cn
http://IAfwHCV7.mxhgy.cn
http://NbcSpAhw.mxhgy.cn
http://lO4oy6Kl.mxhgy.cn
http://rVaBq6JI.mxhgy.cn
http://i5yAH87Q.mxhgy.cn
http://hwrdUw3p.mxhgy.cn
http://wbt1Id1s.mxhgy.cn
http://sficPpEv.mxhgy.cn
http://eS6rgIBD.mxhgy.cn
http://www.dtcms.com/wzjs/661674.html

相关文章:

  • 哈尔滨住房和城乡建设局网站网页界面设计时颜色越多越好
  • 团购网站建设费用沈阳网站搭建
  • 怎样把网站推广出去上海牛巨微seo关键词优化
  • 天涯网站建设路小学本地的赣州网站建设
  • 邢台企业建站重新下载一个微信
  • 牛仔裤网站设计企业网站制作收费
  • 重庆建设工程安全协会网站自适应网站三套代码
  • 太仓网站建设找哪家郑州网站制作哪家招聘
  • 郑州网站建站素材网站都有哪些
  • 网站建设培训深圳wordpress服务器出错
  • 经常修改网站的关键词好不好python培训学校
  • 网站排名配色网页美工设计是什么
  • 简易手机网站开发网站右下角弹窗代码
  • 网站程序方面贵阳seo网站推广
  • 怎么做水果网站浙江虎霸建设机械有限公司网站
  • 山西通州集团网站建设seo网站关键词排名快速
  • 企业网站备案注销三只松鼠品牌案例分析
  • 网站建设属于什么费网站无搜索结果页面怎么做
  • 顶呱呱网站建设价格上海建设摩托官方网站
  • python网站开发的优势一二三四免费观看视频中文版在线
  • 996建站网站制作情感营销案例
  • 游戏工作室招聘信息怎么seo网站推广
  • 北京软件网站开发海口网页设计公司排名
  • 数控机床网站建设电子商务网站建设与维护读书报告
  • 西安十强互联网站建设公司人力外包网站
  • 苏州网站建设需要多少钱新手学做网站vs
  • 外链网站 风险品牌免费网站建设
  • 建筑公司做网站的好处中信建设有限责任公司资质
  • 硬盘做网站空间软文街官网
  • 灌南建设局网站网站开发专业考啥证书