一去二三里 飞扬青云@gitee 飞扬青云@csdn 飞扬青云@cnblogs 花狗Fdog 界面合集 长沙红胖子 Qt各控件的视频讲解
---------------------------------------------
界面美化系列视频1
界面美化系列视频2
界面框架视频
Qt自定义标题栏视频
Qt 开源项目收集大全
qt常用开源控件库
Qt开源炫酷界面QCoolPage
Qt界面开发【各种控件以及图表】
QT 开源类库集合
Qt-Open-Source-Project各种开源库链接
网易云音乐模仿系列视频-----重绘标题栏
pyqt界面视频集合
QWidget设置背景图片
qt-material-widgets的GitHub地址
界面定制:
PyDracula - 界面美化模板【视频】
PyDracula【Github地址】
QtDracula【Github地址】
自定义悬浮条
Qt利用"布局、widget、ScrollArea"实现抽屉效果
自定义标题栏
实现窗口透明的五种方法(长沙红胖子)
//透明窗体中的圆形按钮(按钮不透明)
setAttribute(Qt::WA_TranslucentBackground, true );
QPalette pal = palette();
pal.setColor(QPalette::Background, QColor(0x00,0xff,0x00,0x00));
setPalette(pal);
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
setStyleSheet("QPushButton{ color: green; background: #f44336; font-size: 10px; border:1px solid red; "
"min-width:60; max-width:60; min-height:60; max-height:60;border-radius:30px;border-image:url(:/home.png);}"
"QPushButton:hover { font-size: 10px; color: white; background: #d5d5d5; border-image:url(:/set.png); } "
"QPushButton:pressed { background: #f2f2f2;}");
---------------------------------------------
qt 如何设计好布局和漂亮的界面
Qt 界面设计总结
Qt 之水平/垂直布局(QBoxLayout、QHBoxLayout、QVBoxLayout)
setMargin(0);
setSpacing(0);
setContentsMargins(0,0,0,0);
pHLayout->addStretch(); // 添加伸缩
setStretch(0,80);
setStretch(1,20);
addWidget(m_mainSplitter);
pHLayout->addWidget(pButton1, 0 , Qt::AlignLeft | Qt::AlignTop);
pHLayout->addWidget(pButton4, 0 , Qt::AlignLeft | Qt::AlignBottom);
重新LayOut要先清楚子窗体的parent
布局中的间隔
- 1、addSpacing(int size)在layout的控件之间插入间距,其插入的间距是在setSpacing(int)的基础上的,即是layout的控件间的间距为addSpacing值+setSpacing值。
需要注意的是layout布局的控件之间是有默认距离为10(即setSpacing默认设置为10)通过setSpacing(0)函数设置为0可使控件紧贴。>- 2、addStretch(int stretch = 0)是在layout的控件之间插入stretch个控件的间距。
- 3、addSpacerItem(QSpacerItem(int w, int h,QSizePolicy::Policy hData = QSizePolicy::Minimum,QSizePolicy::Policy vData = QSizePolicy::Minimum))
一般用在控件大小不等的时候。例如窗口的标题栏:部分控件的大小不变,空白区域允许拉长或缩短时。- 4、 需要注意的是当你设置了某些控件的大小时,再使用layout布局可能会有出乎意料的情况应该是两者之间存在了冲突。
QSplitter(分离部件)
QSplitter布局的两种方法:addWidget、父对象
QTextEdit *pEdit1=new QTextEdit(this);
QTextEdit *pEdit2=new QTextEdit(this);
QTextEdit *pEdit3=new QTextEdit(this);
pEdit1->setText("1");
pEdit2->setText("2");
pEdit3->setText("3");
QSplitter *pSplitterV=new QSplitter(Qt::Vertical,this);//上下分
pSplitterV->addWidget(edit1);//按顺序压入
pSplitterV->addWidget(edit2);
QSplitter *pSplitterH=new QSplitter(Qt::Horizontal,this);//左右分
pSplitterH->addWidget(pSplitterV);
pSplitterH->addWidget(edit3);
QVBoxLayout *pMainLayout = new QVBoxLayout(this);
pMainLayout->addWidget(pSplitterH)
-----------
| | |
|----| |
| | |
------------
QTabWidget添加自定义样式
对Tab页布局,是将要布局的Tab页点击为当前Tab页,而后在右侧点击QTabWidget进行布局,就是对Tab页布局了。这个还是让人有点费解,对子页布局居然是对父窗体进行布局。
//去除选项卡的关闭按钮
tabWidget->tabBar()->setTabButton(0, QTabBar::RightSide, nullptr);
QTabWidget边框的右边和下边,都多出了一条白边。大概2px宽
解决方法:
QTabWidget的documentMode属性复选框打钩即可。
取消documentMode后,选项卡下边会有一条白线,可在样式表里设置:
QTabWidget { border-top-color: rgba(255, 255, 255, 0); }
发现tabbar上面有一根线始终去不掉
QTabBar {
qproperty-drawBase: 0;
}
当tab个数大于一定个数时,会出现如下图左侧白线所示,这个是Qt自带的,作用是点击回到第一个tab,隐藏方法:
QTabBar::tear {
width: 0px;
border: none;
}
QTableWidget详解(样式、右键菜单、表头塌陷、多选等)
QTableWidget布局控件
Qt 笔记(1) 为QTableWidget设置自定义代理(myTable.zip)
QTableWidget实现QComboBox的代理且发送信号实现联动
设置代理
comb代理
常用代理总结
QTableWidget内存清理
QTableWidgetItem的析构
QTableWidget加载百万条数据不卡
ui->tableWidget->horizontalHeader->setSectionResizeMode(QHeaderView::ResizeToContens);
ui->tableWidget->setColumnCount(list.size());
ui->tableWidget->setHorizontalHeaderLabels(list);
ui->tableWidget->setDefaultValue(valueList);
ui->tableWidget->setItemDelegateForColumn(0,new QSpinBoxDelegate(32768,this));
//--------
ui->tableWidger->setColumncount(3);
ui->tableWidger->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄";
ui->tableWidger->setRowCount(5);
//ui->tableWidger->setItem(0,0,new QTableWidgetItem("张三"));
QList<QString> nameList;
nameList<<"张三"<<"李四"<<"王五"<<"张龙"<<"赵虎";
QStringList sexList;
sexList<<"男"<<"男"<<"女"<<"男"<<"女";
for(int i=0; i<5; i++)
{
int col=0;
ui->tableWidger->setItem(i,col++,new QTableWidgetItem(nameList[i]));//[]会直接崩掉
ui->tableWidger->setItem(i,col++,new QTableWidgetItem(nameList.at(i)));//at()会抛出异常
ui->tableWidger->setItem(i,col++,new QTableWidgetItem(QString::number(18+i)));
}
cell是一个绝对存在的容器,而item是一个被填入到cell中的一个实体,可以有也可以没有。
无论单元格中有没有 值,cellClicked()都能被发出,说明不管有没有值,都有这个容器在。
在单元格有值的情况下,itemClicked()才能被发出,说明必须要有值才有发出信号的实体。
connect(ui->tableWidget,&QTableWidget::itemClicked,this,&MainWindow::enter);
connect(ui->tableWidget,&QTableWidget::cellClicked,this,&MainWindow::enter);
// 返回鼠标单击的所在单元格的row和col
void PageProductInfo::show_prodcut_sets(int row,int col)
{
qDebug() << "所点击的单元格的row=" << row << ",col=" << col;
// 获取所点击的单元格
QTableWidgetItem* item = ui->tableWidget_right->item(row ,col);
qDebug() << item->text();
}
void MainWindow::gettheitem()
{
//获取当前点击的单元格的指针
QTableWidgetItem* curItem = ui->tableWidget->currentItem();
//获取单元格内的内容
QString wellName = curItem->text();
//输出内容
qDebug() << wellName;
}
QPushButton *button = dynamic_cast<QPushButton *>(QObject::sender()); //找到信号发送者
QModelIndex index = ui->tableWidget->indexAt(button->pos()); //定位按钮
QTableWidgetItem *item = ui->tableWidget->item(index.row(), 0); //得到item
QTableWidget::setCellWidget(int row, int column, QWidget *widget)//设置表格某行某列为QWidget
QTableWidget::setItem(int row, int column, QTableWidgetItem *item)//设置表格某行某列内容为QTableWidgetItem
QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::SelectionFlags command)//使用cell要有行列
QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
m_pTableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
QMenu * m_pTableMenu = new menu(m_pTableWidget);
connect(m_pTableWidget, &QTableWidget::customContextMenuRequested, this, [=](){
m_pTableMenu->exec(QCursor::pos());
});
QAction *pAction = new QAction("删除");
m_pTableMenu->addAction(pAction);
connect(pAction, &QAction::triggered, [=](){ });
ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
m_tabMenu = new QMenu(ui->tableWidget); //右键
action= new QAction("展示最近数据",this);
m_tabMenu->addAction(action);
connect(ui->tableWidget, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slot_DL_RcOnTw(QPoint)));
connect(action,SIGNAL(triggered(bool)),this,SLOT(slotActionInsert()));
void MainWindow::slot_DL_RcOnTw(QPoint pos)
{
m_tabMenu->exec(QCursor::pos());
}
右键删除所在行:
QTableView删除行,列
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
model = new QStandardItemModel;
QStringList slt;
slt<<QString::fromUtf8("第一列")<<QString::fromUtf8("第二列")<<QString::fromUtf8("第三列");
model->setHorizontalHeaderLabels(slt);
ui->tableView->setModel(model);
QList<QStandardItem *> qlist;
qlist << new QStandardItem("q")<<new QStandardItem("w")<<new QStandardItem("e");
model->appendRow(qlist);
qlist.clear();
qlist << new QStandardItem("qq")<<new QStandardItem("ww")<<new QStandardItem("ee");
model->appendRow(qlist);
qlist.clear();
qlist << new QStandardItem("qqq")<<new QStandardItem("www")<<new QStandardItem("eee");
model->appendRow(qlist);
qlist.clear();
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);//设置选择元素,以元素为单位
ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);//设置选择模式,
// ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选择行行为,以行为单位
// ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);//设置选择模式,选择单行
//ui->tableView->setSelectionBehavior(QAbstractItemView::SelectColumns);//设置选择列行为,以列为单位
//ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);//设置选择模式,选择单列
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);//右键点击菜单
menu = new QMenu(ui->tableView);
act = new QAction("删除当前行",this);
actcol = new QAction("删除当前列",this);
menu->addAction(act);
menu->addAction(actcol);
connect(ui->tableView,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(rightclickslot(QPoint)));
connect(act,SIGNAL(triggered(bool)),this,SLOT(deleteslotrow()));
connect(actcol,SIGNAL(triggered(bool)),this,SLOT(deleteslotcol()));
}
void MainWindow::rightclickslot(QPoint pos)
{
QModelIndex index = ui->tableView->indexAt(pos);
currentrow = index.row(); //保存所选行
currentcol = index.column();
qDebug()<<"index.data()"<<index.data().toString();
qDebug()<<"model->data(index)"<<model->data(index).toString();
qDebug()<<"currentrow"<<currentrow;
qDebug()<<"currentcol"<<currentcol;
if(index.isValid())
menu->exec(QCursor::pos());
}
void MainWindow::deleteslotrow()
{
QMessageBox message(QMessageBox::NoIcon,QString::fromUtf8("提示"),QString::fromUtf8("是否删除本行数据"),
QMessageBox::Yes | QMessageBox::No,NULL);
//如确认删除
if(message.exec() == QMessageBox::Yes)
{
model->removeRow(currentrow);
}
}
void MainWindow::deleteslotcol()
{
QMessageBox message(QMessageBox::NoIcon,QString::fromUtf8("提示"),QString::fromUtf8("是否删除本列数据"),
QMessageBox::Yes | QMessageBox::No,NULL);
//如确认删除
if(message.exec() == QMessageBox::Yes)
{
QMessageBox::information(NULL,QString::fromUtf8("提示"),QString::fromUtf8("就不让你删"));
//model->removeColumn(currentcol);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
QTableView右键删除(没在有效行上不弹出)
m_rightClickMenu = new QMenu(this); //右键点击菜单
auto deleteAction = new QAction(tr("删除"), this); //删除事件
m_rightClickMenu->addAction(deleteAction); //将action添加到菜单内
connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(SLot_Measure_Table_Click_Ritht_Menu(QPoint)));
connect(deleteAction,&QAction::triggered,this,[=]()
{
QList<int> rows;
QItemSelection selection = ui->tableView->selectionModel()->selection();
for (const QItemSelectionRange &selectionRange : selection)
{
for (int row = selectionRange.top(); row <= selectionRange.bottom(); ++row)
rows.append(row);
}
qSort(rows.begin(), rows.end(), qGreater<int>());
for (int row : rows)
m_model->removeRow(row);
});
void MainWidget::SLot_Measure_Table_Click_Ritht_Menu(QPoint pos)
{
QModelIndex index = ui->tableView->indexAt(pos); //找到tableview当前位置信息
if (index.isValid()) //如果行数有效,则显示菜单
{
m_rightClickMenu->exec(QCursor::pos());
}
}
QTableView的分页栏_制作
QTableView分页栏_使用
ui->tableWidget->setItemDelegateForColumn(0, new QDoubleSpinBoxDelegate(30.000,3.000,3,this);
ui->tableWidget->item(i,1)->data(Qt::DisplayRole).toDouble()*1e6;
m_pModel = new QStandardItemModel(this);
m_pModel->setHorizontalHeaderLabels(QStringList()<<"频率"<<"带宽");
ui->tableView->setModel(m_pModel);
m_pModel->romoveRows(0,m_pModel->rowCounts());
QList<QStandardItem*> itemList;
itemList.append(new QStandardItem(QString::number(freq/1e6,'f',6)));
m_pModel->insertRow(0,itemList);
QTableView固定某列宽 其他列宽自适应填充伸展
注:列宽的设置需要放在setModel之后,否则会出现异常现象
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); //所有列都扩展自适应宽度,填充充满整个QTableView宽度
horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);//对第0列单独设置固定宽度
setColumnWidth(0, 50);//设置固定宽度
ui->tableWidget->scrollToBottom(); //让滚动条滚动到最底部
ui->tableWidget->scrollToTop(); //让滚动条滚动到最顶部
不可编辑:
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//不可编辑
//.h 文件
class GComboxDelegate : public QItemDelegate
{
Q_OBJECT
public:
GComboxDelegate(QObject * parent = nullptr);
~GComboxDelegate();
//编辑单元格时调用函数
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//取单元格里面的内容更新QComboBox的值
void setEditorData(QWidget *editor, const QModelIndex &index) const;
//QComboBox的值设置到单元格中,在这里面可以发送消息
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
signals:
void OnEmitCurrentIndexChangeSignal(int iRow, int iColumn , int iId ) const; //定义消息必须有const
private:
};
//.cpp中
//编辑单元格时调用函数
QWidget *GComboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if ( index.isValid() && index.column() == 1 ) // 1 代表列
{
QComboBox *editor = new QComboBox(parent); //创建QComboBox
editor->setEditable(true);
editor->installEventFilter(const_cast<GComboxDelegate *>(this));
return editor;
}
else
{
return QItemDelegate::createEditor(parent, option, index);
}
}
//取单元格里面的内容更新QComboBox的值
void GComboxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if ( index.isValid() && index.column() == 1) // 1 代表列
{
QString value = index.model()->data(index, Qt::DisplayRole).toString(); //取单元格内容更新QComBoBox
QComboBox *combox = static_cast<QComboBox *>(editor);
combox->addItem( "男" ); //QComboBox中增加可选项
combox->setItemData(0, 1,Qt::UserRole); //增加附加数据
combox->addItem( "女" ); //QComboBox中增加可选项
combox->setItemData(1, 1,Qt::UserRole); //增加附加数据
combox->setCurrentText(value); //设置选择项
}
else
{
QItemDelegate::setEditorData(editor, index);
}
}
//QComboBox的值设置到单元格中,在这里面可以发送消息
void GComboxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if ( index.isValid() && index.column() == 1 ) //1代表列
{
QComboBox *combox = static_cast<QComboBox *>(editor);
model->setData(index, combox->currentText(), Qt::DisplayRole); //设置单元格内容
int iType= combox->currentData(Qt::UserRole).toInt(); //取出当前选中的QComboBox的附加数据
model->setData(index, iType, Qt::UserRole); //设置单元格附加数据
emit OnEmitCurrentIndexChangeSignal(index.row(),index.column(), iType); //发送信号,实现其它联动更新
else
{
QItemDelegate::setModelData(editor, model, index);
}
}
//使用代理
GComboxDelegate IdentityType = new GComboxDelegate(this); //定义变量
ui->tableWidget->setItemDelegateForColumn(1, IdentityType ); //第一列设置代理
connect(IdentityType, SIGNAL(OnEmitCurrentIndexChangeSignal(int,int,int)), this, SLOT(OnIndexChangeSlot(int,int,int))); //绑定信号槽函数,在槽函数中处理联动信息。
//槽函数定义
public slots:
void OnIndexChangeSlot(int iRow,int iColumn,int iType); //可不加const
QTableView基本使用
Qt Model/View 学习(5) - QTableView(优雅)使用教程
QTableView实现鼠标悬浮(hover)行高亮显示
QStandardItemModel(2.超级详细函数)
// 遍历QTableView所有行
int rows = ui->tableView1->model()->rowCount();
for(int r = 0; r < rows; r++)
{
qDebug() << ui->tableView1->model()->index(r,0).data().toString();
}
// QTableView选中所有行
QItemSelectionModel *selections = ui->tableView1->selectionModel();
QModelIndexList selected = selections->selectedRows();
for (int i = 0; i < selected.count(); i++)
{
QString name = standardItemModel->index(selected.at(i).row(), 0).data().toString();
}
解决QTableview加载百万行数据卡顿问题:核心思想是将model放入线程中
QStandardItemModel* model = new QStandardItemModel(); //创建数据模型
QItemSelectionModel *theSelection; //选择模型
ui->tableView->setModel(model);
model->setHorizontalHeaderLabels({"学号", "姓名", "考试题目"});
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
model->setItem(row, col, new QStandardItem("text"));
theSelection = new QItemSelectionModel (model) ;//选择模型
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)), this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
ui->tableView->setSelectionModel(theSelection); //设置选择模型
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
//ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选中模式为选中行
ui->tableView->setSelectionMode ( QAbstractItemView::SingleSelection);//禁止选择多行
void MainWindow::on_currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{ //选择单元格变化时的响应
if (current.isValid())
{
LabCellPos->setText (QString::asprintf ("当前单元格:%d 行,%d 列", current.row(),current.column()));
QStandardItem* aItem=theModel->itemFromIndex(current);
this->LabCellText->setText ("单元格内容:"+aItem->text());
QFont font=aItem->font();
ui->actFontBold->setChecked(font.bold());
}
}
QAbstractTableModel[官翻]
QAbstractTableModel基本操作
QAbstractTableModel基本使用:数据加载以及增删行列
QTableView Optimization
Qt中QTreeview、QLIstView、QTableview等更新数据model时内存泄漏的问题
解决内存泄漏的方法是:将model删除,并重新给view赋新model。原因是QAbstractTableModel自身并没有清空占用的内存。
void setData()
{
delete ui->tableView->model();
ui->tableView->setModel(nullptr); // 或新model
}
void Widget::onDeleteALLTriggered()
{
int count=m_pModel->rowCount();
m_pModel->removeRows(0,count);
}
继承QAbstractTableModel,必须实现3个纯虚函数rowcount,columncount,data。
rowCount 代表 table 总的行数,columnCount 代表 table 总的列数,data 代表某个单元格的内容(最重要的函数),headerData 代表每一列(或每一行)表头的内容
这个是使用QMap的:QTableView效率优化2 - 自定义Model秒级加载百万行数据
这个是使用QList的:qtableview及自定义model的使用
#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H
#include
#include
struct ModelItem {
QString id;
QString name;
QString one;
QString two;
QString three;
QString four;
QString five;
QString six;
};
class MyTableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit MyTableModel(QObject *parent = nullptr);
~MyTableModel();
int rowCount(const QModelIndex &parent = QModelIndex())const override;
int columnCount(const QModelIndex &parent = QModelIndex())const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
//bool insertRows(int row, int count,const QModelIndex &parent = QModelIndex());
virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
void SetDeleteList(QList<int> i_List);
void SetHeadData(QStringList i_list);
void SetModelData(QList<ModelItem> model);
signals:
private:
QList<ModelItem> modelData;
QStringList headeList;
QList<int> m_DeleteList;
};
#endif // MYTABLEMODEL_H
#include "mytablemodel.h"
#include
#include
MyTableModel::MyTableModel(QObject *parent)
{
}
MyTableModel::~MyTableModel()
{
}
int MyTableModel::rowCount(const QModelIndex &parent) const
{
return modelData.count();
}
int MyTableModel::columnCount(const QModelIndex &parent) const
{
return headeList.size();
}
QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
if (section < headeList.size())
{
return headeList[section];
}
}
return QAbstractItemModel::headerData(section, orientation, role);
}
bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(!index.isValid())
return 0;
if(role == Qt::DisplayRole || role == Qt::EditRole)
{
const int row=index.row();
switch(index.column())
{
case 0: modelData[row].id=value.toString();break;
case 1:modelData[row].name=value.toString();break;
case 2:modelData[row].one=value.toString();break;
case 3:modelData[row].two=value.toString();break;
case 4:modelData[row].three=value.toString();break;
case 5:modelData[row].four=value.toString();break;
case 6:modelData[row].five=value.toString();break;
case 7:modelData[row].six=value.toString();break;
}
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
//bool MyTableModel::insertRows(int row, int count,const QModelIndex &parent)
//{
if(row<0||count<1||row>rowCount())
return false;
//需要将操作放到beginInsertRows和endInsertRows两个函数调用之间
beginInsertRows(parent, row, row + count - 1);
for(int i=row;i<row+count;i++)
{
//在接口对应行插入空数据
modelData.insert(i,ModelItem);
}
endInsertRows();
// // return true;
//}
bool MyTableModel::removeRows(int row, int count, const QModelIndex &parent)
{
if(row<0||count<1||row+count>rowCount())
return false;
//需要将操作放到beginRemoveRows和endRemoveRows两个函数调用之间
beginRemoveRows(parent, row, row + count - 1);
if(m_DeleteList.size()!=0)
{
for(int i=0;i<m_DeleteList.size();i++)
{
modelData.removeAt(m_DeleteList[i]);
}
}
// for(int i=row+count-1;i>=row;i--)
// {
// //移除该行数据
// modelData.removeAt(i);
// }
m_DeleteList.clear();
endRemoveRows();
return true;
}
void MyTableModel::SetDeleteList(QList<int> i_List)
{
m_DeleteList=i_List;
}
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
if(role == Qt::DisplayRole || role == Qt::EditRole)
{
const int row=index.row();
switch(index.column())
{
case 0: return modelData.at(row).id;
case 1:return modelData.at(row).name;
case 2:return modelData.at(row).one;
case 3:return modelData.at(row).two;
case 4:return modelData.at(row).three;
case 5:return modelData.at(row).four;
case 6:return modelData.at(row).five;
case 7:return modelData.at(row).six;
}
}
return QVariant();
}
void MyTableModel::SetHeadData(QStringList i_list)
{
headeList=i_list;
}
void MyTableModel::SetModelData(QList<ModelItem> model)
{
modelData=model;
}
添加行、删除行:
bool MyTableModel::insertRows(int row, int count, const QModelIndex &parent)
{
//row为0就是开始,为rowcount就在尾巴
if(row<0||count<1||row>rowCount())
return false;
//需要将操作放到beginInsertRows和endInsertRows两个函数调用之间
beginInsertRows(parent, row, row + count - 1);
for(int i=row;i<row+count;i++)
{
//在接口对应行插入空数据
modelData.insert(i,MyModelItem());
}
endInsertRows();
return true;
}
bool MyTableModel::removeRows(int row, int count, const QModelIndex &parent)
{
if(row<0||count<1||row+count>rowCount())
return false;
//需要将操作放到beginRemoveRows和endRemoveRows两个函数调用之间
beginRemoveRows(parent, row, row + count - 1);
for(int i=row+count-1;i>=row;i--)
{
//移除该行数据
modelData.removeAt(i);
}
endRemoveRows();
return true;
}
自定义数据:
pItem->setData(Qt::UserRole, QVariant::fromValue(user)); // 设置用户数据
QVariant variant = item->data(Qt::UserRole); // 获取用户数据
QVariant var;
var.setValue(12);
int data=var.toInt();
//自定义结构体
struct MyClass{
int id;
QString name;
};
Q_DECLARE_METATYPE(MyClass)
QVariant var = QVariant::fromValue(info); //结构体
var.setValue(info);
CInfo info= var.value<CInfo>()
QThread m_thread;
m_model->moveToThread(&m_thread);
connect(&m_thread, &QThread::finished, &m_thread,&QObject::deleteLater);
connect(&m_thread, &QThread::finished, m_model, &QObject::deleteLater);
m_thread.start();
//添加数据前:
TableView->setUpdatesEnabled(false); //暂停界面刷新
...添加大量数据过程...
//添加完毕后:
TableView->setUpdatesEnabled(true); //恢复界面刷新
默认不显示排序图标,点击表头显示排序图标,进行排序
m_tableView->setSortingEnabled(false); // 不设置排序
m_tableView->horizontalHeader()->setSortIndicatorShown(false); // 隐藏排序图标
// 信号发出,进行排序以及图标显示
connect(m_tableView->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, [this](int logicalIndex, Qt::SortOrder order) {
qDebug() << logicalIndex << order;
if (0 == logicalIndex) {
this->m_model->sort(0, order);
m_tableView->horizontalHeader()->setSortIndicatorShown(true);
}
});
Qt自定义点击表头排序,使支持恢复默认顺序
浮动窗口Advanced-Docking-System
m_pDock1 = new QDockWidget("参数1", this);
m_pDock1->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
m_pDock1->setWidget(new ParamWidget1);
//去除标题栏
QWidget* lTitleBar = m_pDock1->titleBarWidget();
QWidget* lEmptyWidget = new QWidget(this);
m_pDock1->setTitleBarWidget(lEmptyWidget);
delete lTitleBar;
m_pDock2 = new QDockWidget("参数2", this);
m_pDock2->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
m_pDock2->setWidget(new ParamWidget2);
//去除标题栏
QWidget* lTitleBar2 = m_pDock2->titleBarWidget();
QWidget* lEmptyWidget2 = new QWidget(this);
m_pDock2->setTitleBarWidget(lEmptyWidget2);
delete lTitleBar2;
addDockWidget(Qt::RightDockWidgetArea, m_pDock1);
addDockWidget(Qt::RightDockWidgetArea, m_pDock2);
tabifyDockWidget(m_pDock1, m_pDock2);
// m_pDock1->show();
m_pDock1->raise();
// m_pDock1->setMaximumWidth(150);
m_pDock1->setMinimumWidth(150);
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::East);
QTreeWidget添加项目例子
QTreeWidget增删改查
QTreeWidget设置Delegate
QTreeWidget控件使用方法(复选框)
QTreeWidget和QDockWidget
QTreeWidget勾选QTreeWidgetItem的处理
QTreeWidget 弹出右键菜单
QTreeWidget右键菜单
QTreeWidget:拖拽项目
QTreeWidget连线样式设置
QTtreeWidget节点显示隐藏
treeWidget->setStyleSheet("QTreeView::branch {image:none;}");//去掉前面的三角
treeWidget->setStyleSheet("QTreeWidget::branch:has-siblings:!adjoins-item{border-image:none;}");//去掉连线
QTreeWidget 中加入控件——以QPushButton为例:
//添加控件,为item的第几列设置一个widget控件
void QTreeWidget::setItemWidget ( QTreeWidgetItem * item, int column, QWidget * widget );
//获取控件,获取item列里面的控件时的方法为:
QWidget * QTreeWidget::itemWidget ( QTreeWidgetItem * item, int column );
//添加按钮的例子---setItemWidget()----------
auto topLevelItem = new QTreeWidgetItem(); //创建一个 TreeItem 容器用于后来装载控件
ui->treeWidget->addTopLevelItem(topLevelItem); //目的是添加一行 Item
//设置 Item 内控件,0 是第几列
QPushButton *topLevelButton = new QPushButton("Top Level Button");
ui->treeWidget->setItemWidget(topLevelItem, 0, topLevelButton);
connect(topLevelButton, &QPushButton::clicked,)),
this,&Widget::startTask);
//多层--(指定父窗体)----
QTreeWidgetItem *items3 = new QTreeWidgetItem(tree,QStringList(QString("num_13")));
QTreeWidgetItem *item104 = new QTreeWidgetItem(items3,QStringList(QString("item104")));
//多层--(addChild)-----
QStringList strList;
strList<<"名称"<<"年龄"<<"性别";
ui->treeWidget->setHeaderLabels(strList);
ui->treeWidget->header()->setStyleSheet(sstyle);
QTreeWidgetItem *item1 = new QTreeWidgetItem(QStringList()<<"七年级");
ui->treeWidget->addTopLevelItem(item1);
QTreeWidgetItem *item11 = new QTreeWidgetItem(QStringList()<<"小涨"<<"13"<<"男");
item1->addChild(item11);
QTreeWidgetItem *item12 = new QTreeWidgetItem(QStringList()<<"小红"<<"14"<<"女");
item1->addChild(item12);
QTreeWidgetItem *item13 = new QTreeWidgetItem(QStringList()<<"小丽"<<"13"<<"女");
item1->addChild(item13);
QTreeWidgetItem *item2 = new QTreeWidgetItem(QStringList()<<"八年级");
ui->treeWidget->addTopLevelItem(item2);
QTreeWidgetItem *item21 = new QTreeWidgetItem(QStringList()<<"小涨"<<"13"<<"男");
item2->addChild(item21);
QTreeWidgetItem *item22 = new QTreeWidgetItem(QStringList()<<"小红"<<"14"<<"女");
item2->addChild(item22);
QTreeWidgetItem *item23 = new QTreeWidgetItem(QStringList()<<"小丽"<<"13"<<"女");
item2->addChild(item23);
//--------------------------
//添加一级节点
QTreeWidgetItem *items1 = new QTreeWidgetItem(tree,
QStringList(QString("num_1")));
QTreeWidgetItem *items2 = new QTreeWidgetItem(tree,
QStringList(QString("num_1")));
QTreeWidgetItem *items3 = new QTreeWidgetItem(tree,
QStringList(QString("num_3")));
//查找节点,查找与num_1完全一致的项,并返回其指针列表。
QList<QTreeWidgetItem*> s = tree->findItems("num_1", Qt::MatchFlag::MatchExactly);
// 无情删除
for (auto item : s) {
delete item;
}
//随着子项的展开,自动出现横滚动条
m_pTreeList->header()->setHidden(true);
m_pTreeList->header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
m_pTreeList->header()->setResizeMode(0, QHeaderView::ResizeToContents);
m_pTreeList->header()->setStretchLastSection(false);
m_pTreeList->setTextElideMode(Qt::ElideNone);
QTreeWidgetItem *parentItem = ui->treeWidget->topLevelItem(0); //获取顶级节点
QTreeWidgetItem *newItem = new QTreeWidgetItem(parentItem); //创建子节点
newItem->setFirstColumnSpanned(true); //设置子节点跨越所有列(PS:否则它的宽度只有第一列的宽度)
CustomWidget *widget = new CustomWidget(this); //初始化 待嵌套的 widget
ui->treeWidget->setItemWidget(newItem, 0, widget); //设置 QTreeWidget 嵌套 widget
添加自定义控件的关键是QTreewidget::SetItemWidget方法,而QTreeview没有SetItemWidget这个方法,只能使用QDelegate设置代理实现。
(5)QTreeWidget添加下拉框太大且不上下居中的解决方法
QComboBox *m_pStyle = new QComboBox(this);
m_pStyle->addItems(QStringList()<<"大"<<"小");
m_pStyle->setStyleSheet("min-height:10; QComboBox::down-arrow{min-height:10;}");
QTreeWidgetItem *pTreeItemStyle = new QTreeWidgetItem(pTreeItemTop1);
pTreeItemStyle->setText(0,"样式");
m_pTree->setItemWidget(pTreeItemStyle, 1, m_pStyle);
QEvent::Type参数值:
0 - 999:系统保留
1000-65535:用户定义
Qt自定义事件的三种方法
Qt中的消息通知和事件发送
QT事件传递与事件过滤器
//appendPlainText()会一直累加内存,到100行清除
if(ui->plainTextEdit->blockCount()>100)
{
ui->plainTextEdit->setPlainText("");
}
ui->plainTextEdit->appendPlainText(str);
// 删除换行,下次是加到末尾
void ConsoleDialog::appendMessageToEditor(const QString &message)
{
ui->textEdit->appendPlainText(message);
ui->textEdit->moveCursor(QTextCursor::End);
ui->textEdit->textCursor().deletePreviousChar();
}
ui->textBrowser->insertPlainText(QString::number(value,'f',6));
ui->textBrower->textCursor().insertText("aaaa");
// 文本输出结束后自动换行
ui->textBrowser->moveCursor(QTextCursor::End);
ui->textBrowser->append(QString(""));
//调整当前显示的区域,仿迅雷设置可用此
ui->scrollArea->ensureVisible(30, position);
//代码加窗体
QGridLayout *pLayout = new QGridLayout();
for(int i = 0; i < 100; i++)
{
QPushButton *pBtn = new QPushButton();
pBtn->setText(QString("按钮%1").arg(i));
pBtn->setMinimumSize(QSize(60,30));
pLayout->addWidget(pBtn);
}
ui->scrollArea->widget()->setLayout(pLayout);
ui->combox->addItem(str);
ui->combox->addItem(str, data); //绑定数据data
ui->combox->setCurrentIndex(-1); //界面为空
ui->combox->setItemData(0,23);
int data = ui->combox->currentData().toInt();
ui->comBox->currentIndex(); //索引值
ui->comBox->currentText(); //界面文字
ui->comBox->currentData(); //绑定值
addButton()不指定按钮的id,默认是从-2开始,实际经常从0开始,需逐个指定按钮的id。
//.h中
public slots:
void sltBtnGroupClicked(int nIndex);
//.cpp中
{
QButtonGroup* pBtnGroup = new QButtonGroup(this);
ui->btnCPlush->setCheckable(true); //重要
ui->btnJava->setCheckable(true);
ui->btnPython->setCheckable(true);
pBtnGroup->addButton(ui->btnCPlush, 0);
pBtnGroup->addButton(ui->btnJava, 1);
pBtnGroup->addButton(ui->btnPython, 2);
void(QButtonGroup:: *btnGroupClicked)(int) = &QButtonGroup::buttonClicked;
void(QtWidgetsApplication1:: *sltBtnGroupClicked)(int) = &QtWidgetsApplication1::sltBtnGroupClicked;
connect(pBtnGroup, btnGroupClicked,this, sltBtnGroupClicked);
// 第一个页面默认选中
ui.btnCPlush->setChecked(true);
ui.stackedWidget->setCurrentWidget(ui.btnCPlush);
}
void QtWidgetsApplication1::sltBtnGroupClicked(int nIndex)
{
ui.stackedWidget->setCurrentIndex(nIndex);
}
使用QtCreator创建lvgl开发环境
Qt开源库-【工具选项卡TabToolBar】
QRegExp rx("\\b(?:(?:25[0-5] | 2[0-4][0-9] | [01]?[0-9][0-9]?)\\.){3}(?:25[0-5] | 2[0-4][0-9] | [01]?[0-9][0-9]?)\\b)");
ui->leLocalIP->setValidator(new QRegExpValidator(rx,this));
ui->leLocalIP->setInputMask("000.000.000.000");
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);// set transparent
qt5 仪表控件 码盘 电压表 油表 开源不装逼
汽车仪表控件系列文章
Qt自定义精美的仪表盘控件(汽车仪表、指南针、雷达、摇杆)
Qt精美控件
汽车仪表盘–飞扬青云
汽车仪表盘–飞扬青云2
汽车仪表盘–解析
车速仪表盘
仪表盘
使用QT绘制雷达扫描效果
Qt 雷达模拟仿真工具
飞机仪表(飞扬青云)
表盘(青云)
圆弧仪表盘(青云)
速度仪表盘
云台仪表盘
温度计
柱状标尺
Qt开源炫酷界面QCoolPage–CylinderControl
仪表盘
一款有意思的qt飞行仪表控件
https://github.com/wyyrepo/QFlightInstruments
Cockpit-GUI-Design
Qt飞行器仪表盘库(无代码)
早期版本
早期版本使用例子
5.12版源码
官方持续更新版(5.12可用)
QtPropertyBrowser(GitHub下载)
QtnProperty第三方
QtTreePropertyBrowser使用示例
Qt属性表控件的使用 QtTreePropertyBrowser
QtTreePropertyBrowser表头、遍历
qtTteePropertyWidget添加按钮
QtPropertyBrowser 包括:
m_pVarManager = new QtVariantPropertyManager(ui->propertyWidget);
m_pVarFactory = new QtVariantEditorFactory(ui->propertyWidget);
connect(m_pVarManager, &QtVariantPropertyManager::valueChanged, this, &Widget::slt_propertyValueChanged);
//树控件单击的项名称
void Widget::initPropertyWidget(QString name)
{
ui->propertyWidget->clear();
m_vItems.clear();
QtVariantProperty *pItem = m_pVarManager->addProperty(QtVariantPropertyManager::enumTypeId(), "下拉框");
pItem->setAttribute("enumNames", QStringList()<<"选项0"<<"选项1");
pItem->setValue(1);
ui->propertyWidget->addProperty(pItem);
m_vItems.append(pItem);
m_mapItems.insert("broaditem", pItem);
pItem = m_pVarManager->addProperty(QVariant::Int, "整数项");
pItem->setValue(100);
ui->propertyWidget->addProperty(pItem);
m_vItems.append(pItem);
m_mapItems.insert("uuu", pItem);
pItem = m_pVarManager->addProperty(QVariant::Double, "doble项");
pItem->setValue(66.8);
pItem->setAttribute("decimals",3);
pItem->setAttribute("maximum", 1);
pItem->setAttribute("maximum", 6000);
ui->propertyWidget->addProperty(pItem);
m_vItems.append(pItem);
m_mapItems.insert("uuu", pItem);
pItem = m_pVarManager->addProperty(QVariant::String, "信息");
pItem->setValue("hggfffg");
QRegExp reg("[(a-z)(A-Z)(0-9)(\u4e00-\u9fa5)(\uFF00-\uFFFF)(\0000-\u00FF)"']{1,50}$");
pItem->setAttribute("regExp", reg);
}
void Widget::slt_propertyValueChanged(QtProperty *property, const QVariant &value)
{
if(property == m_mapItems["ddd"])
{
double ff = value.toDouble();
}
if(property->proPertyName() == "ddd")
{
QList<QtProperty*> listProperty = property->subProperties();
for(int i = 0; i < listProperty.count(); ++i)
{
property->removeSubProperty(listProperty.at(i));
}
for(int i = 0; i < newCount; ++i)
{
QProperty *pProperty = new QtProperty(m_pVarManager);
pProperty->setPropertyName("工厂1");
property->addSubProperty(pProperty);
QtVariantProperty *pItem = m_pVarManager->addProperty(QVariant::double,"资产");
pProperty->addSubProperty(pItem);
}
}
}
//qtpropertybrowserutils.cpp
QString QtPropertyBrowserUtils::dateTimeFormat()
{
return QString("yyyy-MM-dd hh:mm:ss");
}
初次刷新和单击树项时刷新不显示:
void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item)
{
QtProperty *property = m_itemToIndex[item]->property();
QIcon expandIcon;
if (property->hasValue()) {
const QString valueToolTip = property->valueToolTip();
const QString valueText = property->valueText();
item->setToolTip(1, valueToolTip.isEmpty() ? valueText : valueToolTip);
item->setIcon(1, property->valueIcon());
item->setText(1, valueText);
if(valueText == "True" || valueText == "False" ) //不显示true、false----
item->setText(1, "");
单击checkBox和改变值时不显示:
QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property,
QWidget *parent)
{
QtBoolEdit *editor = d_ptr->createEditor(property, parent);
editor->setChecked(manager->value(property));
editor->setTextVisible(false); //不显示true、false
https://github.com/qtinuum/QtnProperty
在QtTreePropertyBrowser中添加一个公有函数:
void QtTreePropertyBrowser::setHeaderLables(const QStringList &labels)
{
d_ptr->m_treeWidget->setHeaderLabels(labels);
}
Qt : d指针和q指针
pimpl模式(私有化实现)是为了二进制兼容,更新库时不需重新编译。一个主类,一个私有类。
d_ptr:是主类中指向私有类(Private)的指针
q_ptr:是私有类中指向主类的指针
//主类中(QtTreePropertyBrowser)
class QtTreePropertyBrowserPrivate;
class QtTreePropertyBrowser : public QtAbstractPropertyBrowser
{
Q_OBJECT
public:
QtTreePropertyBrowser(QWidget *parent = 0);
~QtTreePropertyBrowser();
Q_SIGNALS:
void collapsed(QtBrowserItem *item);
void expanded(QtBrowserItem *item);
private:
QScopedPointer<QtTreePropertyBrowserPrivate> d_ptr; //d指针
Q_DECLARE_PRIVATE(QtTreePropertyBrowser)
Q_DISABLE_COPY(QtTreePropertyBrowser)
Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &)) //(私有类指针,槽)
Q_PRIVATE_SLOT(d_func(), void slotExpanded(const QModelIndex &))
Q_PRIVATE_SLOT(d_func(), void slotCurrentBrowserItemChanged(QtBrowserItem *))
Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *))
}
QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent)
: QtAbstractPropertyBrowser(parent), d_ptr(new QtTreePropertyBrowserPrivate)
{
d_ptr->q_ptr = this;
d_ptr->init(this);
connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*)));
}
//私有类中(QtTreePropertyBrowserPrivate)
class QtTreePropertyBrowserPrivate
{
QtTreePropertyBrowser *q_ptr; //q指针
Q_DECLARE_PUBLIC(QtTreePropertyBrowser)
public:
QtTreePropertyBrowserPrivate();
void init(QWidget *parent);
void slotCollapsed(const QModelIndex &index);
void slotExpanded(const QModelIndex &index);
void slotCurrentBrowserItemChanged(QtBrowserItem *item);
void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *);
}
void QtTreePropertyBrowserPrivate::init(QWidget *parent)
{
m_treeWidget = new QtPropertyEditorView(parent);
//这里用QObject::connect是因为QtTreePropertyBrowserPrivate不是QObject子类
QObject::connect(m_treeWidget, SIGNAL(collapsed(QModelIndex)), q_ptr, SLOT(slotCollapsed(QModelIndex)));
QObject::connect(m_treeWidget, SIGNAL(expanded(QModelIndex)), q_ptr, SLOT(slotExpanded(QModelIndex)));
QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
}
//用到的宏定义(qglobal.h)
#define Q_DECLARE_PRIVATE(Class) \
inline Class##Private* d_func() \
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr));) } \
inline const Class##Private* d_func() const \
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr));) } \
friend class Class##Private;
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
inline Class##Private* d_func() \ //返回d指针
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<Class##Private *>(qGetPtrHelper(Dptr));) } \
inline const Class##Private* d_func() const \
{ Q_CAST_IGNORE_ALIGN(return reinterpret_cast<const Class##Private *>(qGetPtrHelper(Dptr));) } \
friend class Class##Private;
#define Q_DECLARE_PUBLIC(Class) \
inline Class* q_func() { return static_cast<Class *>(q_ptr); } \ //返回q指针
inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
friend class Class;
#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()
QtTreePropertyBrowser : public QtAbstractPropertyBrowser
class QtTreePropertyBrowser : public QtAbstractPropertyBrowser
class QtAbstractPropertyBrowser : public QWidget
{
//private类中
QList<QtProperty *> properties() const;
QList<QtBrowserItem *> items(QtProperty *property) const;
QList<QtBrowserItem *> topLevelItems() const;
}
class QtProperty
{
QtAbstractPropertyManager * const m_manager; //d_ptr->m_manager;
private:
friend class QtAbstractPropertyManager; //两个相互friend
};
class QtBrowserItem
{
//private类中
QtAbstractPropertyBrowser * const m_browser;
QtProperty *m_property;
QtBrowserItem *m_parent;
private:
friend class QtAbstractPropertyBrowserPrivate;
};
class QtVariantPropertyManager : public QtAbstractPropertyManager
class QtAbstractPropertyManager : public QObject
{
private:
friend class QtProperty;
};
class QtVariantEditorFactory : public QtAbstractEditorFactory<QtVariantPropertyManager>
template <class PropertyManager>
class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase
{
private:
QSet<PropertyManager *> m_managers;
friend class QtAbstractPropertyEditor;
};
class QtAbstractEditorFactoryBase : public QObject
{
friend class QtAbstractPropertyBrowser;
};
class QtVariantEditorFactory : public QtAbstractEditorFactory<QtVariantPropertyManager>
class QtSpinBoxFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
class QtSliderFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
class QtScrollBarFactory : public QtAbstractEditorFactory<QtIntPropertyManager>
class QtCheckBoxFactory : public QtAbstractEditorFactory<QtBoolPropertyManager>
class QtDoubleSpinBoxFactory : public QtAbstractEditorFactory<QtDoublePropertyManager>
class QtLineEditFactory : public QtAbstractEditorFactory<QtStringPropertyManager>
class QtDateEditFactory : public QtAbstractEditorFactory<QtDatePropertyManager>
class QtTimeEditFactory : public QtAbstractEditorFactory<QtTimePropertyManager>
class QtDateTimeEditFactory : public QtAbstractEditorFactory<QtDateTimePropertyManager>
class QtKeySequenceEditorFactory : public QtAbstractEditorFactory<QtKeySequencePropertyManager>
class QtCharEditorFactory : public QtAbstractEditorFactory<QtCharPropertyManager>
class QtEnumEditorFactory : public QtAbstractEditorFactory<QtEnumPropertyManager>
class QtCursorEditorFactory : public QtAbstractEditorFactory<QtCursorPropertyManager>
class QtColorEditorFactory : public QtAbstractEditorFactory<QtColorPropertyManager>
class QtFontEditorFactory : public QtAbstractEditorFactory<QtFontPropertyManager>
int QtVariantPropertyManagerPrivate::internalPropertyToType(QtProperty *property) const
{
int type = 0;
QtAbstractPropertyManager *internPropertyManager = property->propertyManager();
if (qobject_cast<QtIntPropertyManager *>(internPropertyManager))
type = QVariant::Int;
else if (qobject_cast<QtEnumPropertyManager *>(internPropertyManager))
type = QtVariantPropertyManager::enumTypeId();
else if (qobject_cast<QtBoolPropertyManager *>(internPropertyManager))
type = QVariant::Bool;
else if (qobject_cast<QtDoublePropertyManager *>(internPropertyManager))
type = QVariant::Double;
return type;
}
QVariant QtVariantPropertyManager::value(const QtProperty *property) const
{
QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
if (internProp == 0)
return QVariant();
QtAbstractPropertyManager *manager = internProp->propertyManager();
if (QtIntPropertyManager *intManager = qobject_cast<QtIntPropertyManager *>(manager)) {
return intManager->value(internProp);
} else if (QtDoublePropertyManager *doubleManager = qobject_cast<QtDoublePropertyManager *>(manager)) {
return doubleManager->value(internProp);
} else if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager)) {
return boolManager->value(internProp);
} else if (QtStringPropertyManager *stringManager = qobject_cast<QtStringPropertyManager *>(manager)) {
return stringManager->value(internProp);
} else if (QtDatePropertyManager *dateManager = qobject_cast<QtDatePropertyManager *>(manager)) {
return dateManager->value(internProp);
} else if (QtTimePropertyManager *timeManager = qobject_cast<QtTimePropertyManager *>(manager)) {
return timeManager->value(internProp);
} else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast<QtDateTimePropertyManager *>(manager)) {
return dateTimeManager->value(internProp);
} else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast<QtKeySequencePropertyManager *>(manager)) {
return QVariant::fromValue(keySequenceManager->value(internProp));
} else if (QtCharPropertyManager *charManager = qobject_cast<QtCharPropertyManager *>(manager)) {
return charManager->value(internProp);
} else if (QtLocalePropertyManager *localeManager = qobject_cast<QtLocalePropertyManager *>(manager)) {
return localeManager->value(internProp);
} else if (QtPointPropertyManager *pointManager = qobject_cast<QtPointPropertyManager *>(manager)) {
return pointManager->value(internProp);
} else if (QtPointFPropertyManager *pointFManager = qobject_cast<QtPointFPropertyManager *>(manager)) {
return pointFManager->value(internProp);
} else if (QtSizePropertyManager *sizeManager = qobject_cast<QtSizePropertyManager *>(manager)) {
return sizeManager->value(internProp);
} else if (QtSizeFPropertyManager *sizeFManager = qobject_cast<QtSizeFPropertyManager *>(manager)) {
return sizeFManager->value(internProp);
} else if (QtRectPropertyManager *rectManager = qobject_cast<QtRectPropertyManager *>(manager)) {
return rectManager->value(internProp);
} else if (QtRectFPropertyManager *rectFManager = qobject_cast<QtRectFPropertyManager *>(manager)) {
return rectFManager->value(internProp);
} else if (QtColorPropertyManager *colorManager = qobject_cast<QtColorPropertyManager *>(manager)) {
return colorManager->value(internProp);
} else if (QtEnumPropertyManager *enumManager = qobject_cast<QtEnumPropertyManager *>(manager)) {
return enumManager->value(internProp);
} else if (QtSizePolicyPropertyManager *sizePolicyManager =
qobject_cast<QtSizePolicyPropertyManager *>(manager)) {
return sizePolicyManager->value(internProp);
} else if (QtFontPropertyManager *fontManager = qobject_cast<QtFontPropertyManager *>(manager)) {
return fontManager->value(internProp);
#ifndef QT_NO_CURSOR
} else if (QtCursorPropertyManager *cursorManager = qobject_cast<QtCursorPropertyManager *>(manager)) {
return cursorManager->value(internProp);
#endif
} else if (QtFlagPropertyManager *flagManager = qobject_cast<QtFlagPropertyManager *>(manager)) {
return flagManager->value(internProp);
}
return QVariant();
}
//自己实现,用于判断是不是bool型property
bool QtVariantPropertyManager::isBoolProperty(const QtProperty *property)
{
QtProperty *internProp = propertyToWrappedProperty()->value(property, 0);
if (internProp == 0)
return false;
QtAbstractPropertyManager *manager = internProp->propertyManager();
if (QtBoolPropertyManager *boolManager = qobject_cast<QtBoolPropertyManager *>(manager))
{
return true;
}
else {
return false;
}
}
自绘时间轴
Qt之时间轴样式汇总
自定义图元、鼠标划线、右键属性
Qt 下结合SARibbon、Dock 开发Opencascade应用的基础框架
Qt浅谈之三十五仿QQ设置面板功能
[Qt浅谈之三十六仿360设置中心](https://blog.csdn.net/taiyang1987912/article/details/50249243)Qt浅谈之四十七下拉列表菜单
Qt浅谈之右下角浮出界面
QT重写QStackedWidget实现home界面左右滑动
QT-QScroller实现home界面上下滑动效果
Qt-滚动字幕之无间隙滚动
Qt浅谈之三十二二维码条形码解析
qt-spek 基于Qt的频谱分析器,修改于spek:
https://github.com/wyyrepo/qt-spek
http://spek.cc/
//5个按钮重合在一个位置,而后使用贴图setMask()
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setAttribute(Qt::WA_TranslucentBackground);
//设置背景贴图
QPixmap pixmap;
pixmap.load(":/assets/bgimage.png");
resize(pixmap.size());
setMask(pixmap.mask());
//顶部按钮
QPixmap topBtn(":/assets/topBtn.png");
ui->pushButton->setIconSize(topBtn.size());
ui->pushButton->resize(topBtn.size());
ui->pushButton->setMask(topBtn.mask());
ui->pushButton->setStyleSheet("QPushButton{border:0px;border-image:url()}"
"QPushButton:pressed{border-image:url(:/assets/topBtn.png)};");
//左侧按钮
QPixmap leftBtn(":/assets/leftBtn.png");
ui->pushButton_2->setIconSize(leftBtn.size());
ui->pushButton_2->resize(leftBtn.size());
ui->pushButton_2->setMask(leftBtn.mask());
ui->pushButton_2->setStyleSheet("QPushButton{border:0px;border-image:url()}"
"QPushButton:pressed{border-image:url(:/assets/leftBtn.png)};");
//底部按钮
QPixmap bottomBtn(":/assets/bottomBtn.png");
ui->pushButton_3->setIconSize(bottomBtn.size());
ui->pushButton_3->resize(bottomBtn.size());
ui->pushButton_3->setMask(bottomBtn.mask());
ui->pushButton_3->setStyleSheet("QPushButton{border:0px;border-image:url()}"
"QPushButton:pressed{border-image:url(:/assets/bottomBtn.png)};");
//右侧按钮
QPixmap rightBtn(":/assets/rightBtn.png");
ui->pushButton_4->setIconSize(rightBtn.size());
ui->pushButton_4->resize(rightBtn.size());
ui->pushButton_4->setMask(rightBtn.mask());
ui->pushButton_4->setStyleSheet("QPushButton{border:0px;border-image:url()}"
"QPushButton:pressed{border-image:url(:/assets/rightBtn.png)};");
//中间按钮
QPixmap centerBtn(":/assets/centerBtnImage.png");
ui->pushButton_5->setIconSize(centerBtn.size());
ui->pushButton_5->resize(centerBtn.size());
ui->pushButton_5->setMask(centerBtn.mask());
ui->pushButton_5->setStyleSheet("QPushButton{border:0px;border-image:url()}"
"QPushButton:pressed{border-image:url(:/assets/centerBtnImage.png)};");
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawPixmap(0,0,QPixmap(":/assets/bgimage.png"));
}
pushbutton背景透明:基本都是 setFlat(true) 和 background: transparent
//长按或设为checkable时, 仍会有边框
ui->btn->setStyleSheet("QPushButton{background: transparent;}");
//变形为QToolButton
ui->btn->setStyleSheet("QToolButton{ border-style:falt;}");
Go2Monitor是德国PROCITEC公司开发的一套专业用于无线电信号自动识别,解调,解码,语音检测,信号记录的独立信号分析软件。
Qt实战案例(23)——利用QProgressBar实现彩色进度条
void test::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.setPen(Qt::red);
painter.setBrush(Qt::red);//设置画笔和画刷
drawcaricon(&painter);
}
void test::drawcaricon(QPainter *painter)
{
QPoint center, left, right, top;
center.setX(this->width()/2); // 中心点
center.setY(this->height()/2);
top.setX(center.x()); // 上点
top.setY(center.y()-150);
left.setX(center.x()-70); // 左点
left.setY(center.y()+70);
right.setX(center.x()+70); // 右点
right.setY(center.y()+70);
QPolygon pts;
pts.setPoints(4, center.x(), center.y(),
left.x(), left.y(),
top.x(), top.y(),
right.x(), right.y());
painter->drawConvexPolygon(pts); //填充绘制多边形
}
思路:resizeEvent
void MyWindow::resizeEvent(QResizeEvent * /*resizeEvent*/)
{
int width = width();
int height = height();
int minSize = width > height ? height : width;
if(width != height)
resize(minSize, minSize);
}
思路:对其上部容器进行调整:
void MyWindow::resizeEvent(QResizeEvent * /*resizeEvent*/)
{
int containerWidth = _myContainerWidget->width();
int containerHeight = _myContainerWidget->height();
int contentsHeight = containerHeight ;
int contentsWidth = containerHeight * _aspectRatio;
if (contentsWidth > containerWidth ) {
contentsWidth = containerWidth ;
contentsHeight = containerWidth / _aspectRatio;
}
resizeContents(contentsWidth, contentsHeight);
}
文字竖着显示(字还是朝上):
m_pLabel->setWordWrap(true);
m_pLabel->setAlignment(Qt::AlignCenter);
m_pLabel->setText(strDisplay.split("",QString::SkipEmptyParts).join("\n"));
文字竖着显示(字还是侧的):
QLabel 如何让文字竖着显示
//继承QLabel,重写virtual void initPainter(QPainter* painter) const 函数
void VLabel::initPainter(QPainter *painter) const
{
painter->translate(width()/2, height()/2);
painter->rotate(-90);
painter->translate(-width()/2, -height()/2);
QLabel::initPainter(painter);
}
//自定义函数,旋转宽高
void VLabel::rotateLabel()
{
int m_width = width();
int m_height = height();
setFixedWidth(m_height);
setFixedHeight(m_width);
}
控制文字对齐方向:
ui->doubleSpinBox->setAlignment(Qt::AlignRight);//文字右对齐
ui.widget->layout()->setAlignment(Qt::AlignLeft | Qt::AlignTop);
Qt::Alignment 类型有以下取值。
1)Qt::AlignLeft:: 水平方向靠左。
2)Qt::AlignRight: 水平方向靠右。
3)Qt::AlignHCenter: 水平方向居中。
4)Qt::AlignJustify: 水平方向调整间距两端对齐。
5)Qt::AlignTop: 垂直方向靠上。
6)Qt::AlignButton: 垂直方向靠下。
7)Qt::AlignVCenter: 垂直方向居中。
8)Qt::AlignCenter: 等价于 Qt::AlignHCenter | Qt::AlignVCenter。
【QT】数据处理进度等待框QProgressDialog
https://github.com/nwaniek/qt5-node-editor
https://github.com/MEONMedical/Log4Qt
加入项目中:include(/src/log4qt/log4qt.pri)