python qt5 label 文本过长 滚动区


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 660)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.horizontalLayout.addWidget(self.comboBox)
        self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.verticalLayout_2.addLayout(self.horizontalLayout)
        self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth())
        self.scrollArea.setSizePolicy(sizePolicy)
        self.scrollArea.setMinimumSize(QtCore.QSize(650, 550))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setObjectName("scrollArea")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 776, 548))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
        self.label.setSizePolicy(sizePolicy)
        self.label.setMinimumSize(QtCore.QSize(400, 500))
        self.label.setText("")
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
        self.verticalLayout_2.addWidget(self.scrollArea)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.comboBox.setItemText(0, _translate("MainWindow", "图片文件"))
        self.comboBox.setItemText(1, _translate("MainWindow", "文本文件"))
        self.pushButton.setText(_translate("MainWindow", "确定"))


import os
import cv2
import sys
import time
from PyQt5.QtWidgets import QMessageBox, QApplication, QMainWindow, QDialog
from PyQt5 import QtGui
from untitled import Ui_MainWindow
from PyQt5.QtCore import QRunnable, QThreadPool, pyqtSlot


class ImageLoader(QRunnable):
    def __init__(self, file_path, label):
        super(ImageLoader, self).__init__()
        self.file_path = file_path
        self.label = label

    @pyqtSlot()
    def run(self):
        image = cv2.imread(self.file_path)
        if image is not None:

            image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
            qImg = QtGui.QImage(image.data, image.shape[1], image.shape[0], QtGui.QImage.Format_RGB888)
            pixmap = QtGui.QPixmap.fromImage(qImg)

            image_width = image.shape[1]
            image_height = image.shape[0]

            time.sleep(1)

            self.label.setFixedWidth(image_width)
            self.label.setFixedHeight(image_height)

            self.label.setPixmap(pixmap)

            self.label.adjustSize()  # 调整标签大小,以适应图片大小(不会对图片造成影响)
        else:
            QMessageBox.warning(None, "错误", "图像文件路径无效")




class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        # 调用QMainWindow类的构造函数,初始化主窗口对象。
        super(MainWindow, self).__init__()
        self.setupUi(self)

        self.pushButton.clicked.connect(self.pushButton_function)

    def pushButton_function(self):
        content = self.comboBox.currentText()
        filePath = self.lineEdit.text()
        if content == "图片文件":

            image_loader = ImageLoader(filePath, self.label)

            QThreadPool.globalInstance().start(image_loader)

        elif content == "文本文件":
            fileExtension = os.path.splitext(filePath)[-1]
            if fileExtension == ".txt":
                with open(filePath, "r", encoding="utf-8") as text_file:
                    text = text_file.read()
                    self.label.setText(text)
            else:
                QMessageBox.warning(None, "错误", "无效的文本文件")
        else:
            QMessageBox.warning(None, "错误", "请选择正确类型")



if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

img

我希望在label上显示文本时,当文本太长时自动出现滚动条,可是实际上并没有出现滚动条。我也添加了滚动区,在显示图片时滚动区就正常出来了,可是文本就不行。请问该怎么修改?
不能把label换成lineEdit,因为我需要它既能显示图片,又能显示文本。

你们回答的都不是我想要的。我已经明白是为什么了。
这是因为我没有设置label的大小,导致label不能完整的显示文本,所以即使加了scrollarea也没有用,也不会出现滚动条。
正确的做法是先设置label的大小,确保label能完整地显示文本,这样scrollarea也会自动出现(scrollarea是为label服务的,当label过大时就会出现滚动条)。在label中设置图片也是同理。
以下是修改后的代码。

                with open(filePath, "r", encoding="utf-8") as text_file:
                    text = text_file.read()  # text 是一个字符串对象  字符串对象没有font()方法
                    text_line = text_file.readline()
                    line_count = len(text_file.readlines())

                    self.label.setText(text)

                    font_metrics = QFontMetrics(self.label.font())

                    text_height = QFontMetrics(font_metrics).lineSpacing() * line_count
                    text_width = QFontMetrics(font_metrics).width(text_line) * 2

                    self.label.setMinimumSize(text_width, text_height)

                    self.label.setText(text)

这里涉及到:Qt 中获取字体的像素高度和宽度
https://blog.csdn.net/hanzengyi/article/details/6305791#:~:text=1%201.%20QLabel%3A%3A%20fontMetrics%20%28%29.%20width%20%28QString%20s%29%3A,%E8%8E%B7%E5%8F%96%E5%AD%97%E4%BD%93%E7%9A%84%E9%AB%98%E5%BA%A6%EF%BC%8C%E5%8C%85%E6%8B%AC%E6%96%87%E5%AD%97%E7%9A%84%E5%AE%9E%E9%99%85%E5%AE%BD%E5%BA%A6%E5%92%8C%E8%A1%8C%E8%B7%9D%E3%80%82%204%204.%20QLabel%3A%3A%20fontMetrics%20%28%29.leading%20%28%29%3A%20%E8%A1%8C%E9%97%B4%E8%B7%9D

QLabel你设定好它的大小后,它就固定不变了。它也没法加滚动条,只能把QLabel放到滚动条区域中。
你这个需求,既要显示图片,也要能显示文本,可以使用QTextEdit控件,完全能满足你的要求。
参考如下:

  • 这篇文章讲的很详细,请看:Qt5 设置label自动换行,同理可用于其它文字显示的自动换行
  • 除此之外, 这篇博客: 关于PyQt5在Label标签插入图片并且实现图片的拖拽和缩放中的 label图片的拖拽实现 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 首先关于label标签内插入图片,为了实现图片的移动,可以将label标签插入到一个容器内,我选择的是QGroupBox,设置窗口的代码如下:

    class Ui_Form(QtWidgets.QWidget):
        def __init__(self):
            super(Ui_Form, self).__init__()
            self.setGeometry(100,100,1000,800)
            self.setWindowTitle('image')
            self.groupBox = QtWidgets.QGroupBox(self)  #设置的groupBox容器
            self.groupBox.setGeometry(QtCore.QRect(10, 60, 841, 611))
    
            self.groupBox.setObjectName("groupBox")
            self.label = QtWidgets.QLabel(self.groupBox)   #设置的位于容器内部的label控件
            self.label.setCursor(QtCore.Qt.PointingHandCursor)
            self.label.setGeometry(QtCore.QRect(0, 0, 621, 461))
          
    
            self.label.setObjectName("label")
            self.label.setAlignment(QtCore.Qt.AlignCenter)

     关于图片的插入我这里是设置了一个按钮控件链接到一个槽函数获取本地图片文件,然后显示在label上:

       def on_pushButton1_clicked(self):
            self.path = QtWidgets.QFileDialog.getOpenFileName()#获取本地文件路径
            self.cur_img = cv.imread(self.path[0]) #此处使用了OpenCV包的函数
            self.img = QPixmap(self.path[0])   #获取QPimax对象
            self.label.setPixmap(self.img)     #插入label中
            self.label.setFrameShape(QtWidgets.QFrame.Box)  #设置label标签的边框
            self.label.setLineWidth(1)      
            self.label_w = self.label.width()
            self.label_x = self.label.x()
            self.label_y = self.label.y()
            self.label_h = self.label.height()
            self.label.setScaledContents(True)    #设置label内部图片自适应填充

    随后便是实现图片的拖拽了,这里我们需要实现鼠标按下、释放以及鼠标移动事件:

     def mousePressEvent(self, e):
            if e.buttons() == QtCore.Qt.LeftButton:
                self.flag = True
    
     def mouseReleaseEvent(self, e):  #鼠标释放事件重写
            self.flag = False
            self.movex = ""
            self.movey = ""

    这里设置的中间点需要我们在之前设置好,这里每次释放的时候把其全部清空,然后便是鼠标移动事件

     def mouseMoveEvent(self, e):
            if self.flag:
                self.x1 = e.x()
                self.y1 = e.y()
            if self.movex != "" and self.movey != "":
                self.label_x = self.label_x + (self.x1 - self.movex)
                self.label_y = self.label_y + (self.y1 - self.movey)
            self.movex = self.x1
            self.movey = self.y1
            self.label.setGeometry(QtCore.QRect(self.label_x, self.label_y, self.label_w, self.label_h))  #使得图片能够随着缩放而不影响大小,
    #同时QtCore.QRect确定图形为矩形
    

    显然,拖拽事件是利用鼠标按下时flag为True,结合鼠标移动事件在释放时重新获得label标签的坐标,鼠标释放时将中间点清空,以防止影响下一次拖拽事件。这里需要细品的就是鼠标移动事件里的第二个if语句的内容,通过判断中间点的坐标是否为空来进行事件的进行。