2016-12-03 5 views
1

私は以下のようにQTableViewを持っています。私はテストボタンを押して、カーソルに "a"を挿入したいと思っています - 例えば、(行、列)=(2,2)の "11"の真ん中にあります。つまり、ユーザーはセル(2,2)をダブルクリックし、カーソルを "11"の中央に置き、Testを押します。望ましい結果: "1a1"。PyQt:QTableViewのカーソルにテキストを挿入する方法

screen capture

このなんとかですか?はいの場合、どうですか?どうもありがとう。

# coding: utf-8 

import sys 
from PyQt4 import QtGui, QtCore 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

MY_ARRAY = [['00', '01', '02'], 
      ['10', '11', '12'], 
      ['20', '21', '22']] 


class MyWindow(QTableView): 
    def __init__(self, *args): 
     super(MyWindow, self).__init__() 

     self.tablemodel = MyTableModel(MY_ARRAY) 

     self.tableview = QTableView() 

     self.tableview.setModel(self.tablemodel) 

     self.tableview.setItemDelegate(MyDelegate(self)) 

     self.layout = QVBoxLayout(self) 
     self.layout.addWidget(self.tableview) 

     self.button1 = QPushButton("Test") 

     self.button1.released.connect(self.test) 

     self.layout.addWidget(self.button1) 
     self.setLayout(self.layout) 

    def test(self): 

     # MY_ARRAY.append([30,31,32]) 

     index = self.tableview.currentIndex() 
     item = self.tablemodel.data(index, Qt.DisplayRole) 

     print("item %s " % item) 

     item_edit = self.tableview.edit(index) 

     qDebug("qDebug: item_edit %s " % item_edit) 

     MY_ARRAY.insert(index.row(), ['30', '31', '32']) 

     self.tablemodel.layoutChanged.emit() 

     qDebug(" {} " .format(MY_ARRAY)) 

     qcursor = QCursor.pos() 
     qDebug(" {} ".format(qcursor)) 

     qcursor1 = self.mapFromGlobal(qcursor) 
     qDebug(" {} ".format(qcursor1)) 

     # qDebug(" self.tableview.indexAt(qcursor) {} ".format(self.tableview(qcursor))) 
     # qDebug(" self.tableview.indexAt(qcursor1) {} ".format(self.tableview(qcursor1))) 

     # print(' index.row(): ', index.row()) 

     qDebug(
      " tableview.rowViewportPosition %s " % 
      self.tableview.rowViewportPosition(index.row())) 
     qDebug(
      " tableview.columnViewportPosition %s " % 
      self.tableview.columnViewportPosition(index.column())) 

     # qDebug(" tableview.viewport() %s " % self.tableview.viewport(qcursor)) 

     item = self.tableview.setCurrentIndex(index) 
     qDebug(" tableview.item() %s " % self.tableview) 


class MyTableModel(QAbstractTableModel): 
    def __init__(self, datain, parent=None, *args): 
     super(MyTableModel, self).__init__(parent, *args) 

     self.arraydata = datain 

    def rowCount(self, parent): 
     return len(self.arraydata) 

    def columnCount(self, parent): 
     return len(self.arraydata[0]) 

    def data(self, index, role): 
     if not index.isValid(): 
      return None 

     elif not (role == Qt.DisplayRole or role == Qt.EditRole): 
      return None 
     return (self.arraydata[index.row()][index.column()]) 

    def setData(self, index, value, role=Qt.EditRole): 
     self.arraydata[index.row()][index.column()] = value 
     return True 

    def flags(self, index): 
     return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable 


class MyDelegate(QStyledItemDelegate): 

    def __init__(self, parent=None): 
     super(MyDelegate, self).__init__(parent) 

    def createEditor(self, parent, option, index): 
     editor = QLineEdit(parent) 
     self.connect(editor, SIGNAL("returnPressed()"), 
        self.commitAndCloseEditor) 
     return editor 

    def commitAndCloseEditor(self): 
     editor = self.sender() 
     if isinstance(editor, (QTextEdit, QLineEdit)): 
      self.emit(SIGNAL("commitData(QWidget*)"), editor) 
      self.emit(SIGNAL("closeEditor(QWidget*)"), editor) 

    def setEditorData(self, editor, index): 
     text = index.model().data(index, Qt.DisplayRole) 

     editor.setText(text) 

    def setModelData(self, editor, model, index): 
     model.setData(index, editor.text()) 

def main(): 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_()) 

if __name__ == "__main__": 
    main() 
+0

ようこそスタックオーバーフロー!宿題の助けを求めているようです。それ自体に問題はありませんが、これらのことを守ってください(http://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions/338845#338845)、それに応じて質問を編集してください。 @JoeC。 –

+0

これは本当に宿題のようなものではありません。 – ekhumoro

+0

それは宿題ではありません。私のアマチュアプロジェクトでは、デュアル言語アライメントについての問題です。アロロジックは2つのテキストを自動的に整列させます。非常に頻繁にミスアライメントがあり、手動の調整が必要です。私はPyQtには比較的新しいです。私は数日を読んで本を読んで、グーグルでは何も解決策を見つけることができませんでした。だから、誰かがポインタを2つ与えることができれば本当に感謝しています。 – mike

答えて

1

表のセルにはカーソルがないため、直接編集することはできません。編集機能はitem-delegateによって提供されます。デフォルトでは、テキストデータのエディタウィジェットはQLineEditですが、数値データの場合はQSpinBox、ブールデータの場合はなど、さまざまなエディタウィジェットを使用できます。使用される特定のウィジェットは、custom item-delegateに設定することで制御できます。

編集ウィジェットにテキストを挿入するためのボタンのようなものを使用することの大きな問題は、ボタンをクリックするとすぐにエディタが自動的に閉じられ(破棄される)ということです。したがって、カスタムアクションを追加し、コンテキスト・メニューを使用することがはるかに簡単になります。

class MyWindow(QTableView): 
    def __init__(self, *args): 
     ... 
     self.delegate = MyDelegate(self) 
     self.delegate.contextMenuRequested.connect(self.showContextMenu) 
     self.tableview.setItemDelegate(self.delegate) 

    def showContextMenu(self, editor, pos): 
     pos = editor.mapToGlobal(pos) 
     menu = editor.createStandardContextMenu() 
     menu.addSeparator() 
     action = menu.addAction('Insert Text') 
     if menu.exec_(pos) is action: 
      editor.insert(' foo ') 

class MyDelegate(QStyledItemDelegate): 
    contextMenuRequested = pyqtSignal(object, QPoint) 

    def createEditor(self, parent, option, index): 
     editor = QLineEdit(parent) 
     editor.setContextMenuPolicy(Qt.CustomContextMenu) 
     editor.customContextMenuRequested.connect(
      lambda pos: self.contextMenuRequested.emit(editor, pos)) 
     return editor 
+0

ありがとうございました。その "1a1"は単なる例です。 MyDelegate(QStyledItemDelegate)のcreateEditor()はQLineEditエディタを作成しますが、私はそれをどのように使用するのか分かりません。私のユースケースは次のようになります:各セルには文字列(英語のテキストの段落または他の言語のテキスト)が含まれています。ユーザは、セルの内容を視覚的に調べ、余分なテキストを挿入する場所を決定した後、その場所にカーソルを置き、押しボタンを押す。私はその間にQTableViewのindexWidgetを見つけましたが、それを使用できるかどうかは分かりません。 – mike

+0

@mike。別のボタンを使用してテキストを挿入するのは非常に難しいでしょう。コンテキストメニューはずっと簡単になります。私の更新された答えを見てください。 – ekhumoro

+0

ありがとうございました。あなたの提案を使って試してみましょう。大きな助け、私はそれを感謝します。 – mike

1

qDebugの闘争と用途の多くは最終的に解決策を見つけるために管理私の後。私はそれがさらに改善できると確信しています。しかし、私はPyQtについてあまり知らない。このアイデアは、エディタが閉じられる前にMyDelegate(QStyledItemDelegate)にカーソル位置をキャッシュすることです。私は、同じ問題に遭遇した人にとって、それが役に立つことを願っています。

class MyDelegate(QStyledItemDelegate): 
    ... 
    def createEditor(self, parent, option, index): 
     self.cursorpos = -1 # unset flag 
     editor = QLineEdit(parent) 
     self.connect(editor, SIGNAL("editingFinished()"), 
         self.commitAndCloseEditor) 
     return editor 

    def commitAndCloseEditor(self): 
     editor = self.sender() 
     self.cursorpos = editor.cursorPosition() 
     if isinstance(editor, (QTextEdit, QLineEdit)): 
      self.emit(SIGNAL("commitData(QWidget*)"), editor) 
      self.emit(SIGNAL("closeEditor(QWidget*)"), editor) 

全体が以下に示されている。

# coding: utf-8 

import sys 
from PyQt4 import QtGui, QtCore 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

MY_ARRAY = [['00', '01', '02'], 
      ['10', '11', '12'], 
      ['20', '21', '22']] 


class MyWindow(QTableView): 
    def __init__(self, *args): 
     super(MyWindow, self).__init__() 

     self.tablemodel = MyTableModel(MY_ARRAY) 

     self.tableview = QTableView() 

     self.tableview.setModel(self.tablemodel) 

     # self.tableview.setItemDelegate(MyDelegate(self)) 

     self.delegate = MyDelegate(self) 
     self.tableview.setItemDelegate(self.delegate) 

     self.layout = QVBoxLayout(self) 
     self.layout.addWidget(self.tableview) 

     self.button1 = QPushButton("Test") 

     self.button1.released.connect(self.test) 

     self.layout.addWidget(self.button1) 
     self.setLayout(self.layout) 

    def test(self): 

     index = self.tableview.currentIndex() 
     item = self.tablemodel.data(index, Qt.DisplayRole) 

     qDebug("item %s " % item) 

     qDebug(" <test><MyDelegateMyDelegate> self.delegate.cursorpos: %s " % self.delegate.cursorpos) 

     cursorpos = self.delegate.cursorpos 
     qDebug(" <test> cursor pos %s " % cursorpos) 
     if cursorpos > -1: 
      index.model().setData(index, item[:cursorpos] + ' foo ' + item[cursorpos:]) 
      self.tablemodel.layoutChanged.emit() 
      self.delegate.cursorpos = -1 


class MyTableModel(QAbstractTableModel): 
    def __init__(self, datain, parent=None, *args): 
     super(MyTableModel, self).__init__(parent, *args) 

     self.arraydata = datain 

    def rowCount(self, parent): 
     return len(self.arraydata) 

    def columnCount(self, parent): 
     return len(self.arraydata[0]) 

    def data(self, index, role): 
     if not index.isValid(): 
      return None 

     elif not (role == Qt.DisplayRole or role == Qt.EditRole): 
      return None 
     return (self.arraydata[index.row()][index.column()]) 

    def setData(self, index, value, role=Qt.EditRole): 
     self.arraydata[index.row()][index.column()] = value 
     return True 

    def flags(self, index): 
     return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable 


class MyDelegate(QStyledItemDelegate): 

    def __init__(self, parent=None): 
     super(MyDelegate, self).__init__(parent) 
     self.cursorpos = -1 # unset flag 

    def createEditor(self, parent, option, index): 
     self.cursorpos = -1 # unset flag 
     editor = QLineEdit(parent) 
     self.connect(editor, SIGNAL("editingFinished()"), 
         self.commitAndCloseEditor) 
     return editor 

    def commitAndCloseEditor(self): 
     editor = self.sender() 
     self.cursorpos = editor.cursorPosition() 
     if isinstance(editor, (QTextEdit, QLineEdit)): 
      self.emit(SIGNAL("commitData(QWidget*)"), editor) 
      self.emit(SIGNAL("closeEditor(QWidget*)"), editor) 

    def setEditorData(self, editor, index): 
     text = index.model().data(index, Qt.DisplayRole) 

     editor.setText(text) 


    def setModelData(self, editor, model, index): 
     model.setData(index, editor.text()) 

def main(): 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_()) 

if __name__ == "__main__": 
    main() 
関連する問題