概述
使用Qt做过UI的一定对QHBoxLayout, QVBoxLayout, 和QGridLayout这三个最重要也最常使用的layout managers非常熟悉。那么在QML中又是如何控制和管理UI布局的呢?那么我们这篇文章就为大家介绍这些基础知识。
首先,QML同样允许大家使用硬编码的方式将位置数值直接写到代码中,但是这样做首先难以适应UI的调整,其次代码维护起来也很困难。因此我们不推荐这样做。推荐大家使用的是以下三种布局管理器:Row,、Column、Grid,以及使用Anchor进行布局。
Row
QML 中的 Row 元素会将其子控件都排列在同一行,相互不重叠。我们还可以使用它的spacing 属性来定义子控件之间的距离。比如下列代码就会产生如图所示的效果:
Row {
* E0 b/ }3 v5 A1 y4 w spacing:
2
+ v' q$ M: B, u$ b3 J Rectangle { color:
"red"; width:
50; height:
50 }
+ R7 k3 t6 W2 N
Rectangle { color:
"green"; width:
20; height:
50 }
2 a$ ^1 S1 B4 z$ p* @1 R& _ Rectangle { color:
"blue"; width:
50; height:
20 }
- u4 a6 V; S* g! p# f
}
Column
QML 中的 Column元素会将其子控件都排列在同一列,相互不重叠。我们还可以使用它的spacing 属性来定义子控件之间的距离。比如下列代码就会产生如图所示的效果:
Column {
. x' J! g% G% x spacing:
2
5 B" ?1 H {( g7 n Rectangle { color:
"red"; width:
50; height:
50 }
9 z; _: k2 c S, i0 f
Rectangle { color:
"green"; width:
20; height:
50 }
. B; w0 A7 M. z- F% y3 D0 m
Rectangle { color:
"blue"; width:
50; height:
20 }
) m& c+ t+ J; C
}
Grid
QML 中的 Grid元素会将其子控件都均匀地排列在一个网格内,相互不重叠,每一个子控件都被放置在一个网格单元的(0,0)位置,也就是左上角。Grid的rows 和columns属性定义网格的行数和列数,列数默认是4。我们还可以使用Grid的spacing 属性来定义网格单元之间的距离,这里注意水平和垂直方向的spacing都是一样的。比如下列代码就会产生如图所示的效果:
Grid {
- {/ d t" b# Q$ G columns:
3 ]* l6 ]: ]* @9 { m
spacing:
2; \( q5 L: L" y
Rectangle { color:
"red"; width:
50; height:
50 }
d$ {7 ]8 A& V0 E7 F8 z Rectangle { color:
"green"; width:
20; height:
50 }
2 S% Q( D( y* x) K3 ]
Rectangle { color:
"blue"; width:
50; height:
20 }
+ B. Y! y1 z; D: _1 a/ y Rectangle { color:
"cyan"; width:
50; height:
50 }
2 K2 }- |* ^3 _6 T: w" N0 | Rectangle { color:
"magenta"; width:
10; height:
10 }
7 p7 Q7 {5 \& ~/ D) ^( ^- ?3 Y+ n
}
0 P# J+ j/ i f" u4 ^# x# T混合应用
我们还可以将Grid、Row 和 Column 进行混合应用。比如下面的代码会产生如图所示的效果:
Column {
8 m9 u8 o8 B' ?! O spacing:
2: E6 M! g2 W" N4 a' ?5 b3 l( r. v
Rectangle { color:
"red"; width:
50; height:
50 }
) I8 Q# S2 \1 e' l5 O$ w: F
Row {
+ {* S- ], h4 d! o& ~/ C' M1 x( J
spacing:
29 Q' n: j2 r/ t& X) @% C* r
Rectangle { color:
"yellow"; width:
50; height:
50 }
1 ^+ q" y: a: ^! m
Rectangle { color:
"black"; width:
20; height:
50 }
8 c) _$ @3 ^" n3 X( c Rectangle { color:
"blue"; width:
50; height:
20 }
/ ?; c8 T6 n _4 R. p# O }
% z" c; U& r7 o Rectangle { color:
"green"; width:
20; height:
50 }
- D& C! l! s& ]
}
$ B4 @8 D1 I( J3 F. Y+ S
Anchor
以上方法进行排列是不重叠的,而anchor通俗的说是当前图形相对于某一图形的位置(可重叠)
每一个item 都可以被认为具有 7 条隐藏的“anchor lines":left、 horizontalCenter、 right、 top、 verticalCenter、baseline、以及bottom,如下图所示:
····
其中baseline是指的文本所在的线,在上图中并未标出,如果item没有文字的话baselinw就和top的位置是相同的。
$ l8 M' r1 {3 Q% m: A除此之外,Anchor系统还提供了margins 和offsets。margins 是指一个item和外界之间所留有的空间,而offsets 则可以通过使用 center anchor lines来进行布局。如下图所示
·····
使用 QML anchoring系统,我们可以定义不同items之间的anchor lines之间的关系。例如:
Rectangle { id: rect1; ... }6 @1 J5 L- T; b2 D% R7 J8 P" t; l
Rectangle { id: rect2; anchors.left: rect1.right; anchors.leftMargin: 5; ... }
·····
我们还可以使用多个anchors:
Rectangle { id: rect1; ... }
h3 R; Z" v5 Q& H, KRectangle { id: rect2; anchors.left: rect1.right; anchors.top: rect1.bottom; ... }
·····
通过定义多个水平或垂直的anchors,我们还可以控制item的大小,例如:
Rectangle { id: rect1; x: 0; ... }
7 {( d2 X5 }% @8 IRectangle { id: rect2; anchors.left: rect1.right; anchors.right: rect3.left; ... }
) t+ b& j w j; A, A& k2 fRectangle { id: rect3; x: 150; ... }
·····
注意:出于效率方面的考虑,我们只允许对一个item的邻居和之接父亲使用anchor定义。比如下面的定义是不合法的:
4 q8 s5 W0 k8 g8 K; t" ]4 S2 aItem {+ Q, s) P% Y& _
id: group1
- d# P4 i2 j! t; O/ @ Rectangle { id: rect1; ... }8 c3 k" _' x7 D" o
}' R; w* `+ C2 W6 s/ c5 Z
Item {
2 U5 Q3 L# S" x& N! g id: group2
! U7 T$ b+ o) S& T" J Rectangle { id: rect2; anchors.left: rect1.right; ... } // invalid anchor!" Q' w# A7 D8 ]4 f- B) r
}
/ j. t, w( A8 Q( X! W' m. P