【问题标题】:PyQt: how to handle auto-resize of widgets when their content changesPyQt:如何在内容更改时处理小部件的自动调整大小
【发布时间】:2010-11-12 07:52:29
【问题描述】:

当 qt4 小部件的内容发生变化时,我遇到了一些关于其大小的问题。

我将用两个简单的场景来说明我的问题:

场景 1:

我有一个 QLineEdit 小部件。有时,当我使用 QLineEdit.setText() 更改其内容时,单行字符串不再适合当前大小的小部件。我必须选择小部件并使用箭头键在两个方向滚动字符串才能看到所有内容。

场景 2:

我有一个 QTextEdit 小部件。有时,当我使用 QTextEdit.setHtml() 更改其内容时,呈现的 HTML 内容不再适合当前大小的小部件。小部件开始显示水平和/或垂直滚动​​条,我可以使用它们滚动 HTML 内容。

在这种情况下,我想要的是有一些逻辑来决定在内容更改后,新内容是否不再适合小部件并自动增加小部件的大小,以便一切都适合。

如何处理这些场景? 我正在使用 PyQt4。

编辑:在阅读了评论和第一个答案(其中提到在小部件中输入内容)之后,我再次检查了这个问题。发现一个可怕的错字,我感到非常惊讶。当我写 QTextEdit 时,我的意思是 QTextBrowser,我很抱歉误导了你。那就是:我有一个小部件,它呈现我正在更改的 HTML 代码,我希望小部件增长到足以显示所有内容而没有滚动条。

至于 QLineEdit 而不是 QLabel - 我选择了 QLineEdit,因为我注意到我无法用鼠标从 QLabel 中选择文本来复制它。使用 QLineEdit 是可能的。

【问题讨论】:

  • 只是想让你知道你的问题没有被忽视......过去一天我一直在思考这个问题,但我想不出一个简单的方法做你要求的。这根本不是您使用的物品的设计目的。它们是输入小部件,旨在允许输入比屏幕上舒适的数据更多的数据。如果您真的想调整当前项目的大小,请尝试在布局内扩展 QLabels。

标签: c++ python qt qt4 pyqt4


【解决方案1】:

好的,实现sizeHint() 方法。每次您的内容更改大小时,请致电updateGeometry() 当内容改变而不改变大小时,使用update()。 (updateGeometry()自动调用update())。

【讨论】:

    【解决方案2】:

    也许看看Python QT Automatic Widget Resizer。虽然它是用 python 编写的,但它可能会给你一些关于如何去做你需要做的事情的想法。

    【讨论】:

    • 链接断开。这就是正是不赞成仅链接的“答案”的原因...
    【解决方案3】:

    我在这里用 C++ 回答,因为这是我最熟悉的,而且你的问题不是 PyQt 特有的。

    通常,当sizeHint() 可能发生变化时,您只需调用QWidget::updateGeometry(),就像当内容可能发生变化时,您需要调用QWidget::update()

    但是,您的问题是,当将文本添加到 QLineEditQTextEdit 时,sizeHint() 不会更改。有一个原因:人们不希望他们的对话随着他们的类型而增长:)

    也就是说,如果您真的希望这些小部件中的“随类型增长”行为,您需要从它们继承并重新实现 sizeHint()minimumSizeHint() 以返回更大的尺寸,可能还有 setText()、@987654330 @ 等调用 updateGeometry() 以便注意到 sizehint 的变化。

    sizehint 的计算不会很简单,QLineEditQTextEdit 更容易(秘密是 QAbstractScrollArea),但您可以查看 sizeHint()minimumSizeHint()灵感的实现(也是QComboBox 的实现,它有一种模式可以完全按照您的意愿行事:QComboBox::AdjustToContents

    编辑:您的两个用例(QTextBrowser w/o 滚动条和 QLineEdit 而不是 QLabel 仅用于选择其中的文本)可以通过使用 QLabel 和足够近的 Qt 来解决。 QLabel 在 Qt 4.2 中获得了链接点击通知和所谓的“文本交互标志”(其中之一是 TextSelectableByMouse)。我能弄清楚的唯一区别是加载新内容不是自动的,没有历史记录,并且在 QLabel 中没有微焦点提示(即从链接到链接的标签)。

    【讨论】:

    • QLabel 对我不起作用的原因是自动换行。它拒绝将一个单词分开,这在显示链接时是不可接受的。
    • 我遇到了同样的问题,需要 QLabel 来支持 WrapAtWordBoundaryOrAnywhere。
    【解决方案4】:

    我通过使用以下 C++ 类实现了类似的效果:

    textedit.h

    #ifndef TEXTEDIT_H
    #define TEXTEDIT_H
    
    #include <QTextEdit>
    
    class TextEdit : public QTextEdit
    {
      Q_DISABLE_COPY( TextEdit )
    
    public:
      TextEdit( QWidget* parent = NULL );
      TextEdit( const QString& text, QWidget* parent = NULL );
      virtual ~TextEdit();
    
      void fitToDocument( Qt::Orientations orientations );
      virtual QSize sizeHint() const;
    
    private:
      int fittedHeight_;
      Qt::Orientations fittedOrientations_;
      int fittedWidth_;
    };
    
    #include "textedit-inl.h"
    
    #endif // TEXTEDIT_H
    

    textedit-inl.h

    #ifndef TEXTEDITINL_H
    #define TEXTEDITINL_H
    
    #include "textedit.h"
    
    inline TextEdit::TextEdit( QWidget* parent ) :
        QTextEdit( parent ), fittedOrientations_( 0 )
    { }
    
    inline TextEdit::TextEdit( const QString& text, QWidget* parent ) :
        QTextEdit( text, parent ), fittedOrientations_( 0 )
    { }
    
    inline TextEdit::~TextEdit()
    { }
    
    inline QSize TextEdit::sizeHint() const
    {
      QSize sizeHint = QTextEdit::sizeHint();
      if( fittedOrientations_ & Qt::Horizontal )
        sizeHint.setWidth( fittedWidth_ );
      if( fittedOrientations_ & Qt::Vertical )
        sizeHint.setHeight( fittedHeight_ );
      return sizeHint;
    }
    
    #endif // TEXTEDITINL_H
    

    文本编辑.cpp

    #include "textedit.h"
    
    void TextEdit::fitToDocument( Qt::Orientations orientations )
    {
      QSize documentSize( document()->size().toSize() );
      QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
      if( orientations & Qt::Horizontal ) {
        fittedWidth_ = documentSize.width() + (width() - viewport()->width());
        sizePolicy.setHorizontalPolicy( QSizePolicy::Fixed );
      }
      if( orientations & Qt::Vertical ) {
        fittedHeight_ = documentSize.height() + (width() - viewport()->width());
        sizePolicy.setVerticalPolicy( QSizePolicy::Fixed );
      }
      fittedOrientations_ = orientations;
      setSizePolicy( sizePolicy );
      updateGeometry();
    }
    

    例如,调用TextEdit::fitToDocument( Qt::Horizontal ) 会将小部件的宽度设置为一个固定的宽度,该宽度正好足够大以适应文档及其周围环境(例如,垂直滚动条,如果有的话)。如果您的目标是在内容更改时发生这种情况,请将QTextEdit::textChanged() 信号连接到调用TextEdit::fitToDocument() 的插槽。

    至于QLabel 的问题,解决方法很简单:致电QLabel::setTextInteractionFlags( Qt::LinksAccessibleByMouse | Qt::TextSelectableByMouse )

    【讨论】:

      【解决方案5】:

      对于 QTextBrowser 情况,您应该能够使用获取文档的大小

      QTextBrowser::document()->size();
      

      在设置 html 之后,然后在 QTextBrowser 中调整它的大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        相关资源
        最近更新 更多