QTreeView使用整理

2023-10-31

在Qt开发过程中,树控件QTreeView使用的非常频繁。各种批量展示和编辑信息的地方,都用得上该控件。
在使用QTreeView过程中,用到各种常规、不常规的功能,并进行过各种改造。
这里将这些知识和技巧作一个总结。

一、Model/View框架介绍

1.简介

Model/View架构分为三部分:模型、视图和委托。主要目的是将数据的存储与显示分离。

  • Model模型:对外提供标准接口存取数据,不关心数据如何显示。
  • View视图:自定义数据的显示方式,不关心数据如何组织存储。
  • Delegate委托:在视图的基础上可以自定义特殊的显示和编辑效果。

在这里插入图片描述

一般只有Model与内存上的原始数据打交道,通过原始数据构造一个Model,然后View从Model取数据进行展示。
两者耦合度低,一般对其中一方进行修改,另一方影响很小,因此把一种QT View控件替换为另一种View控件时,Model的代码基本不需要多少改动即可正常运行。
委托一般在我需要定制一些特殊的显示效果或输入方式时使用,提供了很大的灵活性。
这种分层架构给代码的逻辑性和可维护性带来了很大的提升。

2.常用Model和View

最常用的两种View控件为QTableView和QTreeView。其实,QTreeView一般也能满足QTableView的功能。
最常用的Model类型为QStandardItemModel,能满足大部分开发需要。
如果数据量比较大,对性能和内存要求比较高,可以使用自定义model,下文有讲。

完整的Model类型有下面这些:

  • QStringListModel:存储简单的字符串列表
  • QStandardItemModel:可以用于树结构的存储,提供了层次数据
  • QFileSystemModel:本地系统的文件和目录信息
  • QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel:存取数据库数据

QT提供了多个预定义好的视图类:

  • QListView:用于显示列表
  • QTableView:用于显示表格
  • QTreeView:用于显示层次数据

委托一般继承自QStyledItemDelegate类进行定制开发。

二、QSS风格美化

默认的QTreeView是这样的:
在这里插入图片描述

用QSS来改造QTreeView的样式,一般会处理这些项:

  • 表头:背景色、文字色、边框、高度
  • 控件整体:背景色、文字色、边框
  • 元素:背景色、文字色、边框、高度(处理normal、hover、press三态的颜色)
  • 分支:颜色或图片(normal、hover、press三态)
    示例代码如下:
QHeaderView::section
{ 
    height:25px;
    color:white;
    background:#505050;
    border-left:0px solid gray; 
    border-right:1px solid gray; 
    border-top:0px solid gray; 
    border-bottom:0px solid gray;
}
QTreeView
{
    border:none;
    background: #404040;
    show-decoration-selected: 1;  /* 设置整行颜色一致 */
}
QTreeView::item
{
    height: 25px;
    border: none;
    color: white;
    background: transparent;
}
QTreeView::item:hover
{
    background: #2CAEFF;
}
QTreeView::item:selected
{
    background: #1E90FF;
}
QTreeView::branch
{
    background: transparent;
}
QTreeView::branch:hover
{
    background: transparent;
}
QTreeView::branch:selected
{
    background: #1E90FF;
}
QTreeView::branch:closed:has-children
{
    image: url(:/QtExample/Resources/fold_normal.png);
}
QTreeView::branch:closed:has-children:hover
{
    image: url(:/QtExample/Resources/fold_hover.png);
}
QTreeView::branch:open:has-children
{
    image: url(:/QtExample/Resources/unfold_normal.png);
}
QTreeView::branch:open:has-children:hover
{
    image: url(:/QtExample/Resources/unfold_hover.png);
}

示例效果图:
在这里插入图片描述

三、自定义Delegate

虽然QSS可以定制绝大多数QTreeView的样式,但是对于某些情况,QSS实现起来比较棘手。接下来介绍一些高级的用法和改造技巧,用delegate,即委托,对QTreeView的item进行改造,以实现特殊的输入方式和显示效果。

1.使用委托:定制item输入效果

这里演示一个让某列使用QComboBox进行编辑的效果:
在这里插入图片描述

继承QStyledItemDelegate,写一个MyDelegate类,实现里面的以下方法:

  • createEditor: 当item激活编辑状态时,显示的内容。这里创建一个QComboBox
  • setEditorData:用以初始化createEditor里创建的控件内容。这里直接把当前item的text设置为QComboBox选中项。
  • setModelData:应用编辑后,修改model的data。这里把QComboBox的当前选中项文本设置为item的显示文本。
  • updateEditorGeometry:更新控件位置状态。
    示例代码如下:

MyEditDelegate.h


#include <QStyledItemDelegate>

class MyEditDelagate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyEditDelagate(QObject *parent);
    ~MyEditDelagate();
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    void setEditorData(QWidget *editor, const QModelIndex &index) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};

MyEditDelegate.cpp


#include "MyEditDelagate.h"
#include <QComboBox>

MyEditDelagate::MyEditDelagate(QObject *parent)
    : QStyledItemDelegate(parent)
{
}

MyEditDelagate::~MyEditDelagate()
{
}

QWidget *MyEditDelagate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const
{
    /* 只对第4列采用此方法编辑 */
    if (index.column() == 3)
    {
        QComboBox* box = new QComboBox(parent);
        box->addItems({
            QString::fromLocal8Bit("测试输入0"),
            QString::fromLocal8Bit("测试输入1"),
            QString::fromLocal8Bit("测试输入2") });
        return box;
    }
    return NULL;
}

void MyEditDelagate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
    QComboBox* box = static_cast<QComboBox*>(editor);
    box->setCurrentText(value);
}

void MyEditDelagate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox* box = static_cast<QComboBox*>(editor);
    model->setData(index, box->currentText(), Qt::EditRole);
}

void MyEditDelagate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    editor->setGeometry(option.rect);
}

在初始化QTreeView时,新建一个MyDelegate,设itemDelegate:

注意:要设置单元格编辑属性为可编辑(setEditTriggers),否则点击单元格不会有反应。

//ui.treeView->setEditTriggers(QTreeView::NoEditTriggers); /* 单元格不能编辑 */
ui.treeView->setSelectionBehavior(QTreeView::SelectRows); /* 一次选中整行 */
ui.treeView->setSelectionMode(QTreeView::SingleSelection); /* 单选,配合上面的整行就是一次选单行 */
//ui.treeView->setAlternatingRowColors(true); /* 每间隔一行颜色不一样,当有qss时该属性无效 */
ui.treeView->setFocusPolicy(Qt::NoFocus); /* 去掉鼠标移到单元格上时的虚线框 */

MyEditDelagate* delegate = new MyEditDelagate(ui.treeView);
ui.treeView->setItemDelegate(delegate);

2.使用委托:定制item显示效果

可能相比于控制输入,定制item显示效果不那么常用,但是有时候通过委托来绘制是比较容易实现的。比如上述QSS中定义的hover高亮效果:

QTreeView::item:hover
{
    background: #2CAEFF;
}

上述QSS定义存在如下图所示无法高亮整行的问题:

在这里插入图片描述

可以通过在Delegate中(比如上述MyEditDelegate)中实现下面这个paint方法来轻松实现:

void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

想要保持原来绘制的部分可以先写如下代码:

QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
QStyledItemDelegate::paint(painter, viewOption, index);

那么如何hover高亮整行呢。
上述QSS之所以无法高亮整行,是因为item的范围就不是从最左边开始的。因此只能高亮item范围内,item前面多余的空白部分无法填充。
先设置QTreeView的属性indentation为0,让所有的column的x坐标相同。
然后绘制高亮代码如下:

QRect rectBackground = option.rect;
rectBackground.setLeft(0);
if (option.state & QStyle::State_MouseOver)
{
   painter->fillRect(rectBackground, QColor("##E5F3FF"));
}

示例效果如下:

在这里插入图片描述

上述高亮会覆盖前面paint的部分,可以根据需要调整绘制顺序。
由于属性indentation为0,绘制原先部分时需要根据column作相应右偏移,只需要在

QStyledItemDelegate::paint(painter, viewOption, index);

前对viewOption的rect设置适当右偏移即可。或者也在委托里面定制。

在项目中使用delegate高亮部分关键字,效果如下:

在这里插入图片描述

可以把要显示的文本setData到model中,然后在paint的时候分别绘制高亮部分和非高亮部分。
示例代码:


QString strSearchKeywords;  /* 需要高亮的关键字 */
QString strProjectName = index.data(OrderRole = Qt::UserRole + 1).toString();  /* 完整的字符串 */
if (strProjectName.contains(strSearchKeywords))
{
     QStringList listSplit = strProjectName.split(strSearchKeywords);
     QStringList listProjectName;

      /* split默认保留分割后的空字符串,使得原字符串以关键字为分界分成多段 */
      if (listSplit.size() > 0)
      {
          for (int i = 0; i < listSplit.size(); i++)
          {
              /* 第0个若empty,说明是关键字,跳过,因为到第1个时可以加上 */
              if (i == 0 && listSplit[i].isEmpty())
               {
                    continue;
               }
                if (i > 0)
                {
                    /* 关键字作为分界的位置,需要将关键字也加入list以显示 */
                    listProjectName.append(strSearchKeywords);
                }
                if (!listSplit[i].isEmpty())
                {
                    listProjectName.append(listSplit[i]);
                }
            }
        }
        else
        {
            listProjectName.append(strSearchKeywords);
        }

        int iLeftOffset = rectName.left();
        for (QString strPart : listProjectName)
        {
            /* 如果该分段是关键字,则高亮,否则不高亮 */
            painter->setPen((strPart == strSearchKeywords) ? COLOR_HIGHLIGHT : COLOR_NORMAL);

            /* 根据该分段文字与名称总长的比例,获取获取该分段文字rect宽度 */
            QRect rectPart = rectName;
            rectPart.setLeft(iLeftOffset);
            rectPart.setWidth(QFontMetrics(font).width(strPart));
            painter->drawText(rectPart, Qt::AlignLeft | Qt::AlignVCenter | Qt::ElideRight, strPart);

            /* 下一个的左侧距离必须加上实际显示出来的文字宽度 */
            iLeftOffset += QFontMetrics(font).width(strPart);
     }
}

另外,还可以在delegate里面实现以下两个函数控制点击事件和toolTips事件

/* 捕捉点击事件 */
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);

/* 捕捉toolTips事件 */
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index);

通过delegate绘制超出treeView可见宽度的内容,会导致treeView不能自动调整横向滚动条,可以重写QTreeView的setExpanded和expandAll来调整

示例图:
在这里插入图片描述

超出可见宽度item展开时,显示横向滚动条;
超出可见宽度item隐藏时,隐藏横向滚动条。

代码:


    setColumnWidth(0, this->width());   /* 设置item宽度 */
    QModelIndex modelIndex = this->indexAt(this->rect().topLeft());
    QFont font;
    font.setFamily("Microsoft YaHei");
    font.setPixelSize(13);

    /* 遍历所有可见index(从右上角可见index开始向下找) */
    while (modelIndex.isValid())
    {
        /* item宽度要足够宽,能够完整显示下拉箭头、名称、选中√图标 */
        int iItemWidth = QFontMetrics(font).width(QString(modelIndex.data(Qt::UserRole + 1).toString()));
        if (iItemWidth > this->columnWidth(0))
        {
            this->setColumnWidth(0, iItemWidth);
        }
        modelIndex = this->indexBelow(modelIndex);
    }

三、自定义Model

上文已经简单介绍过Qt的Model/View框架,提到了Qt预定义的几个model类型:

  • QStringListModel:存储简单的字符串列表
  • QStandardItemModel:可以用于树结构的存储,提供了层次数据
  • QFileSystemModel:本地系统的文件和目录信息
  • QSqlQueryModel、QSqlTableModel、QSqlRelationalTableModel:存取数据库数据

一般情况下满足需求了,不过有时候需要一些定制功能,或者是大量数据下对性能和开销比较注重,觉得自带的model无用功能太多效率比较低,这时候自定义model就比较适合了。
以上述示例程序为例,当行数达到10W的数据量级时,常规QStandardItemModel 在初始化tree的过程比自定义model慢很多,而且所占用的内存开销是自定义model的数倍甚至数十倍。数据量越大内存差距越明显。如果考虑百万、千万级别的数据,常规model相比于自定义model内存也大很多。

以下为自定义model需要实现的一些虚函数,将会被Qt在查询model数据时调用:

  • headerData: 获取表头第section列的数据
  • data: 核心函数,获取某个索引index的元素的各种数据role决定获取哪种数据,常用有下面几种:
    1)DisplayRole(默认):就是界面显示的文本数据
    2)TextAlignmentRole:就是元素的文本对齐属性
    3)TextColorRole、BackgroundRole:分别指文本颜色、单元格背景色
  • flags: 获取index的一些标志,一般不怎么改
  • index: Qt向你的model请求一个索引为parent的节点下面的row行column列子节点的元素,在本函数里你需要返回该元素的正确索引
  • parent:获取指定元素的父元素
  • rowCount: 获取指定元素的子节点个数(下一级行数)
  • columnCount: 获取指定元素的列数

下面是对比QStandardItemModel和自定义Model的初始化tree时间和占用内存(不设置model程序本身内存:15.4MB)对比:

Model类型 初始化tree时间 占用内存
QStandardItemModel 1263ms 96.9MB
自定义Model 75ms 20MB

程序示例图:

在这里插入图片描述

示例代码:

模拟数据数据结构:


/* 子节点 */
typedef struct _CHILD
{
    QString name;
    int number1;
    int number2;
    int number3;
    _CHILD()
    {
        name = "";
        number1 = number2 = number3 = 0;
    }
}CHILD, *PCHILDITEM;

/* 父节点 */
typedef struct _PARENT
{
    QString name;
    QVector<CHILD*> childs;
    _PARENT()
    {
        name = "";
    }
}PARENT;

模拟数据初始化:

 /* 10个父节点,每个父节点有1W个子节点,共10W行记录 */
    int nParent = 10;
    int nChild = 10000;
    for (int i = 0; i < nParent; i++)
    {
        PARENT* c = new PARENT;
        c->name = QString::fromLocal8Bit("父节点%1").arg(i);
        for (int j = 0; j < nChild; j++)
        {
            CHILD* s = new CHILD;
            s->name = QString::fromLocal8Bit("子节点%1").arg(j);
            s->number1 = 0;
            s->number2 = 1;
            s->number3 = 2;
            c->childs.append(s);
        }
        mDatas.append(c);
    }

模拟数据

QVector<PARENT*> mDatas;

常规QStandardItemModel构造tree代码:


 QStandardItemModel* model = new QStandardItemModel(ui.treeView);
    model->setHorizontalHeaderLabels(headers);
    foreach(PARENT* p, mDatas)
    {
        /* 一级节点:父节点 */
        QStandardItem* itemParent = new QStandardItem(p->name);
        model->appendRow(itemParent);

        foreach(CHILD* c, p->childs)
        {
            /* 二级节点:子节点 */
            QList<QStandardItem*> items;
            QStandardItem* item0 = new QStandardItem(c->name);
            QStandardItem* item1 = new QStandardItem(QString::number(c->number1));
            QStandardItem* item2 = new QStandardItem(QString::number(c->number2));
            QStandardItem* item3 = new QStandardItem(QString::number(c->number3));
            items << item0 << item1 << item2 << item3;
            itemParent->appendRow(items);
        }
    }

自定义Model构造tree代码:


MyModel* model = new MyModel(headers, ui.treeView);
    MyItem* root = model->root();
    foreach(PARENT* p, mDatas)
    {
        /* 一级节点:父节点 */
        MyItem* itemParent = new MyItem(root);

        /* 设为一级节点,供显示时判断节点层级来转换数据指针类型 */
        itemParent->setLevel(1);

        /* 保存PARENT* p为其数据指针,显示时从该PARENT*取内容显示 */
        itemParent->setPtr(p);
        root->appendChild(itemParent);

        foreach(CHILD* c, p->childs)
        {
            MyItem* itemChild = new MyItem(itemParent);

            /* 设为二级节点,供显示时判断节点层级来转换数据指针类型 */
            itemChild->setLevel(2);

            /* 保存CHILD* c为其数据指针,显示时从CHILD*取内容显示 */
            itemChild->setPtr(c);
            itemParent->appendChild(itemChild);
        }
    }

自定义Model MyModel.h代码


#include <QAbstractItemModel>
#include "MyItem.h"

class MyModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    MyModel(QStringList headers, QObject *parent = 0);
    ~MyModel();

    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &index) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;

public:
    MyItem *itemFromIndex(const QModelIndex &index) const;
    MyItem *root();

private:
    QStringList mHeaders;   /* 表头内容 */
    MyItem *mRootItem;      /* 根节点 */
};

自定义Model MyModel.cpp


#include "MyModel.h"

MyModel::MyModel(QStringList headers, QObject *parent)
    : QAbstractItemModel(parent)
{
    mHeaders = headers;
    mRootItem = new MyItem;
}

MyModel::~MyModel()
{
    delete mRootItem;
}

MyItem *MyModel::itemFromIndex(const QModelIndex &index) const
{
    if (!index.isValid())
        return NULL;
    MyItem *item = static_cast<MyItem*>(index.internalPointer());
    return item;
}

MyItem *MyModel::root()
{
    return mRootItem;
}

QVariant MyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal)
    {
        if (role == Qt::DisplayRole)
        {
            return mHeaders.at(section);
        }
    }
    return QVariant();
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    MyItem *item = static_cast<MyItem*>(index.internalPointer());
    if (role == Qt::DisplayRole)
    {
        return item->data(index.column());
    }
    return QVariant();
}

Qt::ItemFlags MyModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    return QAbstractItemModel::flags(index);
}

QModelIndex MyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    MyItem *parentItem;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<MyItem*>(parent.internalPointer());

    MyItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex MyModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    MyItem *childItem = static_cast<MyItem*>(index.internalPointer());
    MyItem *parentItem = childItem->parentItem();

    if (parentItem == mRootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int MyModel::rowCount(const QModelIndex &parent) const
{
    MyItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = mRootItem;
    else
        parentItem = static_cast<MyItem*>(parent.internalPointer());

    return parentItem->childCount();
}

int MyModel::columnCount(const QModelIndex &parent) const
{
    return mHeaders.size();
}

MyItem.h


#include <QVariant>

class MyItem
{
public:
    explicit MyItem(MyItem *parentItem = 0);
    ~MyItem();

    void appendChild(MyItem *child);      //在本节点下增加子节点
    void removeChilds();                    //清空所有节点

    MyItem *child(int row);               //获取第row个子节点指针
    MyItem *parentItem();                 //获取父节点指针
    int childCount() const;                 //子节点计数
    int row() const;                        //获取该节点是父节点的第几个子节点

    //核心函数:获取节点第column列的数据
    QVariant data(int column) const;

    //设置、获取节点是几级节点(就是树的层级)
    int level(){ return mLevel; }
    void setLevel(int level){ mLevel = level; }

    //设置、获取节点存的数据指针
    void setPtr(void* p){ mPtr = p; }
    void* ptr(){ return mPtr; }

    //保存该节点是其父节点的第几个子节点,查询优化所用
    void setRow(int row){
        mRow = row;
    }

private:
    QList<MyItem*> mChildItems;   //子节点
    MyItem *mParentItem;          //父节点
    int mLevel;     //该节点是第几级节点
    void* mPtr;     //存储数据的指针
    int mRow;       //记录该item是第几个,可优化查询效率
};

MyItem.cpp


#include "MyItem.h"
#include "defines.h"

MyItem::MyItem(MyItem *parent)
{
    mParentItem = parent;
    mPtr = NULL;
    mLevel = 0;
    mRow = 0;
}

MyItem::~MyItem()
{
    removeChilds();
}

void MyItem::appendChild(MyItem *item)
{
    item->setRow(mChildItems.size());   //item存自己是第几个,可以优化效率
    mChildItems.append(item);
}

void MyItem::removeChilds()
{
    qDeleteAll(mChildItems);
    mChildItems.clear();
}

MyItem *MyItem::child(int row)
{
    return mChildItems.value(row);
}

MyItem *MyItem::parentItem()
{
    return mParentItem;
}

int MyItem::childCount() const
{
    return mChildItems.count();
}

int MyItem::row() const
{
    return mRow;
}

QVariant MyItem::data(int column) const
{
    if (mLevel == 1)
    {
        /* 一级节点: 父节点 */
        if (column == 0)
        {
            PARENT* c = (PARENT*)mPtr;
            return c->name;
        }
    }
    else if (mLevel == 2)
    {
        /* 二级节点: 子节点 */
        CHILD* s = (CHILD*)mPtr;
        switch (column)
        {
        case 0: return s->name;
        case 1: return QString::number(s->number1);
        case 2: return QString::number(s->number2);
        case 3: return QString::number(s->number3);
        default:
            return QVariant();
        }
    }
    return QVariant();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QTreeView使用整理 的相关文章

  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • 调整 QML 图像显示尺寸

    我有一个带有嵌套的 QML 窗口RowLayout 在内排我有两个图像 来源 png这些图像的文件 故意 相当大 当我尝试设置height这些图像上的属性使它们变小 但它们仍然被画得很大 Desired Appearance Actual
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 如何获取 QIcon 的文件/资源​​路径

    假设我做了这样的事情 QIcon myIcon resources icon ico 我稍后如何确定该图标的路径 例如 QString path myIcon getPath 问题是 没有getPath 会员 我找不到类似的东西 但肯定有办
  • Qt 支持在 QIcon 中为 SVG 着色

    看来 Qt 不支持 SVG 中路径标签上的描边 填充选项
  • QTableView 中的虚拟列?

    我开始学习 Qt4 模型 视图编程 我有初学者问题 我有一个简单的应用程序 其中显示 sqlite 表QTableView class Model QtSql QSqlTableModel def init self parent None
  • QGraphicsView 和 eventFilter

    这个问题已经困扰我两天多了 所以我想我应该问一下 我在Win7上使用Qt 4 5 3 用VC2008编译 我有 MyGraphicsView 继承 QGraphicsView 和 MyFilter 继承 QObject 类 当我将 MyFi
  • 如何在 Qt-Embedded 中(正确)输出多语言文本?

    我的目标系统是 linux 3 3 7 Qt Embedded 开源版 4 8 Droid 字体 取自 fonts droid 20111207 git 1 all deb Debian 软件包并复制到 usr lib fonts目录 主要
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • 如何在 C++ 运行时更改 QML 对象的属性?

    我想在运行时更改 QML 对象的文本 我尝试如下 但文本仍然为空 这是后端类 class BackEnd public QObject Q OBJECT Q PROPERTY QString userFieldText READ userF
  • 当我尝试构建 Qt 4.7.1 静态库时,“找不到 -ljscore”

    我尝试从最新的源构建静态 Qt 库 但出现以下错误 usr bin ld cannot find ljscore collect2 ld returned 1 exit status 如何解决这个问题呢 这是 Qt 构建系统中自 4 7 0
  • Qt中如何获取鼠标在屏幕上的位置?

    我想获取屏幕上的鼠标坐标 我怎样才能在 Qt 中做到这一点 在 Windows 上 使用 C 我正在做类似答案中建议的事情对于这个问题 https stackoverflow com q 11737665 1420197 正如文档所述 QC
  • QTextEdit.find() 在 Python 中不起作用

    演示问题的简单代码 usr bin env python import sys from PyQt4 QtCore import QObject SIGNAL from PyQt4 QtGui import QApplication QTe
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 在 Qt5 中,是否需要 Q_INVOKABLE 来从 QML 调用公共 QObject 函数?

    我刚刚意识到我可以调用暴露于 QML 的对象的几乎任何函数 现在我对 Q INVOKABLE 很好奇 Qt5docs http doc qt io qt 5 qtqml cppintegration exposecppattributes
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示
  • 使用 Visual Studio 2013 构建 Qt 5.2.1 的静态版本

    几天来我一直在尝试使用 Visual Studio 2013 构建 Qt 的静态版本 我就是不明白我做错了什么 System Windows 7 64 位 Visual Studio 2013 仍安装 Visual Studio 2012
  • 如何使QTableView类的restoreState()和saveState()正常工作?

    首先 我想说 我的问题已经在这里讨论过 并且这里是 https stackoverflow com questions 1163030 qt qtableview and horizontalheader restorestate 但答案并
  • Qt:测量事件处理时间

    我想测量我的应用程序中的哪些事件在主线程中需要很长时间才能执行 阻塞 GUI 或者至少是否有任何事件花费的时间超过 比如说 10 毫秒 显然 我对需要很长时间的任务使用线程和并发 但有时很难在其他线程中放入的内容和可以保留在 GUI 中的内
  • 将 gnuplot 嵌入现有 QtWidget 中

    我正在用 C 创建一个 伪 实时绘图应用程序 使用 gnuplot 作为绘图后端 我的要求之一是绘图必须位于现有窗口内 而不是有一个单独的绘图窗口 gnuplot 默认为 Gnuplot 有一个选项可以指定 Qt 小部件 ID 这似乎适合我

随机推荐

  • sugarcrm mysql_SugarCRM安装踩雷(一)

    安装SugarCRM前置条件 1 找对平台 正确版本的安装包 2 APACHE MYSQL TOMCAT环境先确保OK 坑1 进入安装参数设置步骤的MYSQL用户密码 这里根据Mysql的登陆用户名和密码来填写 如果不是单独安装的Mysql
  • 贝叶斯推断及其互联网应用(二):过滤垃圾邮件

    上一次 我介绍了贝叶斯推断的原理 今天讲如何将它用于垃圾邮件过滤 贝叶斯推断及其互联网应用 作者 阮一峰 接上文 七 什么是贝叶斯过滤器 垃圾邮件是一种令人头痛的顽症 困扰着所有的互联网用户 正确识别垃圾邮件的技术难度非常大 传统的垃圾邮件
  • Android 中使用Volley进行网络请求和图片加载详解

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 Volley概述 Volley既可以访问网络取得数据 也可以加载图片 并且在性能方面进行了大幅度的调整 它的设计目标就是适合进行数
  • TRIZ创新方法——技术矛盾机器解决原理

    TRIZ创新方法 技术矛盾及其解决原理 1 什么是矛盾 2 什么是技术矛盾 3 通用工程参数 4 矛盾矩阵 5 运用阿奇舒勒矛盾矩阵解决技术矛盾的步骤 6 案例分析 7 课后习题 技术矛盾的解决 发明原理的第一个应用 早期TRIZ重要内容之
  • Base Model

    1 Deep Residual Learning for Image Recognition 简介 残差网络ResNet是近年来最有效的base model之一 过去 叠加神经网络层数会导致网络退化 degradation 的问题 当层数达
  • Springboot接入OpenAi/Chat GPT的三种方式

    由于现在网上的相关教程并不多外加没有使用代理的demo 所以抛砖引玉 写了三种调用方式 分别是直接访问 非官方SDK访问 官方开源的SDK访问 准备工作 1 导入pom文件 2023 3 30最新版本
  • 使用Xshell、MobaXterm、Pycharm配置连接远程服务器

    实验室使用服务器远程跑程序 大概分为以下 1 使用SSH SFTP远程连接 2 使用IDE远程调试 下面分别来介绍 文章目录 使用SSH Xshell安装及使用简介 MobaXterm安装及使用简介 下载安装教程 使用简介 使用IDE远程调
  • 安装企业级Docker

    1 关闭防火墙 1 1 关闭防火墙 systemctl stop firewalld systemctl disable firewalld 关闭防火墙 1 2 关闭iptables防火墙 yum install iptables serv
  • /prod-api/ 整合阿里云服务器 2020年12月13日 23:44:18(日记)

    学习过程 先从nginx开始Nginx安装配置 Linux 各种踩坑 求赞安慰 Turing 的博客 CSDN博客 因为之前配置过 所以nginx很快就配置完成了 主要是修改一下配置文件 此处有个小坑 nginx配置文件默认监听80端口 但
  • 微信删除的图片怎么恢复?微信照片过期或已被清理如何还原

    小编是个不喜欢清理微信聊天记录里的照片 文档 视频等各种东西的人 但是有一次不知道是因为什么 一股脑就将好几个人的聊天记录中的文件 照片 视频通通清理并删除掉了 后面想找回来 才知道自己当时太冲动了 估计很多人都有这种经历吧 那么 微信删除
  • CSS基础之背景样式

    目录 前言 一 颜色背景 二 图片背景 三 致我们 前言 当我们在网上浏览各种好看的页面时 网页的背景样式往往是吸引我们眼球的重要因素 有用颜色作为背景图的 也有用图片作背景图的 那么怎样利用CSS简单设置一个背景图呢 来看看叭 CSS背景
  • 玩转深度学习——pytorch实现Lenet网络

    玩转深度学习 pytorch实现Lenet网络 什么是LeNet网络 LeNet网络pytorch实现 改进LeNet网络 增加卷积层 尝试修改一些超参数 开始炼丹 什么是LeNet网络 LeNet 它是最早发布的卷积神经网络之一 因其在计
  • 从前端HTML页面提取数据并保存到数据库当中

    前端页面采取form表单的提交方式 form标签中的action属性值为url 规定当提交表单时 向何处发送表单数据 首先把action中的值修改为urls py文件中设置的url method指明提交方式为post 在form表单结束前加
  • 7个案例15分钟让你了解Python套路!

    古人云 书山有路勤为径 学海无涯苦作舟 注 一般标榜着 XX天学会XX XX 分钟了解XX 的文章都不会是让你增长功力的文章 如本文 随着互联网发展 全球在快速数字化 编程这件事也从数十年前只有科研人研在实验室才能做的事变得越来越让人们所熟
  • C++对txt文件的写入读取操作

    文章目录 1 文件流知识 2 文件的写入 3 文件内容的输出 1 文件流知识 摘自c 中文网 ifstream是输入文件流 就是通过它定义的对象获取文件中的内容 ofstream是输出文件流 将内容写入文件 注意 要使用输入输出文件流要包含
  • 1 .SQL——DataGrip 中的DML三种添加数据方法

    insert into student xingx xi id name age grade xb woketime value 1 aa 10 99 男 2023 12 1 给指定字段添加数据 insert into student xi
  • 谷粒商城笔记+踩坑汇总篇

    导航 黑马Java笔记 踩坑汇总 JavaSE JavaWeb SSM SpringBoot 瑞吉外卖 SpringCloud 黑马旅游 谷粒商城 学成在线 设计模式 牛客面试题 目录 一 摘要 二 微服务架构图 三 文章汇总 一 摘要 部
  • 【待解决】报错:gpt模型训练的时候,有报错的torch.distributed.elastic.multiprocessing.errors.ChildFailedError:

    pytorch多GPU并行的问题 torch distributed elastic multiprocessing errors c CSDN博客
  • Goby漏洞更新

    Goby预置了最具攻击效果的漏洞引擎 覆盖Weblogic Tomcat等最严重漏洞 每天从互联网 如CVE 会产生大量的漏洞信息 我们筛选了会被用于真实攻击的漏洞进行每日更新 Goby也提供了可以自定义的漏洞检查框架 发动了互联网的大量安
  • QTreeView使用整理

    在Qt开发过程中 树控件QTreeView使用的非常频繁 各种批量展示和编辑信息的地方 都用得上该控件 在使用QTreeView过程中 用到各种常规 不常规的功能 并进行过各种改造 这里将这些知识和技巧作一个总结 一 Model View框