重载resizeEvent

2018-09-20  本文已影响12人  downdemo

简单实现

  • 目标:改变窗口大小时,窗口中的控件布局将相应改变。如:窗口中包含两个QPushButton控件,宽度小于400时,两个按钮垂直排列,宽度拉伸不低于400时,两个按钮则变为垂直排列;
  • 方法:重载resizeEvent;
#ifndef WIDGET_H
#define WIDGET_H

#include <QMainWindow>
#include "qpushbutton.h"
#include "qboxlayout.h"

namespace Ui {
    class Form;
}

class widget : public QMainWindow
{
    Q_OBJECT

public:
    explicit widget(QWidget *parent = 0);
    ~widget();

private:
    Ui::Form *ui;

    QVBoxLayout* layout;
    QHBoxLayout* layout2;
    QPushButton* btn1;
    QPushButton* btn2;
    QWidget* centralWidget;

protected:
    void resizeEvent(QResizeEvent* event);
};

#endif // WIDGET_H
#include "Widget.h"
#include "ui_Widget.h"

widget::widget(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);

    btn1 = new QPushButton;
    btn1->setText("1");
    btn2 = new QPushButton;
    btn2->setText("2");
    centralWidget = new QWidget;
    setCentralWidget(centralWidget);
}

widget::~widget()
{
    delete ui;
}

void widget::resizeEvent(QResizeEvent* event)
{
    int w = width();
    if (w < 400)
    {
        if (centralWidget->layout()) delete centralWidget->layout();
        QVBoxLayout* layout = new QVBoxLayout;
        layout->addWidget(btn1);
        layout->addWidget(btn2);
        centralWidget->setLayout(layout);
    }
    else
    {
        if (centralWidget->layout()) delete centralWidget->layout();
        QHBoxLayout* layout2 = new QHBoxLayout;
        layout2->addWidget(btn1);
        layout2->addWidget(btn2);
        centralWidget->setLayout(layout2);
    }
}

实现效果

宽度低于400应用垂直布局 否则应用水平布局

存在问题

最大化后布局不变 最大化后布局不变 还原后布局却改变

改进

void widget::resizeEvent(QResizeEvent* event)
{
    int w = width();
    if (w < 400)
    {
        if (centralWidget->layout())
        {
            delete centralWidget->layout();
            qDebug() << "d1";
        }
        QVBoxLayout* layout = new QVBoxLayout;
        layout->addWidget(btn1);
        layout->addWidget(btn2);
        centralWidget->setLayout(layout);
        qDebug() << "aaa";
    }
    else
    {
        if (centralWidget->layout())
        {
            delete centralWidget->layout();
            qDebug() << "d2";
        }
        QHBoxLayout* layout2 = new QHBoxLayout;
        layout2->addWidget(btn1);
        layout2->addWidget(btn2);
        centralWidget->setLayout(layout2);
        qDebug() << "bbb";
    }
}
// file "Widget.cpp"

#include "Widget.h"
#include "ui_Widget.h"

widget::widget(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);

    btn1 = new QPushButton;
    btn1->setText("1");
    btn2 = new QPushButton;
    btn2->setText("2");
}

widget::~widget()
{
    delete ui;
}

void widget::resizeEvent(QResizeEvent* event)
{
    int w = width();
    // centralWidget = new QWidget;
    if (w < 400)
    {
        QVBoxLayout* layout = new QVBoxLayout;
        layout->addWidget(btn1);
        layout->addWidget(btn2);
        centralWidget = new QWidget; // 也可以在if else判断之前new
        centralWidget->setLayout(layout);
        setCentralWidget(centralWidget); // 也可以在if else之后设置
    }
    else
    {
        QHBoxLayout* layout2 = new QHBoxLayout;
        layout2->addWidget(btn1);
        layout2->addWidget(btn2);
        centralWidget = new QWidget;
        centralWidget->setLayout(layout2);
        setCentralWidget(centralWidget);
    }
    // setCentralWidget(centralWidget);
}
宽度低于400应用垂直布局 最大化后如预期应用水平布局 还原后恢复垂直布局

加入滚动条

  • 目标:当控件超出窗口大小时,需要提供滚动条,否则控件将缩小并排满窗口。如:窗口中包含10张表格,每张表格高度至少为300,当窗口宽度小于800时,表格垂直排列,不低于800时则水平排列;
  • 方法:使用QScrollArea设置一片带滚动条的区域,这个区域是空的,还需要用setWidget添加一个控件,setWidget只能添加一个控件,如果多次使用只保留最后的设置,若之前setWidget的控件未释放则将成为悬挂指针。在处理上面举例的多个控件问题时,setWidget添加的应该是一个QWidget,QTableWidget添加到layout后,再对QWidget使用setLayout,即QMainWindow - QScrollArea - QWidget - QLayout - QTableWidget
scrollArea = new QScrollArea;
centralWidget = new QWidget;
layout = new QVBoxLayout;
... // 设置layout
// layout->setSizeConstraint(QLayout::SetFixedSize);
centralWidget->setLayout(layout);
scrollArea->setWidget(centralWidget);
setCentralWidget(scrollArea);
不显示控件的QScrollArea
scrollArea->setStyleSheet("background-color:transparent;"); // 透明背景:所有子控件也会受影响
scrollArea->viewport()->setStyleSheet("background-color:transparent;"); // 这句实测无效

详细实现

#ifndef WIDGET_H
#define WIDGET_H

#include <QMainWindow>
#include "qpushbutton.h"
#include "qboxlayout.h"
#include "qscrollarea.h"
#include "qtablewidget.h"

namespace Ui {
    class Form;
}

class widget : public QMainWindow
{
    Q_OBJECT

public:
    explicit widget(QWidget *parent = 0);
    ~widget();

private:
    Ui::Form *ui;

    QVBoxLayout* layout;
    QHBoxLayout* layout2;
    QPushButton* btn1;
    QPushButton* btn2;
    QWidget* centralWidget;
    QScrollArea* scrollArea;
    QTableWidget* table1;
    QTableWidget* table2;

protected:
    void resizeEvent(QResizeEvent* event);
};

#endif // WIDGET_H
#include "Widget.h"
#include "ui_Widget.h"

widget::widget(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);

    centralWidget = new QWidget;

    btn1 = new QPushButton;
    btn1->setText("1");
    btn2 = new QPushButton;
    btn2->setText("2");
    table1 = new QTableWidget(20, 10, 0);
    table2 = new QTableWidget(20, 10, 0);
    table1->setMinimumHeight(200); // 表格设置最小高度
    table2->setMinimumHeight(200);

    for(int i = 0; i < 20; ++i)
        for (int j = 0; j < 10; ++j)
        {
            QTableWidgetItem* item = new QTableWidgetItem;
            QTableWidgetItem* item2 = new QTableWidgetItem;
            QString txt = QString("%1%2").arg(i).arg(j);
            QString txt2 = QString("%1%2").arg(j).arg(i);
            item->setText(txt);
            item2->setText(txt2);
            table1->setItem(i, j, item);
            table2->setItem(i, j, item2);
        }
  
    scrollArea = new QScrollArea;
    setCentralWidget(scrollArea);
}

widget::~widget()
{
    delete ui;
}

void widget::resizeEvent(QResizeEvent* event)
{
    int w = width();
    if (w < 400)
    {
        QVBoxLayout* layout = new QVBoxLayout;
        layout->addWidget(btn1);
        layout->addWidget(btn2);
        layout->addWidget(table1);
        layout->addWidget(table2);
        centralWidget = new QWidget; // 必须在此处创建
        centralWidget->setLayout(layout);
        scrollArea->setWidget(centralWidget);
    }
    else
    {
        QHBoxLayout* layout2 = new QHBoxLayout;
        layout2->addWidget(btn1);
        layout2->addWidget(btn2);
        layout2->addWidget(table1);
        layout2->addWidget(table2);
        centralWidget = new QWidget;
        centralWidget->setLayout(layout2);
        scrollArea->setWidget(centralWidget);
    }
}

实现效果

宽度低于400控件垂直排列 否则水平排列

设置控件大小

可以使用setFixedSize为每个控件指定固定尺寸,也可以用setMinimumSize、setMaximumSize设置最小、最大尺寸,或者用setFixedHeight、setFixedWidth、setMinimumHeight、setMinimumWidth、setMaximumHeight、setMaximumWidth单独设置高度或宽度。在构造函数中或resizeEvent中设置均可,若不根据窗口大小变化则在构造函数中设置,若需要变化则在resizeEvent中设置。

void widget::resizeEvent(QResizeEvent* event)
{
    int w = width();
    if (w < 400)
    {
        QVBoxLayout* layout = new QVBoxLayout;
        btn1->setFixedSize(100, 50);
        btn2->setFixedSize(50, 100);
        layout->addWidget(btn1);
        layout->addWidget(btn2);
        layout->addWidget(table1);
        layout->addWidget(table2);
        centralWidget = new QWidget;
        centralWidget->setLayout(layout);
        scrollArea->setWidget(centralWidget);
    }
    else
    {
        QHBoxLayout* layout2 = new QHBoxLayout;
        btn1->setFixedSize(50, 100);
        btn2->setFixedSize(100, 50);
        layout2->addWidget(btn1);
        layout2->addWidget(btn2);
        layout2->addWidget(table1);
        layout2->addWidget(table2);
        centralWidget = new QWidget;
        centralWidget->setLayout(layout2);
        scrollArea->setWidget(centralWidget);
    }
}
宽度低于400 宽度不低于400

拖动中间边线同时改动左右窗口大小

  • 目标:主窗口分为左右两部分,按下鼠标拖动中间的边框线可以减小(增大)左窗口宽度,同时增大(减小)右窗口宽度
  • 方法:所有窗口类都必须派生自QWidget,且setMouseTracking(true)。若窗口为QMainWindow派生类,则创建一个QWidget,添加布局以把QMainWindow放置到QWidget上。使用setGeometry设置左右窗口位置,然后重载mouseMoveEvent。此外考虑,拉伸窗口时,右边的子窗口增大,还要重载resizeEvent
B1::B1(QWidget* parent) : QWidget(parent), ui(new Ui::B1)
{
    ui->setupUi(this);
    setMouseTracking(true);

    // 左窗口为QMainWindow的处理方法
    left = new QWidget(this);
    QHBoxLayout* leftLayout = new QHBoxLayout;
    My_MainWindow* leftWidget = new My_MainWindow;
    leftLayout->addWidget(leftWidget);
    left->setLayout(leftLayout);
    // 右窗口为QWidget无需处理
    right = new My_Widget(this);
    const int defaultWidth = 500; // 左窗口初始宽度
    left->setGeometry(0, 0, defaultWidth, height());
    right->setGeometry(defaultWidth, 0, width()-defaultWidth, height());
    right->setMinimumWidth(100); // 如果是osg模型要加上这句,否则拖动到最右侧删掉模型
    left->setMouseTracking(true);
    right->setMouseTracking(true);
}

void B1::resizeEvent(QResizeEvent* event)
{
    left->setGeometry(0, 0, left->width(), height());
    right->setGeometry(left->width(), 0, width() - left->width(), height());
}

void B1::mouseMoveEvent(QMouseEvent* event)
{
    if (event->pos().x() >= 10 && event->pos().x() <= width() - 10)
    {
        setCursor(Qt::SizeHorCursor);
        if (event->pos().x() >= (left->width() - 500) && event->pos().x() <= width() - (right->width() - 500))
        {
            if (event->buttons() == Qt::LeftButton)
            {
                left->setGeometry(0, 0, event->x(), height());
                right->setGeometry(left->width(), 0, width() - left->width(), height());
            }
        }
    }
    else
    {
        setCursor(Qt::ArrowCursor);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读