Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Add an always visible spinbox colum in QtableView
Forum Updated to NodeBB v4.3 + New Features

Add an always visible spinbox colum in QtableView

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 1 Posters 601 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    nbusser
    wrote on last edited by
    #1

    Re: How to add a spinbox column and combo box column in QTableWidget or QTableView?

    Hello everyone !

    I'm bumping this topic because I need to perform the same thing as my fellow. It's kind of hard to find such example on the web, so I need your help.

    So, I need to integrate a spinbox in a TableView, and to have this spinbox always visible and "clickable".

    I have few questions:

    • I understood that I have to use in some way a QStyleOptionsSpinBox, but I don't have any idea of how to use its specific attributes like buttonSymbols. In fact, I don't really have the idea of how to use this option item in my situation.
    • Related to the first point, how can I draw the different elements of the spinbox like the buttons ?
    • I want to retrieve the index of the spin box. However, it's located in my QAbstractTableModel. I don't have any idea of to properly get this information from this delegate.

    Note that I'm using python Pyside2 binding, which doesn't change anything related to the function signatures and usage..

    class SpinBoxDelegate(QtWidgets.QStyledItemDelegate):
        def __init__(self, parent):
            super().__init__(parent)
    
        def createEditor(self, parent, option, index):
            return QtWidgets.QSpinBox(parent)
    
        def setEditorData(self, editor, index):
            editor.setValue(int(index.data()))
    
        def updateEditorGeometry(self, editor, option, index):
            editor.setGeometry(option.rect)
    
        def paint(self, painter, option, index):
            painter.save()
    
            # How to use all the specific attributes of this option ?
            option_spinbox = QtWidgets.QStyleOptionSpinBox()
            option_spinbox.rect = option.rect
            option_spinbox.state = option.state
    
            import pdb
            pdb.set_trace()
    
            # Here, I want to retrieve the spin box index, which is stored in my model...
            painter.drawText(option_spinbox.rect, "Test")
    
            if option_spinbox.state & QtWidgets.QStyle.State_Selected:
                painter.setPen(QtGui.QPen(QtGui.QColor(255, 0, 0)))
                painter.drawRect(option_spinbox.rect)
                painter.restore()
                return
    
            painter.setPen(QtGui.QPen(QtGui.QColor(0, 255, 0)))
            painter.drawRect(option_spinbox.rect)
    
            painter.restore()
            return
    

    For the moment, here is the result of

    1 Reply Last reply
    0
    • N Offline
      N Offline
      nbusser
      wrote on last edited by
      #2

      I finally achieved to a good little result:

      demo

      I have some questions remaining:
      For the moment, the editor shows when double clicking anywhere on the column 2.
      I would like to show the editor only if the user clicked on the number on the center, and not on the arrows on the side.

      For that, I would need to retrieve the mouse position when entering the function createEditor, but I don't know how to do.
      I guess that I can re-implement in some way the function that makes the editor popping...

      Also, is my code ugly in term of conception ? What can I improve to make it prettier then ?

      from PySide2 import QtCore, QtWidgets, QtGui
      from model_ui.segment_model import Columns
      
      class SpinBoxDelegate(QtWidgets.QStyledItemDelegate):
          """This delegates allow a custom display of a spinbox into a tableview"""
          def __init__(self, parent):
              super().__init__(parent)
      
          def is_segment_analyzed(self, index):
              """Checks from a given SegmentModel index, if the corresponding
              segment have been analyzed
              """
      
              analyzed_index = index.siblingAtColumn(Columns.analyzing.value)
              return not index.model().get_attribute_from_index(analyzed_index)
      
          def createEditor(self, parent, option, index):
              """Returns a new SpinBox widget if the segment have been analyzed"""
              if self.is_segment_analyzed(index):
                  return QtWidgets.QSpinBox(parent)
              return None
      
          def setEditorData(self, editor, index):
              """Handles the way editor store new data"""
              editor.setValue(int(index.data()))
      
          def editorEvent(self, event, model, option, index):
              """This function is used to handle the interactions with handmade
              buttons.
              """
      
              # If the event is a click event
              if event.type() == QtCore.QEvent.MouseButtonRelease:
                  # Retrieves the button positions
                  left_arrow_button, right_arrow_button = self.get_left_right_arrow_buttons(option)
      
                  # Retrieves the combo index value from the model index
                  current_combo_value = int(index.data())
      
                  value_changed = False
                  # If left button was clicked, we decrease combo index
                  if left_arrow_button.contains(event.pos()):
                      if current_combo_value > 0:
                          value_changed = True
                          current_combo_value = current_combo_value - 1
      
                  # If left button was clicked, we increase combo index
                  if right_arrow_button.contains(event.pos()):
                      # TODO: Globally handle right combo limit (for all the project)
                      value_changed = True
                      current_combo_value = current_combo_value + 1
      
                  # Report the changes to the model
                  if value_changed:
                      model.setData(index, current_combo_value)
      
          def updateEditorGeometry(self, editor, option, index):
              editor.setGeometry(option.rect)
      
          def get_left_arrow_button(self, option):
              """Creates the left arrow button, depending on the option rect area"""
              arrow_buttons_size = option.rect.height()//1.5
              left_arrow_box = QtCore.QRect(
                  option.rect.left()+1,
                  option.rect.top()+(option.rect.height()//4.5),
                  arrow_buttons_size,
                  arrow_buttons_size)
              return left_arrow_box
      
          def paint_left_arrow_button(self, painter, option):
              """Creates the left arrow button et paints it"""
              left_arrow_box = self.get_left_arrow_button(option)
              painter.drawRect(left_arrow_box)
              painter.fillRect(left_arrow_box, QtGui.QColor(255, 255, 255))
              painter.drawText(left_arrow_box, QtCore.Qt.AlignCenter, "<")
      
          def get_right_arrow_button(self, option):
              """Creates the right arrow button, depending on the option rect area"""
              arrow_buttons_size = option.rect.height()//1.5
              right_arrow_box = QtCore.QRect(
                  option.rect.right()-arrow_buttons_size,
                  option.rect.top()+(option.rect.height()//4.5),
                  arrow_buttons_size,
                  arrow_buttons_size)
              return right_arrow_box
      
          def paint_right_arrow_button(self, painter, option):
              """Creates the right arrow button et paints it"""
              right_arrow_box = self.get_right_arrow_button(option)
              painter.drawRect(right_arrow_box)
              painter.fillRect(right_arrow_box, QtGui.QColor(255, 255, 255))
              painter.drawText(right_arrow_box, QtCore.Qt.AlignCenter, ">")
      
          def get_left_right_arrow_buttons(self, option):
              return self.get_left_arrow_button(option), self.get_right_arrow_button(option)
      
          def paint_left_right_arrow_buttons(self, painter, option):
              self.paint_left_arrow_button(painter, option)
              self.paint_right_arrow_button(painter, option)
      
          def paint(self, painter, option, index):
              painter.save()
      
              if not self.is_segment_analyzed(index):
                  painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
                  painter.drawRect(option.rect)
                  painter.restore()
                  return
      
              option_spinbox = QtWidgets.QStyleOptionSpinBox()
              option_spinbox.rect = option.rect
              option_spinbox.state = option.state
      
              # By default: white pen (eraser)
              painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
      
              # If the segment have been analyzed: we draw information
              # Else, we proint a blank cell
              if self.is_segment_analyzed(index):
                  painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0)))
      
                  painter.drawText(option_spinbox.rect, QtCore.Qt.AlignCenter,
                                   str(index.data()))
      
                  self.paint_left_right_arrow_buttons(painter, option_spinbox)
      
                  painter.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
      
                  # If the segment associated to the spinbox is selected: green line
                  if option_spinbox.state & QtWidgets.QStyle.State_Selected:
                      painter.setPen(QtGui.QPen(QtGui.QColor(0, 255, 0)))
      
              # Drawing boundaries
              painter.drawRect(option_spinbox.rect)
      
              painter.restore()
      
          def sizeHint(self, option, index):
              """Gives an hint about the minimal size of the element to the view"""
              number_of_digits_to_draw = len(str(index.data()))
              arrow_button_width = 25
      
              width = number_of_digits_to_draw * 10 + 2 * arrow_button_width
              height = 45
      
              return QtCore.QSize(width, height)
      
      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved