[PyQt4] -- Visual display of a register



  • Hi there,
    I use a micro-controller (uc) to control an asic (Application Specific Integrated Circuit). To do so, I wrote a PyQt4 application with a lot of qlineedit and qdoublespinbox and a few buttons. The buttons send to the uc the relevant information according to the content of lines and double spinboxes. The uc translates data to the asic protocol and talk to him. The communication is made through serial com using pyserial...

    Most of my registers are less than 8 bits long and the user enter the values with doublespinboxes. Though, I have a bunch of registers to control that are 32 and 192 bits long. I found a turnaround to easily enter the values but I would like to give the user a way to check and type values in an easier way.

    So far I use a QLineEdit with the following syntax for a 32 bits register:
    0:23,24,25:31=0,1,0
    which means from 0 to 23 the value is 0 then 1 for 24th bit and then 0 for 25 to 31
    of course, I wrote a small parser to convert the QLineEdit to serial bits that the uc understand.
    My idea is represented by the figure below :

    !http://olivierlemaire.files.wordpress.com/2012/01/visual_long_register.png(Visual Display of a long register)!

    I would like, according to the above example, that all squares are red (Low state) except for 24 that should be green (Active state) !! Of course, that would be great if I could also toggle the states by clicking on the cells of this widget...

    My issue is that I just don't know how to do that... I kinda see a turnaround using checkboxes but I don't think I can put numbers in. I tried with a qtablewidget, not so successful ! maybe with toggle button and changing the background color according to its state... Really, I don't know.

    Thanks in advance for your help.

    Have a good one,

    Olivier



  • Hi Olivier,

    I don't know if you managed to solve this already but if not I think the following example should do what you need. I wrote it for a project of my own with similar requirements and uses a custom QWidget with mouse events rather than a table or checkboxes. You can use the value() and setValue() functions to get and set the value programatically or click on the individual bits to toggle there values. Hope you find it useful, here goes:

    @
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *

    class BitWidget(QWidget):
    def init(self, num_of_bits, parent=None):
    QWidget.init(self, parent)

        self.num_of_bits=num_of_bits
        self.data=[0 for b in range(num_of_bits)]
        self.data[1]=1
        self.box_size=30
        self.font=QFont('Serif', 12, QFont.Light)
    
    def setBoxSize(self, size): self.box_size=size
    
    def setFont(self, font): self.font=font
    
    def sizeHint(self): return QSize(self.num_of_bits*self.box_size, self.box_size)
    
    def paintEvent(self, event):
        painter=QPainter()
        painter.begin(self)
    
        painter.setFont(self.font)
    
        size=self.size()
        width=size.width()-1
        height=size.height()-1
    
        for i,v in enumerate(self.data):
            painter.fillRect(i*self.box_size, 0, self.box_size, self.box_size, Qt.green if self.data[i] else Qt.red)
            painter.drawLine(i*self.box_size, 0, i*self.box_size, height)
    
            valueString="%d" % i
            fontWidth=painter.fontMetrics().width(valueString)
            fontHeight=painter.fontMetrics().height()
    
            painter.drawText((i*self.box_size)-(fontWidth/2)+(self.box_size/2),
                             (self.box_size/2)+(fontHeight/2), 
                             valueString)
    
        painter.setPen(Qt.black)
        painter.drawRect(0, 0, width, height)
    
        painter.end() 
    
    def mousePressEvent(self, event):
        b=event.pos().x()//self.box_size
        self.data[b]^=1
        self.repaint()
        event.accept()
    
    def value(self):
        value=0
        mask=1
        for i,v in enumerate(self.data):
            if v: value|=mask
            mask<<=1
        return value
    
    def setValue(self, value):
        mask=1
        for i,v in enumerate(self.data):
            self.data[i]=(value&mask)>>i
            mask<<=1
        self.repaint()
    

    class Widget(QWidget):
    def init(self, parent=None):
    QWidget.init(self, parent)

        QVBoxLayout(self)
        self.bitWidget=BitWidget(16, self)
        self.layout().addWidget(self.bitWidget)
        
        valueButton=QPushButton("Value", self)
        valueButton.clicked.connect(self.printValue)
        self.layout().addWidget(valueButton)
    
        self.valueSpinBox=QSpinBox(self)
        self.valueSpinBox.setRange(0, 2**16)
        self.layout().addWidget(self.valueSpinBox)
    
        setValueButton=QPushButton("Set Value", self)
        setValueButton.clicked.connect(self.setValue)
        self.layout().addWidget(setValueButton)
    
    def printValue(self): print "Value:", self.bitWidget.value()
    
    def setValue(self): self.bitWidget.setValue(self.valueSpinBox.value())
    

    if name=="main":
    from sys import argv, exit
    a=QApplication(argv)
    w=Widget()
    w.show()
    exit(a.exec_())
    @

    It should look something like this:

    !http://s15.postimage.org/r3nwtauor/bitwidget.png(BitWidget Screenshot)!

    Feel free to ask any questions, hope it helps.

    Rob


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.