3

I'm working on a touch screen app where gui space is very tight. I'd like to rotate a QLabel a bit so that it's either vertical, or offset at a diagonal a bit. Any suggestions? I couldn't find anything relevant on the QLabel interface.

Thanks so much!

Jubal
  • 8,357
  • 5
  • 29
  • 30

5 Answers5

5

QLabel does not do this. But you can easily create your own widget containing a bit of text:

class MyLabel(QtGui.QWidget):
    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.setPen(QtCore.Qt.black)
        painter.translate(20, 100)
        painter.rotate(-90)
        painter.drawText(0, 0, "hellos")
        painter.end()

Another option is to draw a QGraphicsView, you then have the liberty to map real widgets (i.e. a QLabel) through any coordinate transformation.

Ivo
  • 3,481
  • 1
  • 25
  • 29
  • Hi, thanks. Would you know how to do that with a QPushButton? See thread: http://stackoverflow.com/questions/7339685/how-to-rotate-a-qpushbutton Thanks. – neydroydrec Sep 07 '11 at 21:24
2

I used this post to make another solution that I think is maybe better. Here it is:

class VerticalLabel(QLabel):

    def __init__(self, *args):
        QLabel.__init__(self, *args)

    def paintEvent(self, event):
        QLabel.paintEvent(self, event)
        painter = QPainter (self)
        painter.translate(0, self.height()-1)
        painter.rotate(-90)
        self.setGeometry(self.x(), self.y(), self.height(), self.width())
        QLabel.render(self, painter)

    def minimumSizeHint(self):
        size = QLabel.minimumSizeHint(self)
        return QSize(size.height(), size.width())

    def sizeHint(self):
        size = QLabel.sizeHint(self)
        return QSize(size.height(), size.width())
Controlix
  • 437
  • 2
  • 11
2

Try this

class myStyle(QCommonStyle):

    def __init__(self, angl=0, point=QPoint(0, 0)):
        super(myStyle, self).__init__()
        self.angl = angl
        self.point = point

    def drawItemText(self, painter, rect, flags, pal, enabled, text, textRole):
        if not text:
            return
        savedPen = painter.pen()
        if textRole != QPalette.NoRole:
            painter.setPen(QPen(pal.brush(textRole), savedPen.widthF()))
        if not enabled:
            pen = painter.pen()
            painter.setPen(pen)
        painter.translate(self.point)
        painter.rotate(self.angl)
        painter.drawText(rect, flags, text)
        painter.setPen(savedPen)

and

label = QLabel()
label.setStyle(myStyle(-45, QPoint(0, 100)))
1

Answer from @Controlix is a generic implementation, however, I was getting a "recursive painting call" warning. I was able to address that by combining approaches from @Controlix and @Ivo. Here is my implementation:

from PyQt5.Qt import QLabel
from PyQt5 import QtGui


class VerticalLabel(QLabel):

    def __init__(self, *args):
        QLabel.__init__(self, *args)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.translate(0, self.height())
        painter.rotate(-90)
        painter.drawText(0, self.width()/2, self.text())
        painter.end()
0

I took all of the above posts, and tested each one. I believe this is the best combination of them all.

This centers the text horizontally and vertically, and sets size hints correctly.

enter image description here

from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5 import QtCore

class VerticalLabel(QtWidgets.QLabel):

    def __init__(self, *args):
        QtWidgets.QLabel.__init__(self, *args)

    def paintEvent(self, event):
        painter = QtGui.QPainter(self)
        painter.translate(0, self.height())
        painter.rotate(-90)
        # calculate the size of the font
        fm = QtGui.QFontMetrics(painter.font())
        xoffset = int(fm.boundingRect(self.text()).width()/2)
        yoffset = int(fm.boundingRect(self.text()).height()/2)
        x = int(self.width()/2) + yoffset
        y = int(self.height()/2) - xoffset
        # because we rotated the label, x affects the vertical placement, and y affects the horizontal
        painter.drawText(y, x, self.text())
        painter.end()
        
    def minimumSizeHint(self):
        size = QtWidgets.QLabel.minimumSizeHint(self)
        return QtCore.QSize(size.height(), size.width())

    def sizeHint(self):
        size = QtWidgets.QLabel.sizeHint(self)
        return QtCore.QSize(size.height(), size.width())

class Example(QtWidgets.QWidget):
    def __init__(self):
        super(Example, self).__init__()
        self.initUI()

    def initUI(self):
        lbl1 = VerticalLabel('ABSOLUTE')
        lbl1.setFont(QtGui.QFont('Arial', 20))
        lbl1.setStyleSheet("QLabel { background-color : black; color : orange; }"); 
        lbl2 = VerticalLabel('lbl 2')
        lbl3 = VerticalLabel('lbl 3')
        hBoxLayout = QtWidgets.QHBoxLayout()
        hBoxLayout.addWidget(lbl1)
        hBoxLayout.addWidget(lbl2)
        hBoxLayout.addWidget(lbl3) 
        self.setLayout(hBoxLayout)
        self.setGeometry(300, 300, 250, 150) 
        self.show()

def main():
    app = QtWidgets.QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
Ben DeMott
  • 3,362
  • 1
  • 25
  • 35