Learning Qt 5! (5):布局管理器

Qt 学习之路 2(11):布局管理器

先看看main()代码:

// !!! Qt 5

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget window;
    window.setWindowTitle("Enter your age");

    /*引入了两个新的组件:QSpinBox和QSlider。QSpinBox就是只能输入数字的输入框,并且
    带有上下箭头的步进按钮。QSlider则是带有滑块的滑竿。*/
    QSpinBox *spinBox = new QSpinBox(&window);
    QSlider *slider = new QSlider(Qt::Horizontal, &window);
    //使用setRange()函数设置其范围。
    spinBox->setRange(0, 130);
    slider->setRange(0, 130);

    //将 slider 的valueChanged()信号同 spinBox 的setValue()函数相连。
    QObject::connect(slider, &QSlider::valueChanged, spinBox, &QSpinBox::setValue);
    /*QSpinBox有两个信号:void valueChanged(int)和void valueChanged(const QString &)。
    当使用&QSpinBox::valueChanged取函数指针时,编译器不知道应该取哪一个函数的地址,因
    此报错。解决方法就是,我们创建一个函数指针,这个函数指针参数指定为 int。*/
    void (QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;
    //将这个函数指针作为 signal,与 QSlider 的函数连接:
    QObject::connect(spinBox, spinBoxSignal, slider, &QSlider::setValue);
    spinBox->setValue(35);

    /*创建一个QHBoxLayout对象,即布局管理器。然后将两个组件都添加到这个布局管理器,并
    且把该布局管理器设置为窗口的布局管理器。*/
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(spinBox);
    layout->addWidget(slider);
    window.setLayout(layout);

    window.show();

    return app.exec();
}

Qt 5 中的5种布局管理器,上述代码中使用的是QHBoxLayout(按照水平方向从左到右布局):

QHBoxLayout:按照水平方向从左到右布局;
QVBoxLayout:按照竖直方向从上到下布局;
QGridLayout:在一个网格中进行布局,类似于 HTML 的 table;
QFormLayout:按照表格布局,每一行前面是一段文本,文本后面跟随一个组件(通常是输入框),类似 HTML 的 form;
QStackedLayout:层叠的布局,允许我们将几个组件按照 Z 轴方向堆叠,可以形成向导那种一页一页的效果。

Q&A:
1.博主 我想知道 为什么 把

QWidget window;
window.setWindowTitle(“Enter your age”);

的window的类型改成 QMainWindow之后添加上去的两个部件重叠在一起了?QMainWindow不是QWidget的派生类么?

QMainWindow 的确是继承自 QWidget,但是它同时添加了自己的 layout,正因为有 layout 的存在,所以你需要使用 setCentralWidget() 函数把一个 QWidget 设置为中心的组件,而不是把一个个的子组件用自己的 layout 添加进去(因为 QMainWindow 已经有了默认的 layout,你自己的 layout 才会不起作用)。

2.按照之前的对象树的概念,为什么不是传入new QHBoxLayout(&window)呢?而是使用空参数的折构方法呢?

这是因为调用 setLayout() 函数的时候,如果这个 layout 不属于调用 setLayout() 函数的组件,则会自动设置为该组件。因此,你可以在 new 的时候就添加 parent 指针参数,也可以通过 setLayout() 设置。需要注意的是,如果构造函数添加了 parent 指针,后来又调用了 setLayout() 函数,如果二者不相同,则 setLayout() 函数设置的 parent 指针会覆盖构造函数传入的。

3.window,spinBox,slider这几个,什么时候该用指针,什么时候不该用呢?还有layout。。。

所有 QObject 的子类,因为 Qt 可以利用 parent 指针进行半自动化管理,因此建议使用指针。因为由于QObject 的拷贝构造函数等都是私有的,只能以指针的形式保存到容器中,因而指针更为方便。容器之类一般都是使用栈。不过这一点并不是绝对的,还是具体情况具体分析最好。

4.如果将void (QSpinBox:: *spinBoxSignal)(int) = &QSpinBox::valueChanged;这个函数指针用以下2句代码替换:

void (*spinBoxSignal)(int);
spinBoxSignal = &QSpinBox::valueChanged;

运行时就会指示:
error: no matches converting function ‘valueChanged’ to type ‘void (*)(int)’spinBoxSignal = &QSpinBox::valueChanged;
为什么会这样呢?

成员函数指针需要类实例去调用,因此成员函数指针和全局函数指针是不兼容的。你修改之后的代码:void (*spinBoxSignal)(int);定义了一个全局函数指针,是不能用成员函数 QSpinBox::valueChanged 进行赋值的,这也就是为什么编译器会报无法转换的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值