2016-06-29 22 views
2

私はPYQT5を使用しています。私はスプレッドシートに似たクイックデータ入力用に使うQtableViewウィジェットを持っています。一部の列は編集可能ですが、他の列(ラベルなど)は編集できません。 QItemDelegateをサブクラス化することで、これを簡単に達成しました。QtableView内の編集不可能なセルの上のタブ

私がしたいのは、編集可能なセルからタブをタップすると、編集不可能なセルをスキップして次の編集可能なセルに移動するときです。私はどこかで編集した後にキー押しイベントを調べ、次の列を決定する必要があると思います。代わりに、私が編集可能でないセルに着陸すると、直ちに次の編集可能なセルに移動する必要があります。私のコードは次のとおりです。

class Rates_sheet(QDialog, Ui_rates_sheet): 
    """Displays rates for the next x days for quick changes""" 

    #---------------------------------------------------------------------- 
    def __init__(self): 
     """Constructor""" 
     QDialog.__init__(self) 
     self.ui = Ui_rates_sheet() 
     self.ui.setupUi(self) 
     self.ui.num_days.setValue(45) 
     self.ui.get_avail.clicked.connect(self.make_rate_sheet) 
     self.ui.publish_avail.clicked.connect(self.publish_rates) 
     self.populate() 

    def populate(self): 
     self.rates_model = QSqlTableModel() 
     self.rates_model.setTable("rates_sheet") 
     self.rates_model.select() 
     self.rates_view = self.ui.rates_grid 
     self.rates_view.setModel(self.rates_model) 
     self.rates_view.resizeColumnsToContents() 
     self.rates_view.setSortingEnabled(True) 
     self.rates_view.setColumnHidden(0, True) 
     for x in range(7,12): 
      self.rates_view.setColumnHidden(x, True) 
     self.rates_view.horizontalHeader().moveSection(3,10) 
     self.rates_view.horizontalHeader().moveSection(3,12) 
     self.rates_view.horizontalHeader().moveSection(13,2) 
     self.rates_view.setItemDelegate(Tmodel(self)) 
     self.rates_model.setHeaderData(1, Qt.Horizontal, "Date") 
     self.rates_model.sort(1, Qt.AscendingOrder) 



    def make_rate_sheet(self): 
     pass 

    def publish_rates(self): 
     pass 


class Tmodel(QItemDelegate): 
    """Remplement rates_sheet table""" 

    def __init__(self, parent=None): 
     QItemDelegate.__init__(self) 


    def createEditor(self, parent, option, index): 
     if index.column() == 4: 
      spinbox = QSpinBox(parent) 
      spinbox.setRange(1,4) 
      return spinbox 
     elif index.column() in [5,6,11,12]: 
      spinbox = QSpinBox(parent) 
      spinbox.setRange(49,499) 
      return spinbox 

編集:私は、フラグの値を変更しますが、実行時エラーで終わるためにQSqlTableModelを再実装しようとしてい

class MySqlTableModel(QSqlTableModel): 
def __init__(self): 
    QSqlTableModel.__init__(self) 

def flags(self, index): 
    if index.isValid(): 
     if index.column() == 4: 
      flags ^= 1 
      return flags 

私が取得エラーは次のとおりです。

File "f:\Dropbox\pms\main-5.py", line 2658, in <module> 
    sys.exit(app.exec_()) 

builtins.TypeError: invalid result from MySqlTableModel.flags(), NoneType cannot be converted to PyQt5.QtCore.ItemFlags in this context 

今私はさらに混乱しています。

+1

私が思い出す限り、モデルの 'flags'メソッドを実装し、* ItemIsSelectable *オプションを取り除くことができます。 http://doc.qt.io/qt-5/qabstractitemmodel.html#flagsを参照してください。 – maxik

+0

私は本当に混乱しています。私は、アイテムが選択可能であったかどうかは、ビューの仕事であろうと考えていたでしょう。私はQSqlTableModelを再実装して動作させるのに苦労しています。もっとPYQTの詳細を教えてもらえますか? – Dkellygb

+0

Qtはそのような扱いが異なります。http://doc.qt.io/qt-5.6/model-view-programming.htmlを参照してください。 PyQtについて私はあなたのために間違った男です。しかし、これと多分ここでのいくつかの例を読んでhttp://doc.qt.io/qt-5.6/modelview.htmlはPythonに採用可能でなければなりません。力があなたと一緒にありますように。 – maxik

答えて

1

これを数日間にわたって発汗させた後の答えは、QsqlTableModelを正常に再実装できることです。私は答えにどのように到着したのですか?

まず、QsqlTableModelの代わりにQsqlQueryModelを再実装する必要があることを、C++用のQTフォーラムでネット上の推奨事項を見ました。しかし、setdata、data、rowcount、columncount、insertrows、deleterowsのメソッドを作成する必要があります。これは多くの仕事のようで、エラーになりやすいようでした。私はそれを働かせることができませんでした。

上記のすべてが無意味であり、多くの作業をしていたと思って、stackoverflowからコードスニペットを見つけました。誰かがQsqlQueryModelのdataChangedシグナルを使用しようとしていました。最後に、私が試みていることを正確に行う方法の例を見ました。したがって、コードを次のように更新しました。

class Rates_sheet(QDialog, Ui_rates_sheet): 
    """Displays rates for the next x days for quick changes""" 

    def __init__(self): 
     """Constructor""" 
     QDialog.__init__(self) 
     self.ui = Ui_rates_sheet() 
     self.ui.setupUi(self) 
     self.ui.num_days.setValue(45) 
     self.ui.get_avail.clicked.connect(self.make_rate_sheet) 
     self.ui.publish_avail.clicked.connect(self.publish_rates) 
     self.populate() 

    def populate(self): 
     self.rates_model = MySqlTableModel() 
     self.rates_model.setTable("rates_sheet") 
     self.rates_model.select() 
     self.rates_view = self.ui.rates_grid 
     self.rates_view.setModel(self.rates_model) 
     self.rates_view.resizeColumnsToContents() 
     self.rates_view.setSortingEnabled(True) 
     self.rates_view.setColumnHidden(0, True) 
     self.rates_view.setItemDelegate(Tmodel(self)) 
     self.rates_model.setHeaderData(1, Qt.Horizontal, "Date") 
     self.rates_model.sort(1, Qt.AscendingOrder) 

    def make_rate_sheet(self): 
     pass 

    def publish_rates(self): 
     pass 

class MySqlTableModel(QSqlTableModel): 
    """Overides QSqlTableModel to make columns not selectable""" 

    def __init__(self): 
     QSqlTableModel.__init__(self) 

    def setData(self, index, value, role=Qt.EditRole): 
     if role == Qt.EditRole: 
      value = value.strip() if type(value) == str else value 

     return super(MySqlTableModel, self).setData(index, value, role) 

    def flags(self, index): 
     flags = super(MySqlTableModel, self).flags(index) 

     if index.column() in (4, 5, 6, 11): 
      flags |= Qt.ItemIsEditable 
     else: 
      flags &= Qt.ItemIsSelectable 
     return flags 

これが解決策でした。私はまだテスト中ですが、まだ問題は見つかりませんでした。