QT:QTableView,QCheckBox、QMenu富文本上标

嗯,第一次,稍微有点紧张,写的不好希望大佬不要批评我,会伤心的
相信上标这个简单而不简单的问题一定难道了不少像我一样想用简单方式,尝试通过Word、WPS里面的字符进行实现的傻缺。
话不多说,我们进入正题。

QTableView和QTableWidget方法一样,所以我只讲QTableWidget

说道QTableWidget我们肯定需要一个QTableWidget来做这个东西先随便建一个QTableWidget

然后进入正题,对于QTableWidget\QTableView我们需要用到QItemDelegate代理来进行绘制,这样可以节省很多时间,但是由于QTableView和QTableWiget的表头是独立的QHeadView而且代理设置是不生效的可以查阅QT表中的说明可知As a result, calling a header's setItemDelegate() function will have no effect.因此我们QHeadView只能从他本身的绘制事件入手

然后贴上代码:

#ifndef TOPRICH_H
#define TOPRICH_H

#include <QTableView>
#include <QHeaderView>
#include <QCheckBox>
#include <QItemDelegate>
#include <QTableWidgetItem>

class RichEditDelegate: public QItemDelegate
{
    Q_OBJECT
public :
    RichEditDelegate(QObject*parent=nullptr)
        :QItemDelegate(parent){
        }
    void paint(QPainter*painter, const QStyleOptionViewItem&option, const QModelIndex&index) const;
private :
};

class HeaderView : public QHeaderView
{
    Q_OBJECT
public:
    HeaderView(Qt::Orientation orientation, QWidget *parent = Q_NULLPTR)
        :QHeaderView(orientation, parent){

        }
    HeaderView(QHeaderView tb)
        :QHeaderView(tb.orientation()){

        }
    void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;

};
#endif // TOPRICH_H
#include "TopRich.h"
#include <QDebug>
#include <QTextDocument>
#include <QtWidgets/QApplication>
#include <QStylePainter>
#include <QAbstractTextDocumentLayout>
#include <QStyleOptionViewItem>
#include <QPainter>

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

    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
    QStyle *pStyle = viewOption.widget? viewOption.widget->style() : QApplication::style();

    QString strHTML = QString("");
    strHTML = index.model()->data(index, Qt::DisplayRole).toString();

    QRect textRect = pStyle->subElementRect(QStyle::SE_ItemViewItemText, &viewOption);
    QFont fontDefault;
    int fwidth = QFontMetrics(fontDefault).width(strHTML);
    if(fwidth>textRect.width())
    {//此处是为了进行换行
        QString str;
        for(QString::iterator iter = strHTML.begin(); iter!=strHTML.end(); ++iter)
        {
            str += *iter;
            fwidth = QFontMetrics(fontDefault).width(str);
            if(fwidth>textRect.width()-8)
            {
                if(str.indexOf("\n") == -1){
                    if((*iter) != '-' && *(++iter) != 's'){
                        str += '\n';
                        --iter;
                    }
                    else{
                        str += *iter;
                        str += '\n';
                    }
                }
                for(++iter;iter!=strHTML.end();++iter)
                    str += *iter;
                break;
            }
        }
        strHTML = str;
    }

    strHTML.replace("/s", "<sup>-s</sup>");
    strHTML.replace("\n","<br>");

    QTextDocument doc;
    doc.setHtml(strHTML);
    QAbstractTextDocumentLayout::PaintContext paintContext;

    if((option.state & QStyle::State_Selected) == QStyle::State_Selected){
        drawBackground(painter, viewOption, index);
    }

    painter->save();
    // 坐标变换,将左上角设置为原点
    painter->translate(textRect.topLeft());
    // 设置HTML绘制区域
    painter->setClipRect(textRect.translated(-textRect.topLeft()));
    doc.documentLayout()->draw(painter, paintContext);
    painter->restore();

}
//----------------------------------------------------------------------------------------------------------------------------
void HeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{

    QAbstractItemModel * mo = model();
    QVariant hData = mo->headerData(logicalIndex, Qt::Horizontal);
    QString hDataStr = hData.toString();

    if(hDataStr.contains("<sup>") || hDataStr.contains("/s")){
        //设置显示文本为空,使用默认样式
        QStyleOptionHeader viewOption;
        initStyleOption(&viewOption);

        QStyle * pStyle = style();
        viewOption.rect = rect;
        viewOption.text = "";
        pStyle->drawControl(QStyle::CE_Header, &viewOption, painter);

        //需要显示的HTML
        QString strHTML = QString(hDataStr);
        QRect textRect = pStyle->subElementRect(QStyle::SE_HeaderLabel, &viewOption);
        QPoint textPoint= textRect.topLeft();
        textPoint.setX(textPoint.x());
        strHTML.replace("/s","<sup>-s</sup>");
        strHTML.replace("\n","<br>");
        //qDebug() << "HeaderView::paintSection -- fwidth:" << strHTML;
        QTextDocument doc;
        doc.setHtml(strHTML);
        QAbstractTextDocumentLayout::PaintContext paintContext;

        painter->save();
        //坐标变换,将左上角设置为原点
        painter->translate(textPoint);
        //设置HTML绘制区域
        painter->setClipRect(textRect.translated(-textPoint));

        doc.documentLayout()->draw(painter, paintContext);
        painter->restore();
    }
    else
    {
        painter->save();
        QHeaderView::paintSection(painter, rect, logicalIndex);
        painter->restore();
    }
    updatesEnabled();
}

最后简单的调用设置

ui->tableWidget->setItemDelegateForRow(0,new RichEditDelegate);    
ui->tableWidget->setHorizontalHeader(new HeaderView(ui->tableWidget->horizontalHeader()->orientation()));

见证奇迹的时候到了

整个解决方法中核心的地方就在于QT支持两种文本一个是PlainText一个是RichText,而RichText可以支持Html格式字符,所以我们在重载的时候就需要按照Html的格式进行修改,另一个就是需要了解Qt控件的绘图机制,QStyle的原理。了解以上之后,QMenu设置上标的方法就很简单了。附上代码:

void TopStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
{
    if(element == QStyle::CE_MenuItem){
        if(const QStyleOptionMenuItem * btn = qstyleoption_cast<const QStyleOptionMenuItem *>(option)){
            QStyleOptionMenuItem suopt = *btn;

            QString strHTML = suopt.text;
            suopt.text = "";
            QProxyStyle::drawControl(element, &suopt, painter, widget);

            strHTML.replace("/s", "<sup>-s</sup>");

            QTextDocument doc;
            doc.setHtml(strHTML);
            QAbstractTextDocumentLayout::PaintContext paintContext;
            painter->save();
            //坐标转换
            QPoint textPoint = suopt.rect.topLeft();
            textPoint.setX(textPoint.x()+30);
            painter->translate(textPoint);
            painter->setClipRect(suopt.rect.translated(-textPoint));
            doc.documentLayout()->draw(painter, paintContext);
            painter->restore();
        }
    }
    else
        return QProxyStyle::drawControl(element, option, painter, widget);
}

重载QProxyStyle然后设置QMenu的style就行了。
感谢浏览,写的不好,希望不要计较,共同进步!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值