简体   繁体   中英

PyQt5 - How to add a scrollbar to a QMessageBox

I have a list which is generated based on user-input.

I am trying to display this list in a QMessageBox. But, I have no way of knowing the length of this list. The list could be long.

Thus, I need to add a scrollbar to the QMessageBox.

Interestingly, I looked everywhere, but I haven't found any solutions for this.

Below is, what I hope to be a “Minimal, Complete and Verifiable Example”, of course without the user input; I just created a list as an example.

I appreciate any advice.

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class W(QWidget):

   def __init__(self):
      super().__init__()

      self.initUi()

   def initUi(self):
      self.btn = QPushButton('Show Message', self)
      self.btn.setGeometry(10, 10, 100, 100)
      self.btn.clicked.connect(self.buttonClicked)
      self.lst = list(range(2000))
      self.show()


   def buttonClicked(self):
      result = QMessageBox(self)
      result.setText('%s' % self.lst)
      result.exec_()

if __name__ == "__main__":
   app = QApplication(sys.argv)
   gui = W()
   sys.exit(app.exec_())

You can not add a scrollbar directly since the widget in charge of displaying the text is a QLabel . The solution is to add a QScrollArea . The size may be inadequate so a stylesheet has to be used to set minimum values.

class ScrollMessageBox(QMessageBox):
   def __init__(self, l, *args, **kwargs):
      QMessageBox.__init__(self, *args, **kwargs)
      scroll = QScrollArea(self)
      scroll.setWidgetResizable(True)
      self.content = QWidget()
      scroll.setWidget(self.content)
      lay = QVBoxLayout(self.content)
      for item in l:
         lay.addWidget(QLabel(item, self))
      self.layout().addWidget(scroll, 0, 0, 1, self.layout().columnCount())
      self.setStyleSheet("QScrollArea{min-width:300 px; min-height: 400px}")

class W(QWidget):
   def __init__(self):
      super().__init__()
      self.btn = QPushButton('Show Message', self)
      self.btn.setGeometry(10, 10, 100, 100)
      self.btn.clicked.connect(self.buttonClicked)
      self.lst = [str(i) for i in range(2000)]
      self.show()


   def buttonClicked(self):
      result = ScrollMessageBox(self.lst, None)
      result.exec_()

if __name__ == "__main__":
   app = QApplication(sys.argv)
   gui = W()
   sys.exit(app.exec_())

Output:

在此处输入图片说明

Here is another way to override the widgets behavior.

You can get references to the children of the widget by using 'children()'. Then you can manipulate them like any other widget.

Here we add a QScrollArea and QLabel to the original widget's QGridLayout. We get the text from the original widget's label and copy it to our new label, finally we clear the text from the original label so it is not shown (because it is beside our new label). Our new label is scrollable. We must set the minimum size of the scrollArea or it will be hard to read.

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class ScrollMessageBox(QMessageBox):
   def __init__(self, *args, **kwargs):
      QMessageBox.__init__(self, *args, **kwargs)
      chldn = self.children()
      scrll = QScrollArea(self)
      scrll.setWidgetResizable(True)
      grd = self.findChild(QGridLayout)
      lbl = QLabel(chldn[1].text(), self)
      lbl.setWordWrap(True)
      scrll.setWidget(lbl)
      scrll.setMinimumSize (400,200)
      grd.addWidget(scrll,0,1)
      chldn[1].setText('')
      self.exec_()

class W(QWidget):
   def __init__(self):
      super(W,self).__init__()
      self.btn = QPushButton('Show Message', self)
      self.btn.setGeometry(10, 10, 100, 100)
      self.btn.clicked.connect(self.buttonClicked)
      self.message = ("""We have encountered an error.
The following information may be useful in troubleshooting:
1
2
3
4
5
6
7
8
9
10
Here is the bottom.
""")
      self.show()

   def buttonClicked(self):
       result = ScrollMessageBox(QMessageBox.Critical,"Error!",self.message)

if __name__ == "__main__":
   app = QApplication(sys.argv)
   gui = W()
   sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM