PyQt5 - 如何向 QMessageBox 添加滚动条

问题描述 投票:0回答:3

我有一个根据用户输入生成的列表。

我正在尝试在 QMessageBox 中显示此列表。但是,我无法知道这个列表的长度。这个清单可能很长。

因此,我需要向 QMessageBox 添加滚动条。

有趣的是,我到处寻找,但没有找到任何解决方案。

下面是我希望成为一个“最小、完整且可验证的示例”,当然没有用户输入;我刚刚创建了一个列表作为示例。

我很感激任何建议。

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_())
python pyqt pyqt5 qmessagebox
3个回答
10
投票

您不能直接添加滚动条,因为负责显示文本的小部件是

QLabel
。解决办法是添加一个
QScrollArea
。大小可能不够,因此必须使用样式表来设置最小值。

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_())

输出:


1
投票

这是覆盖小部件行为的另一种方法。

您可以使用“children()”获取对小部件子级的引用。 然后您可以像任何其他小部件一样操作它们。

这里我们添加一个QScrollArea和QLabel到原始widget的QGridLayout中。我们从原始小部件的标签中获取文本并将其复制到新标签中,最后我们清除原始标签中的文本,以便它不会显示(因为它位于新标签旁边)。 我们的新标签是可滚动的。我们必须设置scrollArea的最小尺寸,否则会很难阅读。

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_())

0
投票

另一个想法是在自定义类中修改 QMessageBox 布局,基本上提取用于消息的 Qlabel,将其添加到滚动区域,最后将滚动区域插入 QMessageBox 布局中与原始标签相同的位置

class MessageBox(QtWidgets.QMessageBox):
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.label = label =self.findChild(QtWidgets.QLabel, "qt_msgbox_label")
        idx = self.layout().indexOf(label)
        position = self.layout().getItemPosition(idx)
        self.layout().removeWidget(label)

        layout = QtWidgets.QVBoxLayout()

        scroll_contents = QtWidgets.QWidget()
        scroll_contents.setLayout(layout)

        self.scroll = scroll = QtWidgets.QScrollArea()
        scroll.setMinimumWidth(400)
        scroll.setMinimumHeight(300)
        scroll.setWidgetResizable(True)
        scroll.setWidget(scroll_contents)
        scroll.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)

        layout.addWidget(label)

        self.layout().addWidget(scroll, *position)
© www.soinside.com 2019 - 2024. All rights reserved.