2014-02-03 4 views
1

Я хочу настроить внешний вид моего QTableView. Поэтому я решил отключить линии сетки и сам сделать картину. Я подклассифицировал QStyledItemDelegate и повторно реализовал свой метод рисования. Все работает отлично, пока я не выберу несколько ячеек в своем столе. Выбор как-то испортил картину ...QTableView: выбранная ячейка беспорядочна покраска

В конце я предоставил небольшое демо-приложение.

Если вы запустите приложение, просто нажмите на ячейку с именем «Ночь», и вы увидите, что я имею в виду. Как я могу это изменить?

Я думал о вызове повторной краской после выбора пользователем ячейки, но это не сработало.

Я был бы очень признателен, если бы кто-то помог мне с этим. Большое спасибо!

main.py

from PyQt4 import QtCore 
from PyQt4 import QtGui 

import sys 

from productiontable import productionTableModel 
from productiontable import productionTableBorder 

if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 

    tableview = QtGui.QTableView() 
    model = productionTableModel([["Prod. 1"], ["Prod. 2"], ["Prod. 3"], ["Prod. 4"], ["Prod. 5"]]) 

    tableview.setModel(model) 

    tableview.resizeColumnsToContents() 
    tableview.verticalHeader().setVisible(False) 
    tableview.horizontalHeader().setVisible(False) 
    tableview.setFrameStyle(QtGui.QFrame.NoFrame) 
    tableview.setShowGrid(False) 
    tableview.setFocusPolicy(QtCore.Qt.NoFocus) #remove dotted line, when cell has focus 
    tableview.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 

    d = productionTableBorder() 
    tableview.setItemDelegate(d) 

    tableview.resize(100, 300) 
    tableview.show() 

    sys.exit(app.exec_()) 

productiontable.py

from PyQt4 import QtCore 
from PyQt4 import QtGui 

class productionTableBorder(QtGui.QStyledItemDelegate): 
    def __init__(self, parent = None): 
     QtGui.QStyledItemDelegate.__init__(self, parent) 

    def paint(self, painter, option, index): 
     QtGui.QStyledItemDelegate.paint(self, painter, option, index) 
     if index.row()%2 == 0: 
      painter.save() 
      painter.setPen(QtGui.QPen(QtCore.Qt.white, 4)) 

      #draw a white line from start to end 
      start = QtCore.QPoint(option.rect.x(), option.rect.y()) 
      end = QtCore.QPoint(option.rect.x() + option.rect.width(), option.rect.y()) 
      painter.drawLine(start, end) 

      painter.restore() 

class productionTableModel(QtCore.QAbstractTableModel): 
    def __init__(self, lst = [[]], parent = None): 
     QtCore.QAbstractTableModel.__init__(self, parent) 
     self.__lst = lst 

    def rowCount(self, parent = None): 
     return len(self.__lst) * 2 

    def columnCount(self, parent = None): 
     return 2 

    def data(self, index, role): 
     col = index.column() 
     row = index.row() 
     if role == QtCore.Qt.DisplayRole: 
      if col == 0: 
       if row%2 == 0: 
        return self.__lst[row/2][col] 
      if col == 1: 
       if row%2 == 0: 
        return "Day" 
       else: 
        return "Night" 

     if role == QtCore.Qt.BackgroundRole: 
      return QtGui.QColor(188, 250, 213) 

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

ответ

0

Хорошо, я получил его.

Чтобы нарисовать свои собственные линии сетки, вам необходимо указать подкласс QTableView, подкласс QStyledItemDelegate не работает! Если вы подклассифицируете QStyledItemDelegate и переопределите его метод paint(), вам также необходимо перерасчитать размер ячейки (из-за линий сетки).

Это лучше подходит для подкласса QTableView и для рисования линий сетки в paintEvent.

Вот мое решение (вдохновленный this резьбой):

main.py

from PyQt4 import QtCore 
from PyQt4 import QtGui 

import sys 

from productiontable import productionTableModel 
from productiontable import customTable 

if __name__ == "__main__": 

    app = QtGui.QApplication(sys.argv) 

    tableview = customTable() 
    model = productionTableModel([["Prod. 1"], ["Prod. 2"], ["Prod. 3"], ["Prod. 4"], ["Prod. 5"]]) 

    tableview.setModel(model) 

    tableview.resizeColumnsToContents() 
    tableview.verticalHeader().setVisible(False) 
    tableview.horizontalHeader().setVisible(False) 
    tableview.setFrameStyle(QtGui.QFrame.NoFrame) 
    tableview.setShowGrid(False) 
    tableview.setFocusPolicy(QtCore.Qt.NoFocus) #remove dotted line, when cell has focus 
    tableview.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 

    tableview.resize(100, 300) 
    tableview.show() 

    sys.exit(app.exec_()) 

productiontable.py

from PyQt4 import QtCore 
from PyQt4 import QtGui 

class customTable(QtGui.QTableView): 
    def __init__(self, parent = None): 
     QtGui.QTableView.__init__(self, parent) 


    def paintEvent(self, event): 
     super(customTable, self).paintEvent(event) 

     #set the pen 
     pen = QtGui.QPen(QtCore.Qt.white, 4) 

     # Create the painter 
     painter = QtGui.QPainter(self.viewport()) 

     # Shortcuts to vertical and horizontal headers 
     vh = self.verticalHeader() 
     hh = self.horizontalHeader() 

     # Get the first and last rows that are visible in the view and if the 
     # last visiable row returns -1 set it to the row count 
     firstVisualRow = max([vh.visualIndexAt(0), 0]) 
     lastVisualRow = vh.visualIndexAt(vh.viewport().height()) 
     if lastVisualRow == -1: 
      lastVisualRow = self.model().rowCount(self.rootIndex()) - 1 

     # Get the first and last columns that are visible in the view and if 
     # if the last visible column is -1 set it to the column count. 
     firstVisualColumn = max([hh.visualIndexAt(0), 0]) 
     lastVisualColumn = hh.visualIndexAt(hh.viewport().width()) 
     if lastVisualColumn == -1: 
      lastVisualColumn = hh.count() - 1 

     # Iterate through each row and column drawing only the 
     # bottom and left side lines for each cell. Skipping rows and columns 
     # that are hidden 
     for vrow in xrange(firstVisualRow, lastVisualRow + 1, 2): 
      row = vh.logicalIndex(vrow) 
      FirstRow = (vrow == 0) 
      if vh.isSectionHidden(row): 
       continue 
      # Get top left Y coordinate and row height 
      rowY = self.rowViewportPosition(row) 
      rowh = self.rowHeight(row) 
      for vcol in range(firstVisualColumn, lastVisualColumn + 1): 
       col = hh.logicalIndex(vcol) 
       FirstColumn = (vcol == 0) 
       if hh.isSectionHidden(col): 
        continue 
       # Get top left X coordinate and column width 
       colX = self.columnViewportPosition(col) 
       colw = self.columnWidth(col) 

       # Get the model index 
       index = self.model().createIndex(row, col) 

       # Specify top, bottom, left and right of the cell 
       top = rowY 
       bottom = rowY 
       left = colX 
       right = colX + colw 

       # Save the painter and set the pen 
       painter.save() 
       painter.setPen(pen) 

       # Draw Horizontal Lines 
       painter.drawLine(left, bottom, right, bottom) 

       # Restore painter 
       painter.restore() 


class productionTableModel(QtCore.QAbstractTableModel): 
    def __init__(self, lst = [[]], parent = None): 
     QtCore.QAbstractTableModel.__init__(self, parent) 
     self.__lst = lst 

    def rowCount(self, parent = None): 
     return len(self.__lst) * 2 

    def columnCount(self, parent = None): 
     return 2 

    def data(self, index, role): 
     col = index.column() 
     row = index.row() 
     if role == QtCore.Qt.DisplayRole: 
      if col == 0: 
       if row%2 == 0: 
        return self.__lst[row/2][col] 
      if col == 1: 
       if row%2 == 0: 
        return "Day" 
       else: 
        return "Night" 

     if role == QtCore.Qt.BackgroundRole: 
      return QtGui.QColor(188, 250, 213) 

    def flags(self, index): 
     return (QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsSelectable)  
Смежные вопросы