动态布局
2016-03-21 13:59
253 查看
这次,我们学习下面几个问题:
动态变更布局
QQueue的使用
组件之间的联动
参考来源:http://doc.qt.nokia.com/latest/layouts-dynamiclayouts.html,最终布局如图所示,并实现相关的动态变更。
一个dialog分为三个部分;
第一部分是一个GroupBox,里面是GridLayout(2,2)的方式,按Rotate Widget的按钮,顺时针旋转里面组件的位置。这四个组件是可以联动的,一个修改,另外三个显示值也跟随修改。此四个组件存放在QQueue中。
第二部分也是一个GroupBox,根据comboBox的选择,确定第三部分的位置。
第三部分是DialogButtonBox,有两个Dialog的button,close和help,增加一个旋转按钮“Rotate Widget”
一、创建程序主体,采用dialog的方式。在之前,我们讨论过dialog的主体如何创建,不再重复。MyDialog类继承QDialog。
二、旋转第一部分的四个组件
在mydialog.h:
private:
/* 第一部分的组件*/
QGroupBox *rotableGroupBox;
QQueue<QWidget *> rotableWidgets;
QGridLayout *rotableLayout;
在mydialog.cpp:
void MyDialog :: createRotableGroupBox()
{
rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));
rotableWidgets.enqueue(new QSpinBox);
rotableWidgets.enqueue(new QSlider);
rotableWidgets.enqueue(new QDial);
rotableWidgets.enqueue(new QProgressBar);
int n = rotableWidgets.count();
/*这里设置联动,注意以前第三个参数我们通常使用this,表示调用当前类的函数,对于联动,我们需要调用其他组件的函数,所以这里为其他组件,第一动,导致第二动,第二动,导致第三动,一直所有的都改变,否则一直传递下去*/
for (int i = 0; i < n; ++i) {
connect(rotableWidgets[i], SIGNAL(valueChanged(int)),rotableWidgets[(i+1)%n], SLOT(setValue(int)));
}
rotableLayout = new QGridLayout;
rotableGroupBox ->setLayout(rotableLayout);
rotateWidgets();
}
void MyDialog :: rotateWidgets() //这也同时是slot函数
{
//删除面板上的组件
foreach(QWidget * widget ,rotableWidgets)
rotableLayout->removeWidget(widget);
//删除head的的item,并将其加到最后,这样我们实现旋转。
rotableWidgets.enqueue(rotableWidgets.dequeue());
rotableLayout->addWidget(rotableWidgets[0],1,0);
rotableLayout->addWidget(rotableWidgets[1],1,1);
rotableLayout->addWidget(rotableWidgets[2],0,1);
rotableLayout->addWidget(rotableWidgets[3],0,0);
}
三、横向/纵向模式,自从iphone引入了重量感应器后,一个程序出现横向和纵向的排版,通常都是一样,但是有些程序也提供不同的布局。这里给了一个例子。
在mydialog.h:
private:
/* 第二部分的组件*/
QGroupBox *optionsGroupBox;
QGridLayout *optionsLayout;
QLabel *buttonsOrientationLabel;
QComboBox *buttonsOrientationComboBox;
/* 第三部分的组件*/
QDialogButtonBox *buttonBox;
QPushButton *closeButton;
QPushButton *helpButton;
QPushButton *rotateWidgetsButton;
在mydialog.cpp:
void MyDialog :: buttonsOrientationChanged(int index)
{
//由于我们改变排版,因此新的布局的size可能比原来的小,但是widget的resize比它最小的widget大小。通过setMinmumSize(0,0)来reset。简单来讲,如果我们每次修改布局都希望不受限制设定新的尺寸,reset最小尺寸。
setMinimumSize(0,0);
//方向有两个参数Qt::Horizontal 0x1, Qt::Vertical 0x2,在我们这里0为Horizontal,1为vertical。
Qt::Orientation orientation = Qt::Orientation(index + 1);
if(buttonBox->orientation() == orientation ) //方向没有改变
return;
mainLayout->removeWidget(buttonBox); //删除原来的buttonBox,后面在其他位置加上
int spacing = mainLayout->spacing();
QSize oldSizeHint = buttonBox->sizeHint() + QSize(spacing,spacing);
buttonBox->setOrientation(orientation);
QSize newSizeHint = buttonBox->sizeHint() + QSize(spacing,spacing);
if(orientation == Qt::Horizontal){
mainLayout->addWidget(buttonBox,2,0); //新的位置,放置最下面
resize(size() + QSize(-oldSizeHint.width(), newSizeHint.height()));//设置合适的大小
}else{
mainLayout->addWidget(buttonBox,0,3,2,1); //新的位置,放置最右面
resize(size() + QSize(newSizeHint.width(), -oldSizeHint.height())); //设置合适的大小
//resize(minimumSize().width(), minimumSize().height()); 这样可以得到最紧凑的排列,但是我们希望其他部分不变动,所以我们根据计算进行排版。
}
}
四、对于第二部分:第二部分只有两个组件,占空间比较小,当我们将dialog拉框的时候,我们希望这两个组件都放置在最左边,右边以空白补充。如下,我们在GruiLayout中增加一个空白类。
//这里设置延伸的情况,我们希望后面空白将填满剩余的空间,所以设置第2列具有更高的延伸因子,如果我们希望第1列的combobox将填满剩余的俄空间,setColumnStretch(1,1),可以拉常dialog来看看效果。
optionsLayout->setColumnStretch(2,1);
五、Dialog的提供的缺省button。使用QDialogButtonBox * buttonBox,在里面我们加入两个系统button,Close和Help,以及一个自定义的button,如下
closeButton = buttonBox->addButton(QDialogButtonBox::Close);
helpButton = buttonBox -> addButton(QDialogButtonBox::Help);
rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widget"),QDialogButtonBox::ActionRole);
connect(rotateWidgetsButton,SIGNAL(clicked()),this,SLOT(rotateWidgets()));
connect(closeButton,SIGNAL(clicked()),this,SLOT(close()));
//close是系统的,即继承QDialog
connect(helpButton,SIGNAL(clicked()),this,SLOT(myhelp()));
//myhelp是自定的
动态变更布局
QQueue的使用
组件之间的联动
参考来源:http://doc.qt.nokia.com/latest/layouts-dynamiclayouts.html,最终布局如图所示,并实现相关的动态变更。
一个dialog分为三个部分;
第一部分是一个GroupBox,里面是GridLayout(2,2)的方式,按Rotate Widget的按钮,顺时针旋转里面组件的位置。这四个组件是可以联动的,一个修改,另外三个显示值也跟随修改。此四个组件存放在QQueue中。
第二部分也是一个GroupBox,根据comboBox的选择,确定第三部分的位置。
第三部分是DialogButtonBox,有两个Dialog的button,close和help,增加一个旋转按钮“Rotate Widget”
一、创建程序主体,采用dialog的方式。在之前,我们讨论过dialog的主体如何创建,不再重复。MyDialog类继承QDialog。
二、旋转第一部分的四个组件
在mydialog.h:
private:
/* 第一部分的组件*/
QGroupBox *rotableGroupBox;
QQueue<QWidget *> rotableWidgets;
QGridLayout *rotableLayout;
在mydialog.cpp:
void MyDialog :: createRotableGroupBox()
{
rotableGroupBox = new QGroupBox(tr("Rotable Widgets"));
rotableWidgets.enqueue(new QSpinBox);
rotableWidgets.enqueue(new QSlider);
rotableWidgets.enqueue(new QDial);
rotableWidgets.enqueue(new QProgressBar);
int n = rotableWidgets.count();
/*这里设置联动,注意以前第三个参数我们通常使用this,表示调用当前类的函数,对于联动,我们需要调用其他组件的函数,所以这里为其他组件,第一动,导致第二动,第二动,导致第三动,一直所有的都改变,否则一直传递下去*/
for (int i = 0; i < n; ++i) {
connect(rotableWidgets[i], SIGNAL(valueChanged(int)),rotableWidgets[(i+1)%n], SLOT(setValue(int)));
}
rotableLayout = new QGridLayout;
rotableGroupBox ->setLayout(rotableLayout);
rotateWidgets();
}
void MyDialog :: rotateWidgets() //这也同时是slot函数
{
//删除面板上的组件
foreach(QWidget * widget ,rotableWidgets)
rotableLayout->removeWidget(widget);
//删除head的的item,并将其加到最后,这样我们实现旋转。
rotableWidgets.enqueue(rotableWidgets.dequeue());
rotableLayout->addWidget(rotableWidgets[0],1,0);
rotableLayout->addWidget(rotableWidgets[1],1,1);
rotableLayout->addWidget(rotableWidgets[2],0,1);
rotableLayout->addWidget(rotableWidgets[3],0,0);
}
三、横向/纵向模式,自从iphone引入了重量感应器后,一个程序出现横向和纵向的排版,通常都是一样,但是有些程序也提供不同的布局。这里给了一个例子。
在mydialog.h:
private:
/* 第二部分的组件*/
QGroupBox *optionsGroupBox;
QGridLayout *optionsLayout;
QLabel *buttonsOrientationLabel;
QComboBox *buttonsOrientationComboBox;
/* 第三部分的组件*/
QDialogButtonBox *buttonBox;
QPushButton *closeButton;
QPushButton *helpButton;
QPushButton *rotateWidgetsButton;
在mydialog.cpp:
void MyDialog :: buttonsOrientationChanged(int index)
{
//由于我们改变排版,因此新的布局的size可能比原来的小,但是widget的resize比它最小的widget大小。通过setMinmumSize(0,0)来reset。简单来讲,如果我们每次修改布局都希望不受限制设定新的尺寸,reset最小尺寸。
setMinimumSize(0,0);
//方向有两个参数Qt::Horizontal 0x1, Qt::Vertical 0x2,在我们这里0为Horizontal,1为vertical。
Qt::Orientation orientation = Qt::Orientation(index + 1);
if(buttonBox->orientation() == orientation ) //方向没有改变
return;
mainLayout->removeWidget(buttonBox); //删除原来的buttonBox,后面在其他位置加上
int spacing = mainLayout->spacing();
QSize oldSizeHint = buttonBox->sizeHint() + QSize(spacing,spacing);
buttonBox->setOrientation(orientation);
QSize newSizeHint = buttonBox->sizeHint() + QSize(spacing,spacing);
if(orientation == Qt::Horizontal){
mainLayout->addWidget(buttonBox,2,0); //新的位置,放置最下面
resize(size() + QSize(-oldSizeHint.width(), newSizeHint.height()));//设置合适的大小
}else{
mainLayout->addWidget(buttonBox,0,3,2,1); //新的位置,放置最右面
resize(size() + QSize(newSizeHint.width(), -oldSizeHint.height())); //设置合适的大小
//resize(minimumSize().width(), minimumSize().height()); 这样可以得到最紧凑的排列,但是我们希望其他部分不变动,所以我们根据计算进行排版。
}
}
四、对于第二部分:第二部分只有两个组件,占空间比较小,当我们将dialog拉框的时候,我们希望这两个组件都放置在最左边,右边以空白补充。如下,我们在GruiLayout中增加一个空白类。
//这里设置延伸的情况,我们希望后面空白将填满剩余的空间,所以设置第2列具有更高的延伸因子,如果我们希望第1列的combobox将填满剩余的俄空间,setColumnStretch(1,1),可以拉常dialog来看看效果。
optionsLayout->setColumnStretch(2,1);
五、Dialog的提供的缺省button。使用QDialogButtonBox * buttonBox,在里面我们加入两个系统button,Close和Help,以及一个自定义的button,如下
closeButton = buttonBox->addButton(QDialogButtonBox::Close);
helpButton = buttonBox -> addButton(QDialogButtonBox::Help);
rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widget"),QDialogButtonBox::ActionRole);
connect(rotateWidgetsButton,SIGNAL(clicked()),this,SLOT(rotateWidgets()));
connect(closeButton,SIGNAL(clicked()),this,SLOT(close()));
//close是系统的,即继承QDialog
connect(helpButton,SIGNAL(clicked()),this,SLOT(myhelp()));
//myhelp是自定的
相关文章推荐
- C#读取web.config配置文件内容
- 一分钟搭建Webpack+react+es6框架
- 可重入函数
- Java中的static关键字解析
- 自定义时间选择器的实现(非picker)
- Hadoop2.7.2的部署
- Java开发工具中Compile、Make和Build的区别
- [BZOJ3083]遥远的国度(链剖+dfs序)
- Java开发工具中Compile、Make和Build的区别
- MySQL中的共享锁与排他锁
- 串口控制小夜灯
- LVS之VS/DR搭建web集群实战!!!
- /sys/block/xxx/queue/中的max_hw_sectors_kb 和 max_sectors_kb
- Device Tree(三):代码分析
- iOS中的滤镜
- 快速掌握Lua 5.3 —— 扩展你的程序 (2)
- 魔鬼牧师游戏--简单工厂的改进
- 自定义布局
- halcon小例:ORC识别
- 怎么实现EDIUS中添加的图片素材一样大