如何使表格视图角落项目的角变圆?

问题描述 投票:0回答:1

我有一个

QTableWidget
(或者,
QListWidget
),我想按以下方式设置样式:

  • 单元格的“选定”颜色应该是某种固定的颜色。我可以通过使用以下样式表来做到这一点:

    QTableWidget::item:selected { background-color: #FF0000 }
    
  • 单元格的“未选择”颜色应根据我的代码中的颜色向量单独设置。我可以通过在创建时为每个

    QBrush
    分配
    QTableWidgetItem
    来做到这一点:

    QColor col = color_vector.value(i);
    QBrush brush(col);
    item->setData(Qt::BackgroundRole, QVariant(brush));
    
  • 整个表格应该有圆角(本质上是“剪裁”表格中角项的边框)。

最后一部分我还没有实现。


我尝试过以下方法:

  • 设置样式表:

我可以使用此样式表将表格的角变圆:

QTableWidget 
{ 
    border: 1px solid;
    background: transparent;
    border-radius: 5px 
}

尽管这会在表格周围绘制圆形边框,但各个单元格的背景仍然在角落处“突出”。

我可以为

border-radius
设置相同的
QTableWidget::item
,但是所有单元格的所有角都将被圆化,而不仅仅是表格的边缘。由于
QTableWidgetItem
本身不是
QWidget
,我认为我无法将样式分配给特定项目。

  • 创建
    QDelegate

我尝试对

QStyledItemDelegate
进行子类化并覆盖
paint()
函数。但似乎并没有多大作用。也许我犯了一个错误(对 Qt 来说仍然很新,所以很有可能),或者更改可能被我在样式表/setData 中设置的选项覆盖了?

这是我为

paint(painter, option, index)
实现所做的尝试:

painter->setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(option.rect, 5, 5);
painter->fillPath(path, option.backgroundBrush);
QStyledItemDelegate::paint(painter, option, index);

然后将其添加到表格小部件对象中:

table->setItemDelegateForRow(0, new RoundedCornerDelegate(table));

这甚至还不是最终想要的结果(我仍然需要找出一种只绘制一个圆角的方法),但它似乎不起作用:该项目的背景仍然绘制为纯矩形。即使我将上面代码中的画笔更改为不同的东西,我也没有看到在顶部绘制了不同颜色的圆角矩形(也许在下面?)。

  • 将桌子放入
    QFrame

我之前没有使用过

QFrame
,所以我不确定这是否是预期用途。但我在 UI 编辑器中创建了一个
QFrame
,并将该表添加为子表。然后我尝试了:

ui->frame->setStyleSheet("* { border: 1px solid; border-radius: 5 }");
QWidget* child = qobject_cast<QWidget*>(ui->frame->children().at(0));
ui->frame->setFixedSize(child->size());

但这只会给出奇怪的结果:

QFrame
周围的边框似乎只存在于子项不存在的地方,并且子项不完全可见。

c++ qt qtablewidget qtstylesheets qtablewidgetitem
1个回答
2
投票

sigma 说道:

看起来您可以通过构造具有圆角矩形形状的 QRegion 并使用 QWidget::setMask(QRegion const&).

来实现此目的

这让我找到了这个答案如何圆化QWidget角,并基于它,我做了以下最小的可重现示例:

#include <QApplication>
#include <QTableWidget>
#include <QHeaderView>
#include <QPainterPath>

int main(int argc,char*argv[])
{
    QApplication a(argc, argv);

    //the following is just my setup
    //just a container widget
    QWidget *w = new QWidget();

    QTableWidget *table = new QTableWidget(w);
    table->setGeometry(100,100,200,90);
    table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    //filling the table
    table->insertColumn(0);
    table->insertColumn(1);
    table->insertRow(0);
    table->insertRow(1);
    table->insertRow(2);

    table->setItem(0,0,new QTableWidgetItem("item1"));
    table->item(0,0)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));
    table->setItem(1,0,new QTableWidgetItem("item2"));
    table->item(1,0)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));
    table->setItem(2,0,new QTableWidgetItem("item3"));
    table->item(2,0)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));

    table->setItem(0,1,new QTableWidgetItem("item4"));
    table->item(0,1)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));
    table->setItem(1,1,new QTableWidgetItem("item5"));
    table->item(1,1)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));
    table->setItem(2,1,new QTableWidgetItem("item6"));
    table->item(2,1)->setData(Qt::BackgroundRole, QVariant(QBrush(Qt::green)));

    //removing headers
    table->verticalHeader()->setVisible(false);
    table->horizontalHeader()->setVisible(false);

    //stylesheet of table and its items
    table->setStyleSheet("QTableWidget"
                         "{"
                            "background: rgb(4, 104, 38);"
                            "border: 1px solid white;"
                            "border-radius: 10px;"
                            "color: black;"
                            "selection-background-color: transparent;"
                         "}"
                         "QTableWidget::item"
                         "{"
                            "border: 1px solid white;"
                            "border-radius: 0px;"
                         "}");

    table->viewport()->setStyleSheet("background: rgb(4, 104, 38);"
                                     "border: 1px solid white;"
                                     "border-radius: 10px;"
                                     "color: black;");

    //SOLUTION
    //setting mask on the table's viewport
    //get the viewport's rect
    QRect rect = table->viewport()->rect();
    QPainterPath path;
    //I had to adjust it so it hides the corners that were poking out
    //just made it smaller
    rect.adjust(+1,+1,-1,-1);
    //add the rect to the path so we can draw it as a rounded one
    path.addRoundedRect(rect, 7, 7);
    //feed the rounded rect to a region that we'll use as a mask
    QRegion mask = QRegion(path.toFillPolygon().toPolygon());
    //set the viewport's mask
    table->viewport()->setMask(mask);

    w->setMaximumSize(800,600);
    w->show();

    return a.exec();
}

这是它的样子,你可以看到一些边缘和边框很粗糙,但这已经是我能做到的了:


有关您的方法的说明

第一种方法:

样式表在这种情况下不起作用,因为

QTableWidgetItem
不是派生自
QWidget

设置其样式的唯一方法是通过 ::item 子控件,但无法获取没有状态的单个项目。

第二种方法:

您还没有指定您到底如何使用

QStyledItemDelegate::paint
,所以我的猜测是您没有正确覆盖它,请参阅答案上的Qt子类QStyledItemDelegate绘制方法从未被调用

如果解决了这个问题,您将需要绘制一个仅具有特定圆角的矩形。看一下这个,看看如何:在 Qt 中绘制只有 2 个圆角的矩形

我尝试过这种方法,但我建议不要这样做,因为要达到预期的结果需要太多的工作和混乱。

第三种方法:

使用

QFrame
作为容器只会添加另一层,它会在表格小部件及其视口之间导致同样的问题。

© www.soinside.com 2019 - 2024. All rights reserved.