2012-08-02 253 views
7

我已經使用QTableview和QAbstractTableModel創建了一個表。 在其中一個單元格中,我想添加一個幫助按鈕(該單元格的右下角)。將按鈕添加到QTableview

有沒有辦法達到上述目的?

回答

16

你將不得不爲你實現你自己的委託。

在Qt中,除了數據,模型和視圖外,您還有代表。他們提供輸入功能,他們還負責在View中呈現「特殊」項目,這正是您所需要的。

Qt doc對這些(關鍵字:Model/View programming)有很好的覆蓋率,您還可以找到一些示例herehere

另外(有點偏離主題,但我想我應該指出這一點),如果你使用普通的QTableWidget,你可以插入任何與它的setCellWidget()功能的單元格中的任何東西。

UPD

這裏是Qt的文檔(我與模型/視圖東西吸Qt的,所以不要打我辛苦爲這個代碼)一稍微變形例。它會在右側的每個單元格中繪製一個按鈕,並捕獲單元格中的單擊事件以檢查單擊是否在「按鈕」上,並相應地作出反應。

也許這不是最好的辦法,但正如我所提到的,我對Qt的模型和視圖並不太滿意。

要做正確的事情並允許正確編輯,您還需要執行createEditor(),setEditorData()setModelData()函數。

要在特定的單元格而不是所有單元格中繪製您的東西,只需在paint()函數中添加一個條件(請注意,它將模型索引作爲參數,因此您始終可以知道您正在繪製的單元格,以及油漆相應)。


delegate.h:

class MyDelegate : public QItemDelegate 
{ 
    Q_OBJECT 

public: 
    MyDelegate(QObject *parent = 0); 
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); 
}; 

delegate.cpp:

#include <QtGui> 
#include "delegate.h" 

MyDelegate::MyDelegate(QObject *parent) 
    : QItemDelegate(parent) 
{ 
} 


void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 30;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 30;//button width 
    h = 30;//button height 
    button.rect = QRect(x,y,w,h); 
    button.text = "=^.^="; 
    button.state = QStyle::State_Enabled; 

    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 
} 

bool MyDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) 
{ 
    if(event->type() == QEvent::MouseButtonRelease) 
    { 
     QMouseEvent * e = (QMouseEvent *)event; 
     int clickX = e->x(); 
     int clickY = e->y(); 

     QRect r = option.rect;//getting the rect of the cell 
     int x,y,w,h; 
     x = r.left() + r.width() - 30;//the X coordinate 
     y = r.top();//the Y coordinate 
     w = 30;//button width 
     h = 30;//button height 

     if(clickX > x && clickX < x + w) 
      if(clickY > y && clickY < y + h) 
      { 
       QDialog * d = new QDialog(); 
       d->setGeometry(0,0,100,100); 
       d->show(); 
      } 
    } 

    return true; 
} 

的main.cpp

#include "delegate.h" 

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

    QStandardItemModel model(4, 2); 
    QTableView tableView; 
    tableView.setModel(&model); 

    MyDelegate delegate; 
    tableView.setItemDelegate(&delegate); 

    tableView.horizontalHeader()->setStretchLastSection(true); 
    tableView.show(); 
    return app.exec(); 
} 

結果將是這樣的:

result

+0

我正在使用QTableview。 我想把這個按鈕放在一個特定的單元格中(該單元格的右下角).. 請問您可以分享一些代碼嗎? thankx in adv .. – Learner 2012-08-02 18:45:10

+0

@vikuseth,更新了我的回答 – SingerOfTheFall 2012-08-03 06:49:22

+0

@vikuseth,Oo它對我來說總是可見的。 – SingerOfTheFall 2012-08-04 18:12:53

0

當視圖要畫它調用委託的paint()提供了關於如何的一些信息功能的細胞,什麼,在哪裏畫的內容細胞。默認的委託只是繪製Qt :: DisplayRole文本和選擇狀態。如果你替換委託,那麼你完全替換了默認行爲:你可以繪製任何你喜歡的。如果你想要的文字,那麼你需要安排繪製它。你可以自己做,或者使用標準的C++機制,你可以先調用默認的繪圖代碼,然後在頂部繪製。 它添加QItemDelegate :: paint(畫家,選項,索引)後工作;在我的paint()方法的開始。

0

我得到了解決.. 舊漆方法:

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 30;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 30;//button width 
    h = 30;//button height 
    button.rect = QRect(x,y,w,h); 
    button.text = "=^.^="; 
    button.state = QStyle::State_Enabled; 

    QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 
} 

這裏是更新的paint()方法。

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
     QItemDelegate::paint(painter, option, index); 
    if(index.row()==8)//since i have to make it display only at (8,0) position . 
{ 
    if(index.column()==0) 
    { 
    QStyleOptionButton button; 
    QRect r = option.rect;//getting the rect of the cell 
    int x,y,w,h; 
    x = r.left() + r.width() - 20;//the X coordinate 
    y = r.top();//the Y coordinate 
    w = 15;//button width(based on the requirement) 
    h = 15;//button height(based on the requirement) 
    button.icon= QIcon(QString::fromUtf8("Resources/HelpIcon.png")); 
    button.iconSize = QSize(20,20); 
    button.rect = QRect(x,y,w,h); 
    button.text = "";//no text . since if text will be given then it will push the icon to left side based on the coordinates . 
    button.state = QStyle::State_Enabled; 

    //QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter); 

    QApplication::style()->drawControl(QStyle::CE_PushButtonLabel, &button, painter);//To make the Button transparent . 

    } 
    } 
} 
4

setIndexWidget爲我工作。 例子:

QPushButton* helpButton = new QPushButton("Help"); 

tableView->setIndexWidget(model->index(position,COLUMN_NUMBER), helpButton); 

如果你只是想添加一個按鈕,做的是點擊的東西,添加使用setIndexWidget()按鈕正常工作。我相信我們不需要繁瑣的繪畫方法或實施代表。

5

我有一個解決方案,沒有任何複雜的重新發明整個油漆過程。 我有一個TableView,我在每一行都有一個按鈕。 請注意,在我的情況下,for循環遍歷每一行。

QSignalMapper *signalMapper = new QSignalMapper(this); 

for(int i=0; i<rows.length(); i++) { //replace rows.length with your list or vector which consists of the data for your rows. 
    //do something with your data for normal cells...   
    auto item = model->index(i, COLUMN_FOR_WHATEVER_YOU_WANT); 
    model->setData(item, QVariant::fromValue(yourObject.getSpecificInformation())); 

    //make new button for this row 
    item = model->index(i, COLUMN_BUTTON); 
    QPushButton *cartButton = new QPushButton("Add"); 
    ui->table_view->setIndexWidget(item, cartButton); 

    signalMapper->setMapping(cartButton, i); 
    connect(cartButton, SIGNAL(clicked(bool)), signalMapper, SLOT(map())); 
} 
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(doSomething(int))); 

然後,您將自動獲取用戶單擊該按鈕所在行的索引。 你只需要使自己的插槽:

private SLOTS: 
    void doSomething(int row); 

如果您有特殊的細胞,它的工作類似。

請注意,我並不關心這個例子中的內存泄漏,而且我不完全知道如果你更新你的TableView會發生什麼......(它工作正常,但它可能不會刪除舊的按鈕 - 當新的創建時,指針)

+0

在Qt5中,你甚至不需要使用QSignalMapper;您可以將按鈕的信號連接到您選擇的外殼的拉姆達。 – 2016-07-27 09:43:27