0

I have implemented a table with drag and drop between the cells. This is a pared-down version of the application. I would like to use rounded rect and other drawing features in some of the cells. As can be seen (when run), a shape only shows up in a small window in the upper left corner of the main window.

#! /usr/bin/env python3.6
# -*- coding: utf-8 -*-

import sys

from PyQt5 import QtCore, QtGui, QtWidgets #Just tested it for PyQt4 since I don't have PySide installed...

#
class PaintTable(QtWidgets.QTableWidget):
    def __init__(self, parent):
        QtWidgets.QTableWidget.__init__(self, parent)
        self.center = QtCore.QPoint(-10,-10)
        #self.setAcceptDrops(True)               ## do not pickup drag/drop if assoc with tableWidget
        #self.table.setDragEnabled(True)   ## needs to refer to tablewWidget


    def paintEvent(self, event):

        painter = QtGui.QPainter(self.viewport())
        ##painter.resize(100,200)       
        sizex = self.viewport().width()
        sizey = self.viewport().height()
        #See: http://stackoverflow.com/questions/12226930/overriding-qpaintevents-in-pyqt
        print("Viewport %s # %s # %i / %i"% (self, self.center, sizex, sizey))
        h = int(self.center.y()/50)*50+40
        w = int(self.center.x()/50)*50+25
        a = w-25
        b = h-25
        c = 50
        d = 20
        painter.setPen(QtGui.QPen(QtCore.Qt.green, 5))
        painter.drawRoundedRect((a),(b),(c),(d),10,10)
        line = QtCore.QLineF(w+10.0, h+80.0, w+90.0, h+20.0)
        painter.drawLine(line)
        QtWidgets.QTableWidget.paintEvent(self,event)

    def mousePressEvent(self, event):
        if event.buttons() == QtCore.Qt.RightButton:
            self.center = QtCore.QPoint(event.pos().x(),  event.pos().y())
            print ("at repaint %s" % self.center)
            self.viewport().repaint()

        elif event.buttons() == QtCore.Qt.LeftButton:
            print("In left")
            QtWidgets.QTableWidget.mousePressEvent(self,event)


    def dragMoveEvent(self, e):  # do I need this?
        e.accept(QtCore.QRect(0,0,3000,1800))  ##QRect for moves
        # do not print("in move") from here; will get many

##  locations appear to be related to the upper left corner of the Main Window, not the table

    def dragEnterEvent(self, e):  ## redefined event
      ##
      self.DISPLAY_LOCK = 1  
## 
      was = e.pos()
      print("At top enter %s" % self)
      if (was.x() > 0 and was.x() < self.Wtable) :        
        e.accept()
        wxy = QtCore.QPoint()
        wxy.setX(was.x())
        wxy.setY(was.y()-self.TabYoff)
        print ("newYpos -> %s" % wxy)
##           

    def dropEvent(self, e):  ## redefined event
        print ('drop %s' % self.itemt[0])

#####

class MainWindow(QtWidgets.QMainWindow, QtWidgets.QTableWidget): #, PaintTable ):
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)


# General grid
        self.resize(2400, 1400)

### underlying structure to allow drag and drag to function on the table
        self.cent = QtWidgets.QWidget(PaintTable(self)) ## self      
        self.table = QtWidgets.QTableWidget(self.cent)
        self.setCentralWidget(self.cent)
        self.table.setGeometry(QtCore.QRect(0, 500, 2400, 1400))



        self.setAcceptDrops(True)               ## do not pickup drag/drop if assoc with tableWidget
        self.table.setDragEnabled(True)         ## needs to refer to table

        print("self: %s " % self)
        self.nbrow, self.nbcol = 9, 9
        self.table.setRowCount(self.nbrow)
        self.table.setColumnCount(self.nbcol)
        for row in range(0, self.nbrow):
            self.table.setRowHeight(row, 50)

            for col in range(0, self.nbcol):
                self.table.setColumnWidth(col, 50)

# Each cell contains one single QTableWidgetItem
        for row in range(0, self.nbrow):
            for col in range(0, self.nbcol):
                item = QtWidgets.QTableWidgetItem("#")
                item.setTextAlignment(
                    QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
                )

                self.table.setItem(row, col, item)

# Header formatting
        font = QtGui.QFont()
        font.setFamily(u"DejaVu Sans")
        font.setPointSize(12)
        self.table.horizontalHeader().setFont(font)
        self.table.verticalHeader().setFont(font)

# Font used
        font = QtGui.QFont()
        font.setFamily(u"DejaVu Sans")
        font.setPointSize(10)
        self.table.setFont(font)

# Global Size (can change size here)
        #self.resize(60*9, 60*9 + 20)

# Layout of the underlying palette
        layout = QtWidgets.QGridLayout()
        layout.addWidget(self.table, 0, 0)
        self.setLayout(layout)

# Set the focus in the first cell
        self.table.setFocus()
        self.table.setCurrentCell(0, 0)

    def dragMoveEvent(self, e):  # do I need this?
        e.accept(QtCore.QRect(0,0,2400,1400))  ##QRect for moves
        # do not print("in move") from here; will get many

##  locations appear to be related to the upper left corner of the Main Window, not the table

    def dragEnterEvent(self, e):  ## redefined event
      ##
      self.DISPLAY_LOCK = 1  
## 
      was = e.pos()
      print("At top enter %s" % self)
      ##if (was.x() > 0 and was.x() < self.Wtable) :        
      e.accept()
      ## wxy = QtCore.QPoint()
      ## wxy.setX(was.x())
      ## wxy.setY(was.y()-self.TabYoff)
      print ("newXYpos -> %s %s" % (was.x(),was.y()))
##           

    def dropEvent(self, e):  ## redefined event
        x="go"
        self.table.setItem(3, 3, QtWidgets.QTableWidgetItem("K"))      
        print ('drop %s' % x)        



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    fen = MainWindow()
    fen.show()
    sys.exit(app.exec_())        

I have a second example where I have the shapes where desired, but this version does not support drag and drop.

#! /usr/bin/env python3.6
# -*- coding: utf-8 -*-

import sys

from PyQt5 import QtCore, QtGui, QtWidgets #Just tested it for PyQt4 since I don't have PySide installed...
import sys    
#
#x#class PaintTable(object):
class PaintTable(QtWidgets.QTableWidget):
    def __init__(self, parent):
        QtWidgets.QTableWidget.__init__(self, parent)
        #x#self.table=QtWidgets.QTableWidget()
        print("Create table")
        self.center = QtCore.QPoint(-10,-10)
        ##self.setAcceptDrops(True)         ## does not pickup drag/drop
        ##self.table.setDragEnabled(True)   


    def paintEvent(self, event):
        painter = QtGui.QPainter(self.viewport()) #See: http://stackoverflow.com/questions/12226930/overriding-qpainztevents-in-pyqt
        print("Viewport %s"% self)
        h = int(self.center.y()/50)*50+40
        w = int(self.center.x()/50)*50+25
        a = w-25
        b = h-25
        c = 50
        d = 20
        painter.setPen(QtGui.QPen(QtCore.Qt.green, 5))
        painter.drawRoundedRect((a),(b),(c),(d),10,10)
        line = QtCore.QLineF(w+10.0, h+80.0, w+90.0, h+20.0)
        painter.drawLine(line)
        QtWidgets.QTableWidget.paintEvent(self,event)

    def mousePressEvent(self, event):
        if event.buttons() == QtCore.Qt.RightButton:
            self.center = QtCore.QPoint(event.pos().x(),  event.pos().y())
            print ("at repaint %s" % self.center)
            self.viewport().repaint()

        elif event.buttons() == QtCore.Qt.LeftButton:
            print("In left")
            QtWidgets.QTableWidget.mousePressEvent(self,event)


    def dragMoveEvent(self, e):  # do I need this?
        e.accept(QtCore.QRect(0,0,3000,1800))  ##QRect for moves
        # do not print("in move") from here; will get many

##  locations appear to be related to the upper left corner of the Main Window, not the table

    def dragEnterEvent(self, e):  ## redefined event
      ##
      self.DISPLAY_LOCK = 1  
## 
      was = e.pos()
      print("At top enter %s" % self)
      if (was.x() > 0 and was.x() < self.Wtable) :        
        e.accept()
        wxy = QtCore.QPoint()
        wxy.setX(was.x())
        wxy.setY(was.y()-self.TabYoff)
        print ("newYpos -> %s" % wxy)
##           

    def dropEvent(self, e):  ## redefined event
        print ('drop %s' % self.itemt[0])

#####
#x#class MainWindow(QtWidgets.QTableWidget):
class MainWindow(PaintTable):  ## get graphics on MainWindow, also
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)


# General grid
        #x#self.xxx = PaintTable(self)
        #x#self.table = self.xxx.table
        self.table = PaintTable(self)

        self.setAcceptDrops(True)               ## do not pickup drag/drop if assoc with tableWidget
        self.table.setDragEnabled(True)         ## needs to refer to table

        print("self: %s " % self)
        self.nbrow, self.nbcol = 9, 9
        self.table.setRowCount(self.nbrow)
        self.table.setColumnCount(self.nbcol)
        for row in range(0, self.nbrow):
            self.table.setRowHeight(row, 50)

            for col in range(0, self.nbcol):
                self.table.setColumnWidth(col, 50)

# Each cell contains one single QTableWidgetItem
        for row in range(0, self.nbrow):
            for col in range(0, self.nbcol):
                item = QtWidgets.QTableWidgetItem()
                item.setTextAlignment(
                    QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter
                )

                self.table.setItem(row, col, item)

# Header formatting
        font = QtGui.QFont()
        font.setFamily(u"DejaVu Sans")
        font.setPointSize(12)
        self.table.horizontalHeader().setFont(font)
        self.table.verticalHeader().setFont(font)

# Font used
        font = QtGui.QFont()
        font.setFamily(u"DejaVu Sans")
        font.setPointSize(20)
        self.table.setFont(font)

# Global Size
        self.resize(60*9, 60*9 + 20)

# Layout of the table
        layout = QtWidgets.QGridLayout()
        layout.addWidget(self.table, 0, 0)
        self.setLayout(layout)

# Set the focus in the first cell
        self.table.setFocus()
        self.table.setCurrentCell(0, 0)

##### drag routines
    def dragMoveEvent(self, e):  # do I need this?
        e.accept(QtCore.QRect(0,0,3000,1800))  ##QRect for moves
        # do not print("in move") from here; will get many

##  locations appear to be related to the upper left corner of the Main Window, not the table

    def dragEnterEvent(self, e):  ## redefined event
      ##
      self.DISPLAY_LOCK = 1  
## 
      was = e.pos()
      print("At top enter %s" % self)
      if (was.x() > 0 and was.x() < self.Wtable) :        
        e.accept()
        wxy = QtCore.QPoint()
        wxy.setX(was.x())
        wxy.setY(was.y()-self.TabYoff)
        print ("newYpos -> %s" % wxy)
##           

    def dropEvent(self, e):  ## redefined event
        print ('drop %s' % self.itemt[0])        



if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    fen = MainWindow()
    fen.show()
    sys.exit(app.exec_())        

What structure is required to get both the overlaying of the shapes and the drag and drop capability?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Could you explain yourself better? what a difference your first example has. If it is something graphic you could put some graphic scheme. read [ask] – eyllanesc Mar 15 '18 at 18:48
  • The differences between the code samples are 1) the manner that PaintTable is called from MainWindow, and 2) in the first code sample the structure of table using QtWidget, QtTableWidget and setCentralWidget implements a functional drag and drop. What I want to know is the necessary means to interface MainWindow and PaintTable to be able to both draw shapes (as occurs in the 2nd code) and allow drag and drop (as works in the 1st code)? Hopefully clearer? – Steve95959 Mar 16 '18 at 03:29
  • Where do you want to drag and where? What do you want to drag? I have tried both codes and in the second you can drag but not drop anywhere, in the first you can also drag but not drop, it could be more accurate and descriptive in what you want. In addition to reducing and eliminating unnecessary code. – eyllanesc Mar 16 '18 at 03:32
  • We are seeing different results. When I execute the first code the drag works (any cell to any other cell). It is acknowledged by seeing the "K" at cell 4,4. In the second code the drag does not occur; when the cursor is being moved one sees the red circle with a bar through it. Note, also, the second code has the two shapes over the table whereas the first code does not. If it helps, there is a small amount of test code I can eliminate; I was testing some alternatives. – Steve95959 Mar 16 '18 at 05:20
  • hahaha, so weird way to show that the drag works, my screen is small so I can not see that item 3, 3 changed text, the most natural thing would be if I drag the item i, j to p, q copy the text, and to prove that in your code did not work so I concluded that. – eyllanesc Mar 16 '18 at 05:26
  • In the second example I do not observe the red circle or the bar, I see an oval rectangle with a line, both green. Do you want the DropEvent of the PaintTable to be called? What is your particular goal? I do not understand it so far. – eyllanesc Mar 16 '18 at 05:31
  • Sorry, I did not see your last comment. The red circle with a bar through it should appear as you start to drag from one cell to another, showing that dragging is not finding the 'override' routines for drag enter, move, drop; note that this does not happen for the first case. – Steve95959 Mar 16 '18 at 21:48

0 Answers0