QTableWidget 使い方まとめ (PyQt5/Qt Creator C++)

# はじめに

pyqt5やQt CreatorでQtのtableについて色々と試した内容をメモ

# PyQt5
## 1 シンプルに生成

QTableWidgetを生成し,サイズを4x3に変更するだけのシンプルなプログラム

```table1-1.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(400,400)
      self.setWindowTitle("PyQt5")

      self.table = QTableWidget(self)
      self.table.setRowCount(3)
      self.table.setColumnCount(4)

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
```

![Screenshot from 2021-12-07 16-38-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/6117b6b0-26dc-04d3-cbb3-f9d8462becd8.png)

## 2 tableに値を設定

`setItem`メソッドを使用`QTableWidgetItem("aaa")`みたいなクラスを入れれる.->"aaa"が入る

```table1-2.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(400,400)
      self.setWindowTitle("PyQt5")

      self.table = QTableWidget(self)
      self.table.setRowCount(3)
      self.table.setColumnCount(4)

      self.table.setItem(0,0,QTableWidgetItem("aaa"))

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()

```

![Screenshot from 2021-12-07 20-23-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/f1211395-4a73-422a-f8f3-f6765d3be8b6.png)


## 3.データを設定

```table2.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

table_data_ = {'1':['1','2','3','4','5','6','7','8','9'],
        '2':['1','2','3','4','5','6','7','8','9'],
        '3':['1','2','3','4','5','6','7','8','9'],
        '4':['1','2','3','4','5','6','7','8','9']}

class TableView(QTableWidget):
    def __init__(self, data, *args):
        QTableWidget.__init__(self, *args)
        self.data = table_data_
        self.setData()
        self.resizeColumnsToContents()
        self.resizeRowsToContents()
 
    def setData(self): 
        horHeaders = []
        for n, key in enumerate(sorted(self.data.keys())):
            horHeaders.append(key)
            for m, item in enumerate(self.data[key]):
                newitem = QTableWidgetItem(item)
                self.setItem(m, n, newitem)
        self.setHorizontalHeaderLabels(horHeaders)

class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(400,400)
      self.setWindowTitle("PyQt5")

      self.table = TableView(table_data_, 9, 4,self)

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
```

![Screenshot from 2021-12-07 16-52-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/a18ea0f4-c6ef-44b4-5a43-a9f0f5945ec0.png)

## 4.ボタンを押した時にtableの値を取得して表示

```table3.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

table_data_ = {'1':['1','2','3','4','5','6','7','8','9'],
        '2':['1','2','3','4','5','6','7','8','9'],
        '3':['1','2','3','4','5','6','7','8','9'],
        '4':['1','2','3','4','5','6','7','8','9']}

class TableView(QTableWidget):
    def __init__(self, data, *args):
        QTableWidget.__init__(self, *args)
        self.data = table_data_
        self.setData()
        self.resizeColumnsToContents()
        self.resizeRowsToContents()
 
    def setData(self): 
        horHeaders = []
        for n, key in enumerate(sorted(self.data.keys())):
            horHeaders.append(key)
            for m, item in enumerate(self.data[key]):
                newitem = QTableWidgetItem(item)
                self.setItem(m, n, newitem)
        self.setHorizontalHeaderLabels(horHeaders)

class window(QWidget):
  def __init__(self, parent = None):
    super(window, self).__init__(parent)
    self.resize(400,400)
    self.setWindowTitle("PyQt5")

    self.table = TableView(table_data_, 9, 4, self)

    self.button = QPushButton('button', self)
    self.button.move(120,300)
    self.button.clicked.connect(self.print_table_val)

    
  def print_table_val(self):

    # get table value at(0,0)
    print(self.table.item(0,0).text())     

    # get table all value
    datas = []
    for i in range(4):
      row = []
      for j in range(9):
        row.append(self.table.item(j,i).text())
      datas.append(row)
    print(datas)

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
```


![Screenshot from 2021-12-07 17-31-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/a57d44bc-988f-8bcf-a8b6-b62d016b295a.png)


## 5.tableの値を変える

```table4.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

table_data_ = {'1':['1','2','3','4','5','6','7','8','9'],
        '2':['1','2','3','4','5','6','7','8','9'],
        '3':['1','2','3','4','5','6','7','8','9'],
        '4':['1','2','3','4','5','6','7','8','9']}

class TableView(QTableWidget):
    def __init__(self, data, *args):
        QTableWidget.__init__(self, *args)
        self.data = table_data_
        self.setData()
        self.resizeColumnsToContents()
        self.resizeRowsToContents()
 
    def setData(self): 
        horHeaders = []
        for n, key in enumerate(sorted(self.data.keys())):
            horHeaders.append(key)
            for m, item in enumerate(self.data[key]):
                newitem = QTableWidgetItem(item)
                self.setItem(m, n, newitem)
        self.setHorizontalHeaderLabels(horHeaders)

class window(QWidget):
  def __init__(self, parent = None):
    super(window, self).__init__(parent)
    self.resize(400,400)
    self.setWindowTitle("PyQt5")

    self.table = TableView(table_data_, 9, 4, self)

    self.button = QPushButton('button', self)
    self.button.move(120,300)
    self.button.clicked.connect(self.change_table_val)
    
  def change_table_val(self):
    table_data_['1'][0] = '33'
    self.table.setData() 

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
```

ボタンを押すと,tableの(0,0)の値が33に変わります

![Screenshot from 2021-12-07 17-40-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/5c7c9fca-6b35-84a4-97b8-c6d49672064a.png)

## 6.Qt Designerで使う場合の要点

### 1.デザイン上の注意点

デザイン上綺麗にitemだけ表示される様にするためには写真の様に
テーブルのQWidgetの`sizePolicy`を`Preferred` + `QAbstractScrollArea`を`AdjustToContents`にします。
左上に配置したい場合はバネを配置します。

![Screenshot from 2021-12-07 19-30-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/2bf7b729-1be2-c019-9a36-b881215e8d17.png)

![Peek 2021-12-07 19-30.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/92699e2e-de5b-393b-0aad-0a6cfa87d8eb.gif)

## 7.tableにwidgetを埋め込む

https://stackoverflow.com/questions/24148968/how-to-add-multiple-qpushbuttons-to-a-qtableview

```table7.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class LoadTable(QtWidgets.QTableWidget):
    def __init__(self, parent=None):
        super(LoadTable, self).__init__(1, 5, parent)
        self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))   
        headertitle = ("A","B","C","D","E")
        self.setHorizontalHeaderLabels(headertitle)
        self.verticalHeader().hide()
        self.horizontalHeader().setHighlightSections(False)
        self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)

        self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.setColumnWidth(0, 130)

        combox_lay = QtWidgets.QComboBox(self)
        combox_lay.addItems(["I","II"])
        self.setCellWidget(0, 4, combox_lay)

        self.cellChanged.connect(self._cellclicked)

    @QtCore.pyqtSlot(int, int)
    def _cellclicked(self, r, c):
        it = self.item(r, c)
        it.setTextAlignment(QtCore.Qt.AlignCenter)        

    @QtCore.pyqtSlot()
    def _addrow(self):
        rowcount = self.rowCount()
        self.insertRow(rowcount)
        combox_add = QtWidgets.QComboBox(self)
        combox_add.addItems(["I","II"])
        self.setCellWidget(rowcount, 4, combox_add)

    @QtCore.pyqtSlot()
    def _removerow(self):
        if self.rowCount() > 0:
            self.removeRow(self.rowCount()-1)


class ThirdTabLoads(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ThirdTabLoads, self).__init__(parent)    

        table = LoadTable()

        add_button = QtWidgets.QPushButton("Add")
        add_button.clicked.connect(table._addrow)

        delete_button = QtWidgets.QPushButton("Delete")
        delete_button.clicked.connect(table._removerow)

        button_layout = QtWidgets.QVBoxLayout()
        button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
        button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)


        tablehbox = QtWidgets.QHBoxLayout()
        tablehbox.setContentsMargins(10, 10, 10, 10)
        tablehbox.addWidget(table)

        grid = QtWidgets.QGridLayout(self)
        grid.addLayout(button_layout, 0, 1)
        grid.addLayout(tablehbox, 0, 0)        


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = ThirdTabLoads()
    w.show()
    sys.exit(app.exec_())
```

![Screenshot from 2021-12-09 12-35-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/850f3336-d7ab-b854-60dc-0d52c9776b67.png)

## 8.ボタン埋め込み

```table8.py
import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class LoadTable(QtWidgets.QTableWidget):
    def __init__(self, parent=None):
        super(LoadTable, self).__init__(1, 5, parent)
        self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))   
        headertitle = ("A","B","C","D","E")
        self.setHorizontalHeaderLabels(headertitle)
        self.verticalHeader().hide()
        self.horizontalHeader().setHighlightSections(False)
        self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)

        self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.setColumnWidth(0, 130)

        #combox_lay = QtWidgets.QComboBox(self)
        #combox_lay.addItems(["I","II"])
        button = QtWidgets.QPushButton(self)
        button.setText('Click!')
        self.setCellWidget(0, 4, button)

        self.cellChanged.connect(self._cellclicked)

    @QtCore.pyqtSlot(int, int)
    def _cellclicked(self, r, c):
        it = self.item(r, c)
        it.setTextAlignment(QtCore.Qt.AlignCenter)        

    @QtCore.pyqtSlot()
    def _addrow(self):
        rowcount = self.rowCount()
        self.insertRow(rowcount)
        button = QtWidgets.QPushButton(self)
        button.setText('Click!')
        self.setCellWidget(rowcount, 4, button)

    @QtCore.pyqtSlot()
    def _removerow(self):
        if self.rowCount() > 0:
            self.removeRow(self.rowCount()-1)


class ThirdTabLoads(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ThirdTabLoads, self).__init__(parent)    

        table = LoadTable()

        add_button = QtWidgets.QPushButton("Add")
        add_button.clicked.connect(table._addrow)

        delete_button = QtWidgets.QPushButton("Delete")
        delete_button.clicked.connect(table._removerow)

        button_layout = QtWidgets.QVBoxLayout()
        button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
        button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)


        tablehbox = QtWidgets.QHBoxLayout()
        tablehbox.setContentsMargins(10, 10, 10, 10)
        tablehbox.addWidget(table)

        grid = QtWidgets.QGridLayout(self)
        grid.addLayout(button_layout, 0, 1)
        grid.addLayout(tablehbox, 0, 0)        


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = ThirdTabLoads()
    w.show()
    sys.exit(app.exec_())
```

![Screenshot from 2021-12-09 12-48-55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/b42a2044-49fc-629e-a2ab-9fb0d1a065ee.png)

## ボタン埋め込みシンプルver

```table9.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class window(QWidget):
   def __init__(self, parent = None):
      super(window, self).__init__(parent)
      self.resize(400,400)
      self.setWindowTitle("PyQt5")

      self.table = QTableWidget(self)
      self.table.setRowCount(3)
      self.table.setColumnCount(4)

      button = QPushButton(self)
      button.setText('Click!')
      self.table.setCellWidget(0, 0, button)

def main():
   app = QApplication(sys.argv)
   ex = window()
   ex.show()
   sys.exit(app.exec_())
if __name__ == '__main__':
   main()
```

![Screenshot from 2021-12-09 12-52-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/15a2cc9a-6d26-4177-8d08-203de07e42ff.png)

### 2.python表示

- コード生成

```
pyuic5 -o table_ui.py table.ui
```

- 生成したpythonコードを読み込んで表示するプログラム

```table1.py
import sys

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow

from table_ui import Ui_MainWindow


class Gui(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Gui, self).__init__(parent)
        self.setupUi(self)

if __name__ == '__main__':
    argvs = sys.argv
    app = QApplication(argvs)
    gui = Gui()
    gui.show()
    sys.exit(app.exec_())
```

![Peek 2021-12-07 19-52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/418e4bb1-7e62-9051-0f54-b9565d379714.gif)

- テーブルの値を変えてみる

```table2.py
import sys

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QMainWindow, QTableWidgetItem

from table_ui import Ui_MainWindow


class Gui(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Gui, self).__init__(parent)
        self.setupUi(self)
        self.tableWidget.setItem(0,0,QTableWidgetItem("aaa"))

if __name__ == '__main__':
    argvs = sys.argv
    app = QApplication(argvs)
    gui = Gui()
    gui.show()
    sys.exit(app.exec_())
```

![Screenshot from 2021-12-07 20-28-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/d43c2d27-3eb9-a662-b4a4-70f43ed32541.png)

# Qt Creator

## 1.値を入れる

1.UIはデザイナーのときと同じ様に以下のように設定.

![Screenshot from 2021-12-07 22-05-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/6a471f8e-3ed5-3a35-79c1-599672a597cf.png)


2.`mainWindow.cpp`に以下の２行を追加し,テーブルに値をいれます

```
    QTableWidgetItem *newItem = new QTableWidgetItem(tr("%1").arg(333));
    ui->tableWidget->setItem(0,0,newItem);
```

追加後は以下のようになります

```mainWindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"



MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QTableWidgetItem *newItem = new QTableWidgetItem(tr("%1").arg(333));
    ui->tableWidget->setItem(0,0,newItem);
}

MainWindow::~MainWindow()
{
    delete ui;
}

```

![Screenshot from 2021-12-07 22-07-36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/63372b98-a5f4-ff85-5d4a-e376565b2b2a.png)

## 2.テーブルにwidgetを入れる

まず,UIでテーブルとボタンを配置

![Screenshot from 2021-12-09 13-24-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/6e52c35b-2083-d5b6-090e-335e9fabc88b.png)

mainwindow.cpp内で以下の様に記載すると,tableの(0,0)位置にpushbuttonが埋め込まれる.

```
ui->tableWidget->setCellWidget(0,0,ui->pushButton);
```

![Screenshot from 2021-12-09 13-24-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/80f76c3d-2d3b-c291-0ea3-0aecc08cf816.png)


```mainwindow.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->tableWidget->setCellWidget(0,0,ui->pushButton);
}

MainWindow::~MainWindow()
{
    delete ui;
}
```

# 最後に

色々と理解していって,速くまとまったアプリケーションを作成できたらいいなと思います。

# 参考

uiから作成したプログラムに追加して,ボタンクリックでラベル文字の変更するように

https://qiita.com/grinpeaceman/items/54b439bfa52640c444e1