RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1607145
Accepted
Евграф Котовский
Евграф Котовский
Asked:2025-02-18 17:23:07 +0000 UTC2025-02-18 17:23:07 +0000 UTC 2025-02-18 17:23:07 +0000 UTC

PyQt5 中 QLabel 中的文本超出范围

  • 772

我为fb2书籍编写了这个阅读器,见下文。

当我将列表中的文本粘贴pages[]到 时textLabel,
文本“超出”了 的宽度textLabel。

在此处输入图片描述


setWordWrap这有帮助,但是文本变得难以阅读。

在此处输入图片描述

没有的话该如何修复setWordWrap?


main.py:

import sys
from config import *
from PyQt5.Qt import *
from src.Book import *
from src.styles.WhiteTheme import *


class BookViewer(object):
    def __init__(self, appStyle: style = WhiteTheme, appStyleFromSystem="Windows",
                 app=QApplication(sys.argv)) -> None:

        self.app = app
        self.Book = None

        # creating and configuring BookViewer window
        self.content = QWidget()
        self.content.setFixedSize(500, 500)
        self.content.setWindowIcon(QIcon("./media/karfagen.png"))
        self.content.setWindowTitle(f"Karfagen Book Viewer")
        self.content.setStyleSheet(appStyle.style)
        self.text_font = QFont(FONT_NAME, TEXT_SIZE)
        self.text_height = QFontMetrics(self.text_font)

        self.layout = QVBoxLayout(self.content)

        self.pageNumber = 0

        self.textLabel = QLabel()
        self.textLabel.setFixedWidth(400)
        self.textLabel.setFixedHeight(400)

        self.navigationBox = QGroupBox()
        self.navigationBox.setStyleSheet("""
        QGroupBox {
            border: 0px black solid;
        }
        """)

        #creating navigation panel
        self.navigationTopPanel = QWidget()
        self.navigationTopPanelLayout = QHBoxLayout()
        self.navigationTopPanel.setLayout(self.navigationTopPanelLayout)

        self.openFile = QPushButton(text = "open file")
        self.openFile.clicked.connect(self.openFileFunc)
        self.openFile.setFixedWidth(70)

        self.layout.addWidget(self.navigationTopPanel)

        self.navigationTopPanelLayout.addWidget(self.openFile)
        self.navigationTopPanelLayout.setAlignment(Qt.AlignLeft)

        #creating elements for navigation in Book
        self.navigationBoxLayout = QHBoxLayout()

        self.btn_prev = QPushButton(text="<")
        self.btn_prev.clicked.connect(self.prev_page)

        self.pageNumberLabel = QLabel(text=str(self.pageNumber))

        self.btn_next = QPushButton(text=">")
        self.btn_next.clicked.connect(self.next_page)

        self.navigationBoxLayout.addWidget(self.btn_prev)
        self.navigationBoxLayout.setAlignment(Qt.AlignCenter)
        self.navigationBoxLayout.addWidget(self.pageNumberLabel)
        self.navigationBoxLayout.addWidget(self.btn_next)

        self.navigationBox.setLayout(self.navigationBoxLayout)

        self.layout.addWidget(self.textLabel)
        self.layout.addStretch()
        self.layout.addWidget(self.navigationBox)
        self.content.setLayout(self.layout)

    def start(self):
        self.content.show()
        self.app.exec_()

    def render_page(self, pageNumber):
        try:
            self.pageNumberLabel.setText(str(pageNumber + 1))
            self.textLabel.setText("".join(self.pages[self.pageNumber]))
        except Exception as e:
            self.show_messagebox(str(e))

    def prev_page(self):
        if self.pageNumber > 0 and self.Book:
            self.pageNumber -= 1
            self.render_page(self.pageNumber)

    def next_page(self):
        if self.pageNumber <= len(self.pages) and self.Book:
            self.pageNumber += 1
            print(self.pageNumber)
            self.render_page(self.pageNumber)

    def parseBookData(self):
        """
        Parses raw book data into pages, handling paragraph wrapping and page breaks.

        Returns:
            A list of pages, where each page is a list of strings (paragraphs/lines).
        """

        pages= []
        page = []
        current_text_height = 0
        font_metrics = QFontMetrics(QFont(FONT_NAME, TEXT_SIZE))

        for paragraph in self.Book.text_data:
            # Split paragraph into lines that fit
            lines = self.split_paragraph_into_lines(paragraph, font_metrics, self.textLabel.width())
            for line in lines:
                line_height = font_metrics.height()  # Use actual line height

                if current_text_height + line_height <= self.textLabel.height():
                    page.append(line + "<br>")
                    current_text_height += line_height
                else:
                    pages.append(page)
                    page = [line]
                    current_text_height = line_height  # Reset height to the current line's height

        # Add the last page if it's not empty
        if page:
            pages.append(page)

        return pages

    def split_paragraph_into_lines(self, paragraph: str, font_metrics: QFontMetrics, max_width: int):
        """
        Splits a paragraph into lines that fit within the maximum width, handling word wrapping.

        Args:
            paragraph: The paragraph to split.
            font_metrics: QFontMetrics object.
            max_width: The maximum width for a line.

        Returns:
            A list of strings, where each string is a line.
        """

        if font_metrics.horizontalAdvance(paragraph) >= self.textLabel.width():

            words = paragraph.split()
            lines = []
            current_line = ""

            for word in words:
                test_line = current_line + word + " "  # Add word and a space to test
                if font_metrics.horizontalAdvance(test_line) <= max_width:
                    current_line = test_line
                else:
                    if current_line:  # Add the current line if it's not empty
                        newString = ""
                        for i in range(len(current_line)):
                            newString += current_line[i]
                            if font_metrics.horizontalAdvance(newString) == max_width:
                                break
                    lines.append(newString)
                    current_line = word + " " + current_line[i:len(current_line)]  # Start a new line with the current word

            if current_line:  # Add the last line
                lines.append(current_line.strip())
            return lines

        else:
            return [paragraph]

    def openFileFunc(self):
        options = QFileDialog.Options()

        # Get the file names from the dialog
        files, _ = QFileDialog.getOpenFileNames(self.content,
                                                 "Select Fiction Book Files",
                                                 "",
                                                 "Fiction Book 2 (*.fb2);;All Files (*)",
                                                 options=options)
        if files:
            self.Book = Book(files[0])
            self.Book.parse()

            self.content.setWindowTitle(self.Book.title + " " + self.Book.author + " " + "Karfagen Book Viewer")
            self.pages = self.parseBookData()
            self.render_page(self.pageNumber)

    def show_messagebox(self, text):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Icon.Error)
        msg.setText(text)
        msg.setInformativeText("")
        msg.setWindowTitle("error")
        msg.setDetailedText("")
        msg.exec()

Book.py:

from xml.dom.minidom import parse

class Book(object):

    def __init__(self, filename, encoding="UTF-8"):
        self.filename = filename
        self.encoding = encoding

        self.text_data = None
        self.document = None

        self.genre = None
        self.author = None
        self.title = None
        self.lang = None

    def parse(self):
        document = parse(self.filename)

        self.document = document
        self.genre = self.loadTagValueFromXML("genre")
        self.lang = self.loadTagValueFromXML("lang")
        self.author = self.loadTagValueFromXML("last-name") + self.loadTagValueFromXML("first-name")
        self.title = self.loadTagValueFromXML("book-title")

        paragraphs = document.getElementsByTagName("section")
        for paragraph in paragraphs:
            text_nodes = [
                node.childNodes[0].nodeValue for node in paragraph.childNodes
                if node.nodeName == 'p' and node.childNodes[0].nodeValue
            ]
        self.text_data = text_nodes
        self.parsedTextData = []

    def loadTagValueFromXML(self, tag_name):
        try:
            tag = self.document.getElementsByTagName(tag_name)[0].childNodes[0].nodeValue
            return tag
        except IndexError:
            return ""
python
  • 1 1 个回答
  • 66 Views

1 个回答

  • Voted
  1. Best Answer
    S. Nick
    2025-02-23T20:21:49Z2025-02-23T20:21:49Z

    我尝试为你做出一些改变。

    替换为:

        self.textLabel = QLabel()
    

    到:

        self.textLabel = QTextBrowser()
    

    添加者:

    # +++ # +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv           
                paragraph = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + \
                    paragraph + "<br>"                              # +++
    # +++ # +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    + "<br>"从行中删除

        page.append(line + "<br>")
    

    还有一些其他小东西。

    尝试一下你得到的东西。
    您还有一些工作要做。


    书籍查看器

    import sys
    from src.Book import *
    from src.configParser import *
    from PyQt5.Qt import *
    
    
    class BookViewer(object):
        def __init__(self, 
            app = QApplication(sys.argv), 
            appConfig = configParser()) -> None:
    # +
            app.setFont(QFont("Times", 14, QFont.Bold))             # +
            
            self.app = app
            self.Book = None
            self.pages = []
            self.pageNumber = 0
            self.appConfig = appConfig
            self.appStyle = self.appConfig.APP_THEME
    
            # creating and configuring BookViewer window
            self.content = QWidget()
    #?        self.content.setFixedSize(700, 500)
            self.content.resize(700, 500)                            # +
            self.content.setWindowIcon(QIcon("./media/karfagen.png"))
            self.content.setWindowTitle(f"Karfagen Book Viewer")
            self.content.setStyleSheet(self.appStyle)
            self.text_font = QFont(self.appConfig.FONT_NAME, 
                self.appConfig.TEXT_SIZE)
            self.text_height = QFontMetrics(self.text_font)
    
    #?       self.textLabel = QLabel()
            self.textLabel = QTextBrowser()                         # +++
    #        self.textLabel.setWordWrap(True)
    #?       self.textLabel.setFixedWidth(400)
    #?       self.textLabel.setFixedHeight(400)
    
            self.navigationBox = QGroupBox()
            self.navigationBox.setStyleSheet("""
            QGroupBox {
                border: 2px black solid;
            }
            """)
    
            #creating navigation panel
            self.navigationTopPanel = QWidget()
    
            self.openFile = QPushButton(text = "open file")
            self.openFile.clicked.connect(self.openFileFunc)
    #?        self.openFile.setFixedWidth(70)
    
            self.navigationTopPanelLayout = QHBoxLayout(
                self.navigationTopPanel)
            self.navigationTopPanelLayout.addWidget(self.openFile)
            self.navigationTopPanelLayout.setAlignment(Qt.AlignLeft)
    
            #creating elements for navigation in Book
            self.btn_prev = QPushButton(text="<")
            self.btn_prev.clicked.connect(self.prev_page)
    
            self.pageNumberLabel = QLabel(text=str(self.pageNumber))
    
            self.btn_next = QPushButton(text=">")
            self.btn_next.clicked.connect(self.next_page)
    
            self.goToPageField = QLineEdit()
            self.goToPageField.setValidator(QIntValidator())
            self.goToPageField.setPlaceholderText(
                "Enter number of page to go")
            self.goToPageField.setStyleSheet("""
                QLineEdit {
                    border: 0px black solid;
                    background-color: #bbbbbb;
                    color: #000000;
                }
            """)
            self.goToPageField.editingFinished.connect(self.pageByNumber)
    
            self.navigationBoxLayout = QHBoxLayout()
            self.navigationBoxLayout.addWidget(self.btn_prev)
            self.navigationBoxLayout.setAlignment(Qt.AlignCenter)
            self.navigationBoxLayout.addWidget(self.pageNumberLabel)
            self.navigationBoxLayout.addWidget(self.btn_next)
            self.navigationBoxLayout.addWidget(self.goToPageField)
            self.navigationBox.setLayout(self.navigationBoxLayout)
    
            self.layout = QVBoxLayout(self.content)
            self.layout.addWidget(self.navigationTopPanel)        
            self.layout.addWidget(self.textLabel)
    #?        self.layout.addStretch()
            self.layout.addWidget(self.navigationBox)
    #?        self.content.setLayout(self.layout)
    
        def start(self):
            self.content.show()
            self.app.exec_()
    
        def render_page(self, pageNumber):
            try:
                self.pageNumberLabel.setText(
                    f"{str(pageNumber + 1)}/{len(self.pages)}")
                self.textLabel.setText("".join(self.pages[pageNumber]))
            except Exception as e:
                self.show_messagebox(str(e))
    
        def pageByNumber(self):
            pageNumber = int(self.goToPageField.text())
            if pageNumber > 0 and pageNumber <= len(self.pages):
                self.pageNumber = pageNumber
                self.render_page(pageNumber - 1)
     
        def prev_page(self):
            if self.pageNumber > 0 and self.Book:
                self.pageNumber -= 1
                self.render_page(self.pageNumber)
    
        def next_page(self):
            if self.pageNumber <= len(self.pages) and self.Book:
                self.pageNumber += 1
                self.render_page(self.pageNumber)
    
        def parseBookData(self):
            """
            Parses raw book data into pages, handling paragraph 
            wrapping and page breaks.
    
            Returns:
                A list of pages, where each page is a list of 
                strings (paragraphs/lines).
            """
    
            pages= []
            page = []
            current_text_height = 0
    #        font_metrics = QFontMetrics(
    #            QFont(self.appConfig.FONT_NAME, self.appConfig.TEXT_SIZE))
    
            fm = QFontMetrics(self.textLabel.font())                # +         
    
            for paragraph in self.Book.text_data:
            
    # +++ # +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv           
                paragraph = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" + \
                    paragraph + "<br>"                              # +++
    # +++ # +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                # Разделите абзац на строки, которые подходят
                lines = self.split_paragraph_into_lines(
                    paragraph, fm, self.textLabel.width())
        
                line_height = fm.height()                           # +    
                for line in lines:
                    if current_text_height + line_height <= \
                        self.textLabel.height() - 30:
    #                                           ^^^^  чтобы убрать прокрутку
    
    #?                    page.append(line + "<br>") # заменил, смотри выше
                        page.append(line)
                        current_text_height += line_height
                    else:
                        pages.append(page)
                        page = [line]
                        current_text_height = line_height  # Reset height to the current line's height
    # +
                QApplication.processEvents()                        # +
                
            # Добавить последнюю страницу, если она не пустая
            if page:
                pages.append(page)
    
            return pages
    
        def split_paragraph_into_lines(self, 
            paragraph: str, 
            font_metrics: QFontMetrics, 
            max_width: int):
            """
            Splits a paragraph into lines that fit within the maximum width, handling word wrapping.
    
            Args:
                paragraph: The paragraph to split.
                font_metrics: QFontMetrics object.
                max_width: The maximum width for a line.
    
            Returns:
                A list of strings, where each string is a line.
            """
    
            if font_metrics.horizontalAdvance(paragraph) >= self.textLabel.width():
                words = paragraph.split()
                lines = []
                current_line = ""
                for word in words:
                    test_line = current_line + word + " "  # Add word and a space to test
                    if font_metrics.horizontalAdvance(test_line) <= max_width:
                        current_line = test_line
                    else:
                        if current_line:  # Add the current line if it's not empty
                            newString = ""
                            for i in range(len(current_line)):
                                newString += current_line[i]
                                if font_metrics.horizontalAdvance(newString) == max_width:
                                    break
                      
                        lines.append(newString)
    
                        current_line = word + " " + \
                            current_line[i:len(current_line)] # Start a new line with the current word
                if current_line:  # Add the last line
                    lines.append(current_line.strip())
                return lines
            else:
                return [paragraph]
    
        def openFileFunc(self):
            options = QFileDialog.Options()
    
            # Get the file names from the dialog
            files, _ = QFileDialog.getOpenFileNames(
                self.content,
                "Select Fiction Book Files",
                "",
                "Fiction Book 2 (*.fb2);;All Files (*)",
                options=options)
            if files:
                self.Book = Book(files[0])
                self.Book.parse()
    
                self.content.setWindowTitle(
                    self.Book.title + " " + self.Book.author + " " + "Karfagen Book Viewer")
    
                self.pages = self.parseBookData()
                self.render_page(self.pageNumber)
    
        def show_messagebox(self, text):
            msg = QMessageBox()
    #           msg.setIcon(QMessageBox.Icon.Error)
            msg.setText(text)
            msg.setInformativeText("")
            msg.setWindowTitle("error")
            msg.setDetailedText("")
            msg.exec()
    

    在此处输入图片描述

    在此处输入图片描述

    在此处输入图片描述

    在此处输入图片描述

    • 1

相关问题

  • 是否可以以某种方式自定义 QTabWidget?

  • telebot.anihelper.ApiException 错误

  • Python。检查一个数字是否是 3 的幂。输出 无

  • 解析多个响应

  • 交换两个数组的元素,以便它们的新内容也反转

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5