您的位置:首页 > 编程语言 > Qt开发

QTableWidget中表格显示图片

2016-06-22 17:41 423 查看
QTableWidget中的表格显示图片有几种方式:

需要先将图片加载为资源。

1.直接在创建QTableWidgetItem的时候创建,如

tableWdiget->setItem(0,1,new QTableWidgetItem(QIcon(":/image/cpu")," "));

2.通过在item中创建一个label,通过label的setPixMap函数来显示图片:

QLabel *label = new QLabel("");

label->setPixmap(QPixmap(":/image/grid").scaled(30,30));

ui->matrixViewTable->setCellWidget(0,i,label);


3.通过继承 QStyledItemDelegate类使用委托来实现item中显示图片:

class QPixmapItemdele : public QStyledItemDelegate

{

public:

QPixmapItemdele(QObject* parent = 0):QStyledItemDelegate(parent){ }

//在委托类的paint中画图

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

{

if(index.data(Qt::DisplayRole).canConvert<QPixmap>())

{

QPixmap pix = index.data(Qt::DisplayRole).value<QPixmap>();

painter->drawPixmap(option.rect,pix);

}


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

}

};

然后为tablewidget设置委托,后面就可以设置具体的某项的图片:
ui->matrixViewTable->setItemDelegate(new QPixmapItemdele());

//以下是设置第一行的所有列的图片

for(int i=0; i<ui->matrixViewTable->columnCount(); i++)
{ 
QTableWidgetItem *item = new QTableWidgetItem();
ui->matrixViewTable->setItem(0,i,item);
item->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(":/image/grid").scaled(30,30)));
}


以上三种方法,法一直接在item上创建Icon,则表中每个Item表示为左边icon,右边为icon对应的text,即使text为空,也会留出很大的空间出来,导致左边的icon很小,

可以用以下语句来设置左边图标大小:

ui->matrixViewTable->setIconSize(QSize(30,30));

但是右边还是有text留出来的空间,如果想让icon充满整个item,则此方法没法达成。

法二通过item中创建label来setPixMap的方式可以让icon充满整个item,但是显示出来的icon用鼠标点击不会有选择动作发生,或者也许可以处理点击事件(未
4000
试过,不知是否能行)。

法三继承委托能够让图片充满整个item,同时选择图片时,会出现选择框,不至于像法二一样点击了没有任何反应。

以下是法三QWidgetTable使用委托的代码(委托类已在上面给出):

ui->matrixViewTable->setItemDelegate(new QPixmapItemdele());

int colcount = 17;

int rowcount = 2;

ui->matrixViewTable->setColumnCount(colcount);

ui->matrixViewTable->setRowCount(rowcount);

ui->matrixViewTable->horizontalHeader()->setVisible(false);

ui->matrixViewTable->verticalHeader()->setVisible(false);

ui->matrixViewTable->setSelectionMode(ui->matrixViewTable->NoSelection);

ui->matrixViewTable->setEditTriggers(ui->matrixViewTable->SelectedClicked);

ui->matrixViewTable->setShowGrid(false);

ui->matrixViewTable->setFrameShape(QFrame::NoFrame);

const int width = 30;


for(int i=0; i<ui->matrixViewTable->columnCount(); i++)

{ 

ui->matrixViewTable->setColumnWidth(i,width);

//设置第8列为间隔行,不允许点击或选择

if(i==8)

{

QTableWidgetItem *itm1 = new QTableWidgetItem();

ui->matrixViewTable->setItem(0,i,itm1);

itm1->setFlags(Qt::NoItemFlags);


QTableWidgetItem *itm2 = new QTableWidgetItem();

ui->matrixViewTable->setItem(1,i,itm2);

itm2->setFlags(Qt::NoItemFlags);

continue;

}

QTableWidgetItem *item = new QTableWidgetItem();

ui->matrixViewTable->setItem(0,i,item);

item->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(":/image/grid").scaled(30,30)));


QTableWidgetItem *item2 = new QTableWidgetItem();

ui->matrixViewTable->setItem(1,i,item2);

item2->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(":/image/grid").scaled(30,30)));

}


ui->matrixViewTable->setColumnWidth(8,15);

以下是运行生成的效果,每个表格中间是一个图片:



使用委托能够在表格中显示图片,但是如果要在表格中画图,比如画线,则使用委托画出来的图会把线覆盖掉,也就是线会有画出来,但是看不到,实际是画了在图的下面。

在表格中显示图片还有第4种方法,安装事件过滤器,然后在过滤器函数EventFilter()函数中进行画图。因为此处用到的QTableWidget是Widget中的一个控件,因此可以安装事件过滤器,让Widget监视QTableWidget中的事件。代码如下,在类中重写QWidget类的eventFilter函数,然后创建表格时,每一列就创建为空,在evenFilter函数中检测到paint事件时才进行将图片画到表格中。

class MatrixView : public QWidget

{

Q_OBJECT


public:

explicit MatrixView(QWidget *parent = 0);

~MatrixView();


public:

bool eventFilter(QObject *, QEvent *);

private:

void InitTableWidget();

bool IsMouseInTableWidget(QEvent *event, QPoint &p);


void SetPointToCenter(QPoint&);

private:

Ui::MatrixView *ui;

QPoint m_beginP;

QPoint m_endP;

bool m_bmove;

bool m_brelease;

};

//以下是在构造函数中创建表格,表格其他部分与上面代码一样

m_bmove = false;
m_brelease = false;
//必须是tablewidget的viewport注册事件过滤才会有鼠标事件,如果是tablewidget注册,则收到除了鼠标事件外的其他事件,也就是鼠标事件收不到
ui->matrixViewTable->viewport()->installEventFilter(this);


for(int i=0; i<ui->matrixViewTable->columnCount(); i++)

{ 

ui->matrixViewTable->setColumnWidth(i,COL_WIDTH);

//设置第8列为间隔行,不允许点击或选择

if(i == NULL_COL)

{

QTableWidgetItem *itm1 = new QTableWidgetItem();

ui->matrixViewTable->setItem(0,i,itm1);

itm1->setFlags(Qt::NoItemFlags);


QTableWidgetItem *itm2 = new QTableWidgetItem();

ui->matrixViewTable->setItem(1,i,itm2);

itm2->setFlags(Qt::NoItemFlags);

continue;

}


QTableWidgetItem *item = new QTableWidgetItem();

ui->matrixViewTable->setItem(0,i,item);

//使用委托显示图片

//item->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(pixmap).scaled(30,30)));


QTableWidgetItem *item2 = new QTableWidgetItem();

ui->matrixViewTable->setItem(1,i,item2);

//item2->setData(Qt::DisplayRole,QVariant::fromValue<QPixmap>(QPixmap(pixmap).scaled(30,30)));

}


//在eventFilter中获取tablewidget的鼠标按下、移动,释放事件,进行画线,在画线之前进行画图。此处画图的效果与法三的效果一样,且可以在图上面画线。如果不需要处理鼠标事件,此处可以忽略3个鼠标事件的判断。

bool MatrixView::eventFilter(QObject *object, QEvent *event)

{

//   qDebug("%s type:%d",object->objectName().toStdString().c_str(),event->type());

if(object->objectName()!=QString("qt_scrollarea_viewport"))

{

return QWidget::eventFilter(object,event);

}



if(event->type() == QEvent::MouseButtonPress)

{

if(IsMouseInTableWidget(event,m_beginP))

{

m_endP = m_beginP;

update();

}

}


if(event->type() == QEvent::MouseButtonRelease)

{

IsMouseInTableWidget(event,m_endP);

m_brelease = true;

SetPointToCenter(m_endP);

update();

}


if(event->type() == QEvent::MouseMove)

{

QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);

//不进行判断左右键,如果判断左右键,会导致m_endP有时无值,画出的线断断续续

m_endP = mouseEvent->pos();

m_bmove = true;

update();

}



if(event->type() == QEvent::Paint)

{

QPainter paint(ui->matrixViewTable->viewport());


//使用paint事件在表格中画图

int w = COL_WIDTH;

int h = ui->matrixViewTable->rowHeight(0);

for(int i=0; i<ui->matrixViewTable->columnCount()-1; i++)

{

int x = i>=NULL_COL ? i*COL_WIDTH+NULL_COL_WIDTH : i*COL_WIDTH;

int y = 0;

int y1 = ui->matrixViewTable->rowHeight(0);

QPixmap pix(":/image/grid");

paint.drawPixmap(QRect(x,y,w,h),pix);


QPixmap pix1(":/image/grid");

paint.drawPixmap(QRect(x,y1,w,h),pix1);

}

//在表格中画线,线随鼠标动

if(m_bmove)

{

QPen pen(Qt::black,5);

paint.setPen(pen);

SetPointToCenter(m_beginP); //取得鼠标最接近项的中心点

paint.drawPoint(m_beginP);



QPen pen1(Qt::black,3);

paint.setPen(pen1);

paint.drawLine(m_beginP,m_endP);



QPen pen2(Qt::black,5);

paint.setPen(pen2);

paint.drawPoint(m_endP);

}

if(m_brelease)

{

m_bmove = false;

m_brelease = false;

}

}

//此处必须返回基类的eventFilter,以让基类有机会进行处理其他事情,否则单单返回true,Qtablewidget上面将无其他东西显示


return QWidget::eventFilter(object,event);

}


//判断鼠标按下的点是否在表格内,可无需关注


bool MatrixView::IsMouseInTableWidget(QEvent *event, QPoint &point)

{

if(event->type() == QEvent::MouseButtonPress  ||

event->type() == QEvent::MouseButtonRelease||

event->type() == QEvent::MouseMove)

{

QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);

if(mouseEvent->button() == Qt::LeftButton)

{

QPoint p = mouseEvent->pos();

//检查鼠标位置是否点在列表的项中,需要考虑中间空白间隔的那列除外

int col = p.x()/COL_WIDTH>=NULL_COL ? (p.x()+NULL_COL_WIDTH)/COL_WIDTH : p.x()/COL_WIDTH;

int row = p.y()/ui->matrixViewTable->rowHeight(0);

if(col<ui->matrixViewTable->columnCount() && row<ui->matrixViewTable->rowCount())

{

if(col != NULL_COL)

{

point = p;

return true;

}

}

}

}

return false;

}


//取得最靠近该点的项的中心点,可无需关注

void MatrixView::SetPointToCenter(QPoint &point)

{

int x = 0;

if(point.x()/COL_WIDTH < NULL_COL)

{

x = point.x()/COL_WIDTH*COL_WIDTH + COL_WIDTH/2;

}

else

{

//因为第8列是空列,所以要排除这一列,先将point所在的x坐标减去8列前的部分,得到超出8列后的部分,就可以按照取中心点的方法取得这超出后部分的中心点,再加上8列前部分的位置,就得到最终的中心点

int null_col_end_x = NULL_COL*COL_WIDTH + NULL_COL_WIDTH;

x = null_col_end_x + (point.x()-null_col_end_x)/COL_WIDTH*COL_WIDTH + COL_WIDTH/2;

}


int h = ui->matrixViewTable->rowHeight(0);

int y = point.y()/h*h + h/2;

point = QPoint(x,y);

}

效果 图:(图中直线上的折线是抗锯齿,如果线宽小的话就不会这么明显)




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: