سؤال

I'm attempting to produce a widget that consists of a text display that can be resized by the user grabbing the lower right corner. So far I've been able to generate this:

enter image description here

I've applied a red background to the layout to make it more obvious what's going on. I've used the following code to generate this:

  m_sizeGrip = new QSizeGrip( this );
  m_layout = new QHBoxLayout( this );
  m_label = new QLabel( this );

  m_layout->setContentsMargins( QMargins() );
  m_layout->setSpacing( 0 );
  m_layout->addWidget( m_label );
  m_layout->addWidget( m_sizeGrip, 0, Qt::AlignBottom | Qt::AlignRight );

  setWindowFlags( Qt::SubWindow );

Basically, it's a horizontal layout with the label and grip added to it, which is then installed on a QWidget. My problem is that I'd like the grip to be on the lower right corner of the label, rather than the parent widget. I'd also like to make it invisible while keeping it enabled.

Or perhaps I'm going about this the wrong way. My ultimate goal is to have a textual display widget that can be resized by the user either horizontally or vertically, but doesn't have a visible grip that would obscure the text. Am I already on the right track with the code above, or is there a better way to achieve this?

هل كانت مفيدة؟

المحلول

You could create a custom QLabel for that. The idea would be to track mouse move events (which by default only fire when a mouse button is pressed), and resize based on how much the mouse traveled since the last event.

This allows you to control exactly how to display the "gripper" (if at all) and what shape it should have. You can constrain the resizing to vertical or horizontal (or not).

Here's a demo of how you could do that (resizes both ways). Warning: this might wreak havoc in your layout.

#include <QtGui>

class GripLabel: public QLabel
{
    Q_OBJECT

    public:
        GripLabel(QString const& title, QWidget* parent = 0)
            : QLabel(title, parent),
              resizing(false),
              gripSize(10, 10)
        {
            // Prevent the widget from disappearing altogether
            // Bare minimum would be gripSize
            setMinimumSize(100, 30);
        }

        QSize sizeHint() const
        {
            return minimumSize();
        }

    protected:
        bool mouseInGrip(QPoint mousePos)
        {
            // "handle" is in the lower right hand corner
            return ((mousePos.x() > (width()  - gripSize.width()))
                &&  (mousePos.y() > (height() - gripSize.height())));
        }

        void mousePressEvent(QMouseEvent *e)
        {
            // Check if we hit the grip handle
            if (mouseInGrip(e->pos())) {
                oldPos = e->pos();
                resizing = true;
            } else {
                resizing = false;
            }
        }

        void mouseMoveEvent(QMouseEvent *e)
        {
            if (resizing) {
                // adapt the widget size based on mouse movement
                QPoint delta = e->pos() - oldPos;
                oldPos = e->pos();
                setMinimumSize(width()+delta.x(), height()+delta.y());
                updateGeometry();
            }
        }

        void paintEvent(QPaintEvent *e)
        {
            QLabel::paintEvent(e);
            QPainter p(this);
            p.setPen(Qt::red);
            p.drawRect(width()-gripSize.width(), height()-gripSize.height(),
                       gripSize.width(), gripSize.height());
        }

    private:
        bool resizing;
        QSize gripSize;
        QPoint oldPos;
};

Sample main:

#include "griplabel.h"

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QWidget *w = new QWidget;
    QPushButton *b = new QPushButton("button");
    GripLabel *l = new GripLabel("Hello");
    QHBoxLayout *y = new QHBoxLayout;
    y->addWidget(b);
    y->addWidget(l);
    y->setSizeConstraint(QLayout::SetFixedSize);
    w->setLayout(y);
    w->show();
    return app.exec();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top