4

How to place text (not just a number) in the middle of QProgressBar when setRange(0, 0) on Windows?

The following is a PyQt example which still doesn't work as expected.

import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.resize(800, 600)

#        self.lb=QLabel('finding resource   ')

        self.pb = QProgressBar()
        self.pb.setRange(0, 0)

        self.pb.setAlignment(Qt.AlignCenter)
        self.pb.setFormat('finding resource...')
        self.pb.setStyleSheet("text-align: center;")

#        self.pb.setTextVisible(False)


        self.statusBar().setSizeGripEnabled(False)
#        print(self.statusBar().layout() )
        self.statusBar().setStyleSheet("QStatusBar::item {border: none;}")
        self.statusBar().addPermanentWidget(self.pb, 1)


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

    ui = MainWindow()
    ui.show()
    sys.exit(app.exec_())
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
iMath
  • 2,326
  • 2
  • 43
  • 75
  • 2
    If you're going to [cross-post](http://lists.qt-project.org/pipermail/pyside/2014-December/002235.html) [every question](http://www.riverbankcomputing.com/pipermail/pyqt/2014-December/035240.html) that you ask, could you please have the decency to say that you have done so and provide the appropriate links? – ekhumoro Dec 19 '14 at 18:06
  • sorry, I'll remember your warning and follow the netiquette next time! – iMath Dec 21 '14 at 14:10

2 Answers2

5

vahancho explained the reason nicely in his answer and mentioned to override QProgressBar.text(). Fortunately this is straightforward in Python and I know how to do it.

from PySide import QtGui, QtCore

class MyProgressBar(QtGui.QProgressBar):
"""
    Progress bar in busy mode with text displayed at the center.
"""

    def __init__(self):
        super().__init__()
        self.setRange(0, 0)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self._text = None

    def setText(self, text):
        self._text = text

    def text(self):
        return self._text

app = QtGui.QApplication([])

p = MyProgressBar()
p.setText('finding resource...')
p.show()

app.exec_()

gives

enter image description here

This is on Windows 7.

Btw. First I thought about the brute force approach: QStackedLayout with a QLabel on top of a QProgressBar. That should also always work.

Community
  • 1
  • 1
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
  • Plus one, but I think `setAlignment` (and probably also `setRange`) should really go in the `__init__`, as it's required to meet the OPs original spec – ekhumoro Jan 07 '15 at 18:55
  • Thanks ! When changed to PyQt code, it works well ,but the PySide code here prompts "TypeError: 'str' object is not callable" while it is working , have you noticed this ? I guess this is a bug with PySide. – iMath Jan 14 '15 at 12:51
  • @iMath Sorry, I made a tiny mistake resulting in a name clash. Before I had the text hardcoded. Code is fixed now, even for PySide. – NoDataDumpNoContribution Jan 14 '15 at 15:00
  • Thank you very much ! but why name clash doesn't happen in PyQt ? Which used a rather good tool to wrap Qt for Python , PySide or PyQt ? – iMath Jan 15 '15 at 05:27
  • @iMath PyQt or PySide - both should be mostly equivalent. PyQt supports Qt 5 but has a more restrictive license, i.e. you cannot make commercial products with it, afaik. If the answer now fully solves your question, why not marking it as solved? – NoDataDumpNoContribution Jan 15 '15 at 08:19
  • you can make commercial products with PyQt provided you buy the license. – iMath Jan 16 '15 at 12:34
2

The reason of why you do not see a text in your progress bar when the range is set to min=0 and max=0, is that QProgressBar::text() function returns an empty string in that case. The source code of QProgressBar::text() function contains the following lines:

QString QProgressBar::text() const
{
    Q_D(const QProgressBar);
    if ((d->maximum == 0 && d->minimum == 0) || d->value < d->minimum
            || (d->value == INT_MIN && d->minimum == INT_MIN))
        return QString(); // <---- an empty string on null range.
[..]

Therefor the text is invisible. The only way you can change the behavior is overriding the QProgressBar::text() function as it is declared to be a virtual function. Unfortunately I do not know how to do it in Python.

vahancho
  • 20,808
  • 3
  • 47
  • 55
  • 1
    Although that fixes the issue of forcing the text to display in busy mode, it does not show it in the middle of the progress bar (the style determines that). – ekhumoro Dec 19 '14 at 17:53
  • yes, any way to show it in the middle of the progress bar ? – iMath Dec 21 '14 at 14:12
  • @ekhumoro Well as least on Windows the text is in the middle. See image in the other answer. – NoDataDumpNoContribution Jan 07 '15 at 09:09
  • @Trilarion. No, the default text alignment is determined by the style. The Qt "Windows" and "Cleanlooks" styles put the text to the right of the progress meter, whereas most other styles put the text in the middle (not sure about Mac). And this behaviour matches what I see when using PyQt on Windows itself - although I only tested with XP (the default is perhaps different in later Windows versions). Reimplementing `text()` is not enough - it's also necessary to use something like `setAligment()` (as you do in your own answer to this question). – ekhumoro Jan 07 '15 at 18:44