QTableWidgetと、「上に移動」と「下に移動」の2つのボタンについて考えてみます。上に移動をクリックすると、「下に移動」と同様に、現在の行が1行上に移動します。
対応する上への移動と下への移動機能を実装する最も簡単な方法は何ですか?
QTableWidgetと、「上に移動」と「下に移動」の2つのボタンについて考えてみます。上に移動をクリックすると、「下に移動」と同様に、現在の行が1行上に移動します。
対応する上への移動と下への移動機能を実装する最も簡単な方法は何ですか?
私はそれを使用してそれを行うことができましたQTableWidget
、ここに完全な例があります:
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class mtable(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.move_up = QtGui.QAction("Move_Up", self)
self.connect(self.move_up, QtCore.SIGNAL('triggered()'), self.moveUp)
self.move_down = QtGui.QAction("Move_Down",self)
self.connect(self.move_down, QtCore.SIGNAL('triggered()'), self.moveDown)
self.toolbar = self.addToolBar('Toolbar')
self.toolbar.addAction(self.move_up)
self.toolbar.addAction(self.move_down)
##Init Table
self.table = QtGui.QTableWidget(4,3)
for i in range(0,4):
for j in range(0,4):
self.table.setItem(i,j,QtGui.QTableWidgetItem("a_"+str(i)+str(j)))
self.setCentralWidget(self.table)
def moveDown(self):
row = self.table.currentRow()
column = self.table.currentColumn();
if row < self.table.rowCount()-1:
self.table.insertRow(row+2)
for i in range(self.table.columnCount()):
self.table.setItem(row+2,i,self.table.takeItem(row,i))
self.table.setCurrentCell(row+2,column)
self.table.removeRow(row)
def moveUp(self):
row = self.table.currentRow()
column = self.table.currentColumn();
if row > 0:
self.table.insertRow(row-1)
for i in range(self.table.columnCount()):
self.table.setItem(row-1,i,self.table.takeItem(row+1,i))
self.table.setCurrentCell(row-1,column)
self.table.removeRow(row+1)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
tb = mtable()
tb.show()
sys.exit(app.exec_())
以前は十分な詳細がなかったため、回答を修正しました
このプロセスには、現在の選択を参照するスロット (またはスロット) にボタンを接続し、ビューからボタンを移動して新しい場所に挿入することが含まれます。
次の例は、実際に QTableView + QStandardItemModel を使用しています。その理由は、ウィジェットからのメソッドしか使用できないため、QTableWidget がはるかに制限されているためです。モデルと選択モデルを直接操作できるようになると、はるかに簡単になります。takeItem()
ただし、各行を構築するために複数回使用する場合、QTableWidget のこの例を作り直すことは可能です...
完全に機能する例を次に示します。
from PyQt4 import QtCore, QtGui
from functools import partial
class Dialog(QtGui.QDialog):
DOWN = 1
UP = -1
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.resize(800,600)
self.table = QtGui.QTableView(self)
self.table.setSelectionBehavior(self.table.SelectRows)
self.model = QtGui.QStandardItemModel(20, 6, self)
self.table.setModel(self.model)
self.upBtn = QtGui.QPushButton('Up', self)
self.downBtn = QtGui.QPushButton('Down', self)
self.mainLayout = QtGui.QVBoxLayout(self)
self.mainLayout.addWidget(self.table)
self.buttonLayout = QtGui.QHBoxLayout()
self.buttonLayout.addWidget(self.upBtn)
self.buttonLayout.addWidget(self.downBtn)
self.mainLayout.addLayout(self.buttonLayout)
self.upBtn.clicked.connect(partial(self.moveCurrentRow, self.UP))
self.downBtn.clicked.connect(partial(self.moveCurrentRow, self.DOWN))
self._initTable()
def _initTable(self):
for row in xrange(self.model.rowCount()):
for col in xrange(self.model.columnCount()):
item = QtGui.QStandardItem('%d_%d' % (row+1, col+1))
self.model.setItem(row, col, item)
def moveCurrentRow(self, direction=DOWN):
if direction not in (self.DOWN, self.UP):
return
model = self.model
selModel = self.table.selectionModel()
selected = selModel.selectedRows()
if not selected:
return
items = []
indexes = sorted(selected, key=lambda x: x.row(), reverse=(direction==self.DOWN))
for idx in indexes:
items.append(model.itemFromIndex(idx))
rowNum = idx.row()
newRow = rowNum+direction
if not (0 <= newRow < model.rowCount()):
continue
rowItems = model.takeRow(rowNum)
model.insertRow(newRow, rowItems)
selModel.clear()
for item in items:
selModel.select(item.index(), selModel.Select|selModel.Rows)
if __name__ == "__main__":
app = QtGui.QApplication([])
d = Dialog()
d.show()
d.raise_()
app.exec_()
init は単純で、テーブル、モデル、およびボタンをセットアップするだけです。を使用して両方のボタンを同じメソッドに接続しますfunctools.partial
。これは、同じ関数呼び出しを異なる引数でラップするのに非常に便利です。次に、テーブルは 20x6 データで埋められます。
ボタンがクリックされると、行が選択されていることを確認します。選択された行ごとに、そのアイテムを解決し (移動後に再選択するために)、1 を加算または減算して新しい行番号を決定します。また、有効な移動範囲内にあることを確認し、そうでない場合はスキップします。takeRow()
最後に、インデックスのリストとして行全体を削除するために呼び出し、その行を新しい行番号に挿入し直します。そのループの後、保存したアイテムを使用して新しいインデックスを検索し、それらを再度選択します。