天天看點

Qt基礎控件學習04 QTableWidget(詳解)

最近項目有需求,做一個類似這樣的子產品界面,于是第一時間想着用的是QTablewidget來實作,原因是指派和取值都友善一些,

而且這個子產品需要有單擊輕按兩下的動作。

Qt基礎控件學習04 QTableWidget(詳解)

開發的過程,不可避免的就是查一下文檔,或者看看别人怎麼寫的。于是就順便學一下QTablewidget。先上點基礎的有用的

一、設定表單樣式

  table_widget->setColumnCount(4); //設定列數

ui->tableWidget->setColumnWidth(0,20);//單獨設定某一列的寬度
           

  table_widget->horizontalHeader()->setDefaultSectionSize(150); 

  table_widget->horizontalHeader()->setClickable(false); //設定表頭不可點選(預設點選後進行排序)

  //設定表頭内容

  QStringList header;

  header<<tr("name")<<tr("last modify time")<<tr("type")<<tr("size");

  table_widget->setHorizontalHeaderLabels(header);

  //設定表頭字型加粗

  QFont font = this->horizontalHeader()->font();

  font.setBold(true);

  table_widget->horizontalHeader()->setFont(font);

  table_widget->horizontalHeader()->setStretchLastSection(true); //設定充滿表寬度

  table_widget->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);

  table_widget->verticalHeader()->setDefaultSectionSize(10); //設定行高

  table_widget->setFrameShape(QFrame::NoFrame); //設定無邊框

  table_widget->setShowGrid(false); //設定不顯示格子線

  table_widget->verticalHeader()->setVisible(false); //設定垂直頭不可見

  table_widget->setSelectionMode(QAbstractItemView::ExtendedSelection);  //可多選(Ctrl、Shift、  Ctrl+A都可以)

  table_widget->setSelectionBehavior(QAbstractItemView::SelectRows);  //設定選擇行為時每次選擇一行

  table_widget->setEditTriggers(QAbstractItemView::NoEditTriggers); //設定不可編輯

  table_widget->horizontalHeader()->resizeSection(0,150); //設定表頭第一列的寬度為150

  table_widget->horizontalHeader()->setFixedHeight(25); //設定表頭的高度

  table_widget->setStyleSheet("selection-background-color:lightblue;"); //設定選中背景色

  table_widget->horizontalHeader()->setStyleSheet("QHeaderView::section{background:skyblue;}"); //設定表頭背景色

  //設定水準、垂直滾動條樣式

  table_widget->horizontalScrollBar()->setStyleSheet("QScrollBar{background:transparent; height:10px;}"

  "QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"

  "QScrollBar::handle:hover{background:gray;}"

  "QScrollBar::sub-line{background:transparent;}"

  "QScrollBar::add-line{background:transparent;}");

  table_widget->verticalScrollBar()->setStyleSheet("QScrollBar{background:transparent; width: 10px;}"

  "QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"

  "QScrollBar::handle:hover{background:gray;}"

  "QScrollBar::sub-line{background:transparent;}"

  "QScrollBar::add-line{background:transparent;}");

檢視了别人的部落格。接下來自己就要動手了。先看看效果在依次解析一下,裡面遇到一些過程中的問題(幹貨):

一個是用QTableWidget做的,一個是QListWidget做的。先說說QTableWidget

1.首先去掉表格頭,和網格

ui->tableWidget->horizontalHeader()->setHidden(true);
ui->tableWidget->setShowGrid(false); //設定不顯示格子線
           

2.表格中第二列加入一個Qlabel。

QLabel *label = new QLabel(); 

label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

label->setText(QString::number(5-i));            
label->setStyleSheet("color:rgb(255, 255, 255);"                                
 "border-radius:4px;"                                
 "background-color:rgb(85, 0, 255);"                                 
"font: 9pt;");
           

ui->tableWidget->setIndexWidget(index,label);

但是光這樣是不行的,tablewidget的單元格預設把label控件撐滿

Qt基礎控件學習04 QTableWidget(詳解)

為了解決這個問題,我當時也是查了不少部落格,但大多數結果都不是很滿意。于是看到有人說用布局的思路。大概思路就是,用一個qwidget來裝一個布局,在布局裡調整一下控件的margin來達到内部的位置調整,再把qwidget裝入單元格,即使他自動撐滿也沒關系。設定好控件的最大尺寸。label->setMaximumSize(14,14);大功告成。

QWidget *widget = new QWidget;
        QHBoxLayout *hLayout;
        hLayout = new QHBoxLayout();
        hLayout->addWidget(label);
        hLayout->setMargin(0);
        hLayout->setAlignment(widget, Qt::AlignCenter);
        hLayout->setContentsMargins(1, 3, 1, 3);
        widget->setLayout(hLayout);
        ui->tableWidget->setIndexWidget(index,widget);
           

2.去掉表格中的虛線,和表格中行的背景色随滑鼠移動。

參考了下:大概是在表格中重寫一個委托類

QStyledItemDelegate類中一個paint函數。就可以。
           
StyledDelegate *dele = new StyledDelegate();
    ui->tableWidget->setItemDelegate(dele);
class StyledDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    explicit StyledDelegate(QObject *parent = Q_NULLPTR);
    ~StyledDelegate();

    void StyledDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
    {
        QStyleOptionViewItem itemOption(option);
        if (itemOption.state & QStyle::State_HasFocus)
        {
            itemOption.state = itemOption.state ^ QStyle::State_HasFocus;
        }

        //添加滑鼠滑過的背景色
        if(option.state & QStyle::State_MouseOver){
            painter->fillRect(itemOption.rect, QColor(180, 200, 220));
        }

        QStyledItemDelegate::paint(painter, itemOption, index);
    }


};
           

但這樣也僅僅隻能單個單元格。後面想了一下,tablewidget類設計的操作的單元應該是單元格,應該不會封裝行或者列之類的。如果真要達到,背景行跟随的話,思路就是取到行數,然後for()循環一個個單元刷掉。思路可以參考一下:https://blog.csdn.net/m0_37907070/article/details/78642599

我這裡就不再多寫。因為後面想了一下qlistwidget實作這個功能非常簡單

先上一下tablewidget的完整源碼:

ui->tableWidget->horizontalHeader()->setHidden(true);
    ui->tableWidget->verticalHeader()->setHidden(true);
    ui->tableWidget->setColumnCount(4);
    ui->tableWidget->setRowCount(10);
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
    //ui->tableWidget->setFrameShape(QFrame::NoFrame); //設定無邊框
    ui->tableWidget->setShowGrid(false); //設定不顯示格子線
    //ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    //ui->tableWidget->setStyleSheet("selection-background-color:rgb(255,209,128,0)");
    ui->tableWidget->setStyleSheet("QTableWidget::item:selected{background-color:rgb(0,0,0,0);color:rgb(0,0,0)}");
    ui->tableWidget->setColumnWidth(0,20);
    ui->tableWidget->setColumnWidth(1,20);
    ui->tableWidget->setColumnWidth(2,80);
    ui->tableWidget->setColumnWidth(3,80);
    ui->tableWidget->setMouseTracking(true);
    StyledDelegate *dele = new StyledDelegate();
    ui->tableWidget->setItemDelegate(dele);
    QAbstractItemModel *model = ui->tableWidget->model();
    for(int i = 0; i<10; i++)
    {
        ui->tableWidget->setRowHeight(i,22);

        QModelIndex index = model->index(i,1);
        QLabel *label = new QLabel();
        label->setMaximumSize(14,14);
        label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
        if(i<5)
        {
            ui->tableWidget->setItem(i,0,new QTableWidgetItem(QString("S")));
            label->setText(QString::number(5-i));
            label->setStyleSheet("color:rgb(255, 255, 255);"
                                 "border-radius:4px;"
                                 "background-color:rgb(85, 0, 255);"
                                 "font: 9pt;"
                                 "");
        }
        else
        {
            ui->tableWidget->setItem(i,0,new QTableWidgetItem(QString("B")));
            label->setText(QString::number(i-4));
            label->setStyleSheet("color:rgb(255, 255, 255);"
                                 "border-radius:4px;"
                                 "background-color:rgb(204, 0, 0);"
                                 "font: 9pt;");
        }
        QWidget *widget = new QWidget;
        QHBoxLayout *hLayout;
        hLayout = new QHBoxLayout();
        hLayout->addWidget(label);
        hLayout->setMargin(0);
        hLayout->setAlignment(widget, Qt::AlignCenter);
        hLayout->setContentsMargins(1, 3, 1, 3);
        widget->setLayout(hLayout);
        ui->tableWidget->setIndexWidget(index,widget);

        QTableWidgetItem * item3 = new QTableWidgetItem(QString("0.001"));
        QTableWidgetItem * item4 = new QTableWidgetItem(QString("1000"));
        item3->setTextAlignment(Qt::AlignRight| Qt::AlignHCenter);
        item4->setTextAlignment(Qt::AlignRight| Qt::AlignHCenter);
        ui->tableWidget->setItem(i,2,item3);
        ui->tableWidget->setItem(i,3,item4);

    }
           

然後是qlistwidget的

for(int i = 0; i<10; i++)
    {
        QListWidgetItem *item=new QListWidgetItem;

        item->setSizeHint(QSize(0,22));
        ui->listWidget->addItem(item);

        QLabel *label1 = new QLabel();
        QLabel *label2 = new QLabel();
        QLabel *label3 = new QLabel("0.001");
        QLabel *label4 = new QLabel("100000");
        label1->setMaximumSize(16,16);
        label2->setMaximumSize(14,14);

        label1->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
        label2->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
        label3->setAlignment(Qt::AlignHCenter | Qt::AlignRight);
        label4->setAlignment(Qt::AlignHCenter | Qt::AlignRight);

        if(i<5)
        {
            label1->setText("S");
            label2->setText(QString::number(5-i));
            label2->setStyleSheet("color:rgb(255, 255, 255);"
                                 "border-radius:4px;"
                                 "background-color:rgb(85, 0, 255);"
                                 "font: 9pt;");
        }
        else
        {
            label1->setText("B");
            label2->setText(QString::number(i-4));
            label2->setStyleSheet("color:rgb(255, 255, 255);"
                                 "border-radius:4px;"
                                 "background-color:rgb(204, 0, 0);"
                                 "font: 9pt;");
        }
        QWidget *widget = new QWidget;
        QHBoxLayout *hLayout;
        hLayout = new QHBoxLayout();
        hLayout->addWidget(label1);
        hLayout->addWidget(label2);
        hLayout->addWidget(label3);
        hLayout->addWidget(label4);
        hLayout->setMargin(0);
        hLayout->setAlignment(widget, Qt::AlignCenter);
        hLayout->setContentsMargins(1, 3, 1, 3);
        widget->setLayout(hLayout);
        ui->listWidget->setItemWidget(item,widget);
    }

//樣式
QListWidget::item:selected:active { background:rgb(0, 0, 223,0);}
QListWidget::item:selected:!active { background:rgb(0, 0, 223,0);}
           

是不是感覺Qlistwidget的很簡單?

參考一下部落格:

 https://blog.csdn.net/m0_37907070/article/details/78642599

http://blog.sina.com.cn/s/blog_a6fb6cc90101i8it.html

https://www.cnblogs.com/zhoug2020/p/3789076.html