界面事件5 E& E$ \, {) a4 [3 t! A
之前和大家共享了一些基本的操作,这章会给大家共享下界面使用的一些小技巧及方法。7 c9 r" i! T# S3 X
除去现成控件的事件外,不知道大家有没有考虑过其他一些界面的实现方式,例如,类似手机下滑菜单,或者上滑菜单,再比如一个动态背景。或者自己做的地图的量算尺子。 N: v) D* M" }3 s. }. h
这些方法都涉及到界面的滑动事件或者界面的定时刷新事件又或者点击事件之类。TouchGFX给大家提供了UIEventListener类用于事件监听。
' A5 g" k! `0 U1 p" F此类为用户界面事件(即由用户与设备交互生成的事件)声明处理程序接口。除系统计时器刻度外,所有其他与用户界面设备外围设备(显示器,按键等)无关的其他系统事件均不属于该界面。
! t% ?% m" o F8 i0 |下方是类中函数的介绍。1 H7 |6 r) k+ D0 H& ?
5 s& K: C4 H: I' f% J6 K9 K5 p
; I, w7 n3 b( C& C* b; B1 E' W
; o- a+ L S& o1 B% ~1 s' Y6 V4 [. |2 X e: q
UIEventListener类在我们创建窗口界面时该类已经继承过来了,实际上在view类中并没有这些方法的实现,所以需要自己根据需要实现方法。
) y3 e' \9 y+ a之后会给大家展示例子。
; ?9 V! e! A- y, x* I9 x
; {8 s4 }6 }6 [" r! f' l8 `0 n! K0 C. Z+ x. k+ {- L' j
如意控件% I i1 M* [7 j/ K" f. O0 m
上面介绍了界面事件类,现在介绍修改控件的方法以及如何自定义控件,在正常的开发中,TouchGFX Designer提供的控件经常满足不了我们的需求,此时就需要动态的修改控件,或者自己定义控件。首先先介绍动态的修改控件。
" D6 t; v" p) Y3 m- Y, B2 J' K! J还记得第二章讲到的Base类吗,其中有个add()函数,该函数的作用是在窗口上添加一个控件,这就是修改的一种,除此之外,还可以使用控件自身的属性进行更改,例如换图片,移动,渐变,更改文字,具体的需要根据控件的API进行开发。但是需要注意的是控件更改后为了保证可以及时刷新,需要使用invalidate()函数。
( p# ]; g! U4 T. |5 S" _# z g6 `9 Z& c! K+ ^- V% T# w9 ^
' N3 |) D, g9 h$ R/ i; _7 B9 o
Container7 R q% U+ Q' {) j- }( \9 L) a
Container容器,容器这个控件可以说在TouchGFX里使用量最大的控件,容器可以理解为一个透明的窗口,可以将其他控件放到容器里,再将容器作为单独控件放到窗口中,由此可以实现多个界面切换,或者也可以在容器中添加动画,或者事件监听。
# `) L1 c: P; [* ]添加位置: p4 }3 t: |1 g! _! b5 C P
可以在TouchGFX Designer的“容器”小部件组中找到“容器”。+ Q6 H1 r) } m% i/ L( B
* j3 d' S% X+ M6 k
. i) g0 |/ {, y) o7 G
9 H2 l- r5 E8 q% K7 z8 b8 \* t
您可以在用户代码中使用这些函数以及Container类中可用的其他函数。container1.invalidate()如果更改小部件的外观,请记住要通过调用来强制重绘。
0 [2 F. E- {6 t8 M4 E
: a* b+ O8 @' T! f' G$ ^& A1 f/ \. r! E9 ` d
重载容器- v0 m2 O( i# X4 a* s8 V* n* Z
该方法是将容器重载,在容器中创建自己了的逻辑,并且将子控件加入容器之中,针对自己的需要编写对外的接口。
. W# t6 q% O: V+ f8 f下面看一个例子。
8 ]4 a; ]2 U- ~* c# H- #ifndef SLIDEMENU_CONTAINER_HPP& `% d' L8 |9 w3 |0 W% ?
- #define SLIDEMENU_CONTAINER_HPP
i3 v* f: p0 o- h& b, o/ a - * Q, E5 a- u, y9 ?8 b
- #include <touchgfx/containers/Container.hpp>1 i% ~0 V5 ^& o& ]
- #include <touchgfx/widgets/Image.hpp>
! L# [. } P1 K - #include <touchgfx/containers/ListLayout.hpp>
5 ~$ w5 [0 T) T2 r' g d- M# [ - % c0 H4 g& A7 [, k' I$ U
- using namespace touchgfx;
0 L; [3 V4 \2 N
; ^" s1 j+ b% @: @) W- class SlideMenuContainer : public touchgfx::Container 继承容器% d# F( ?; O8 ]2 Q
- {7 Q+ u% w: L3 y( s4 s& M$ s
- public:
) a1 u# ]/ a0 `5 {3 }. g - SlideMenuContainer();
! E$ p7 d7 |, S7 E - virtual ~SlideMenuContainer();9 p7 Q- e! a8 ]
- 将事件添加到容器中,这部分的事件上述提到了. H6 ~3 C6 O% C7 c5 s
- virtual void handleTickEvent();
4 t6 a: q6 k& `0 }2 }( T; | - virtual void handleClickEvent(const touchgfx::ClickEvent& evt);
1 Q( R# W4 U( F5 a: D( N& q - virtual void handleDragEvent(const touchgfx::DragEvent& evt);
5 ^; X+ N& B: r: {: \ - virtual void handleGestureEvent(const touchgfx::GestureEvent& evt);
" P6 m, f! V% c2 e - ) z# H' [; q% ]
- 1 Z" `6 q7 U3 z7 {: b- M/ k) L
- uint8_t getSelectedScreen(). R2 L* j3 n" ?( x
- {6 S& G' d# M6 o# t' w' \
- return currentState;
8 ^8 R! C) ~- Q7 k1 P - } ]! j3 [ Q9 q+ V
- 对外设置回调函数的接口: ~# ]2 b" v6 i/ ?2 G+ ]
- void setMenuChangeEndedCallback(touchgfx::GenericCallback<const SlideMenuContainer&>& callback)) u1 V/ o5 `8 H# H' x
- {
9 Z; `7 [7 l* N. y- `! H - menuChangeAction = &callback;- ?5 a( w8 z) N5 N- B
- }1 c- i( W2 L9 {. V6 t
- private:
. H2 B$ {( v# W. V/ I: t - enum States
4 r: I4 A" G2 _& E3 u& x - {$ V. Z6 j* X1 |: a/ e7 I! \
- ANIMATE_COLLAPSE,
/ Y) U. a) S* h' T( q: d- w5 b" \ - ANIMATE_SHOW,
' F: ]" r+ z5 B, g8 g" S. S& C1 l! P - NO_ANIMATION) U1 u8 `; d0 y# J4 W/ g% p# S
- } currentState;% V$ e% l! D/ X0 M; U
- $ N; g% W, O+ S1 n3 T: s
- GenericCallback<const SlideMenuContainer&>* menuChangeAction;( L5 C& @/ i, l$ S
- : `# I$ ~, _2 i' }; E
- };( d! t' a5 a7 o7 s' Y* J
复制代码 % b5 B- y* k3 W3 B
接下来看一下cpp文件* y% l6 R/ F# B! |) o
- #include <gui/common/SlideMenuContainer.hpp>2 x. N" ?$ a) a3 e- E A) N% s
- #include <touchgfx/EasingEquations.hpp>2 A* e$ U1 w' N b* U" h4 n
- #include "BitmapDatabase.hpp"
3 T# R+ i- _8 [7 v1 w: V# k - #include <touchgfx/Color.hpp>; s/ X- J) U2 F; O7 r
: o* \7 Q# r+ t7 E% D- using namespace touchgfx;
; \ T5 ~+ Z3 I0 ~" p0 {1 F - % T5 ~6 H# l# m: h2 s0 Y# I
- SlideMenuContainer::SlideMenuContainer():7 p9 F( Q4 X5 C0 n# G
- currentState(NO_ANIMATION),0 I% ?1 M6 u$ p7 z G- x f% m3 [
- menuChangeAction(0)0 }( z$ {0 h% V7 f2 U/ C
- {* x- Y/ w9 V7 m" F- z! x* [
- touchgfx::Application::getInstance()->registerTimerWidget(this);. h( m" t0 u* i5 D$ c1 O
- setTouchable(true);
8 A1 m0 Y0 W% }) k; F4 p8 x7 f
3 ] o6 \& p( l1 Q- }
2 Z: N- U- o. e9 K% i - 9 e3 x6 e7 `# U/ o$ x3 w$ q" n+ I; a
- SlideMenuContainer::~SlideMenuContainer()0 l, i7 F) Y+ @8 k' |
- {
2 c' \. t0 N% W# Z7 A0 I4 I - touchgfx::Application::getInstance()->unregisterTimerWidget(this);% N. D$ t( r1 }0 @. b s
- }+ {, z7 P* d5 k' Q
4 P; J2 C8 t2 }5 m- void SlideMenuContainer::handleTickEvent()
2 x% D+ O1 q& _1 D, Z( y - {. ?( o3 @4 a' h4 R9 U
- }- G$ L7 _1 Q+ z# ?( P/ Z% j
- void SlideMenuContainer::handleClickEvent(const ClickEvent& evt)5 L ]8 J% f; Z j; q
- {' d) u3 B1 x; x6 ~# \" d
- 5 K: ~3 }6 ^- _* w0 f& |
- }
/ i, z- T- _) t) V1 l/ I# t: M9 L - void SlideMenuContainer::handleDragEvent(const DragEvent& evt)5 g8 t- ~; X( y, w
- {/ |$ b4 s% t8 [( r t/ f- ~
- //touchgfx_printf("SlideMenuContainer->getDeltaX :%d \r\n", evt.getDeltaX());3 O4 l, E' Q; N5 b/ O6 h
-
a( q: [" J0 f7 ]4 X" [$ R - }; W) d! ]1 A* m. v" e$ m4 H5 ^ `
- 手势响应函数,上滑收起下滑弹出& l6 z n4 _9 Q% J+ J0 n2 y
- void SlideMenuContainer::handleGestureEvent(const GestureEvent& evt)
2 o7 m8 ~( C3 P& s - {
$ B$ S$ O; X6 s8 m" \5 m - if (evt.getType() == evt.SWIPE_VERTICAL)
6 S0 n2 B$ s* R& s - {) C% C1 t' o; L9 g! i
- //touchgfx_printf("SlideMenuContainer->handleGestureEvent \r\n");. b- e/ J8 N( O1 Y/ f
- if (evt.getVelocity() < 0)) ^, J, {. W9 c
- {
; m, e$ T& M$ Q4 t0 u - currentState = ANIMATE_COLLAPSE; S1 J8 c4 ]* a! N( ?* E
- if (menuChangeAction && menuChangeAction->isValid())
! P% d$ n1 P; {4 B* ?) v( h! i - {0 o: {5 k$ V2 q! t% k1 R% C: a$ m
- menuChangeAction->execute(*this);% z$ }8 J* f) F* V7 o6 H/ c
- }
) o) |, z/ ?( P! E
2 L* A/ h0 ]0 u/ X; r3 _- }8 b/ b! |7 w" f$ e, `4 [* x$ v
- else if (evt.getVelocity() > 0)) ], L* I) R& v1 z/ y' d! U
- {
, u! _8 V( n. A" j8 e# }2 H - currentState = ANIMATE_SHOW;3 t! U" f) J+ d
- if (menuChangeAction && menuChangeAction->isValid())5 W8 V m! |- X7 D5 G5 b
- {* Q0 ~8 \; T1 _& `3 l. w* R! U3 E! L
- menuChangeAction->execute(*this);; }, @; j. [+ K+ c$ I
- }
1 z) l/ H+ T0 z' c3 ]( @ - }9 y. w6 d2 |8 i9 r
- }% t K1 Q- F% L3 ^& U, H
- }9 y+ x. v% o. a* {$ I( [
复制代码
$ _5 [. N+ a& o0 H6 N) [& ]自定义控件. L& m; L. w8 N( N1 E& m
除了之上的两种方法,如果需要更为具体的定义控件,或者想要节省空间可以选择自定义控件的方法。
- R' F- e. h5 r- U3 p9 _TouchGFX Designer当前不支持自定义窗口小部件的创建。因此,您将需要手动编写自定义小部件的代码,然后将小部件插入View的用户代码部分。
) ^& R) F7 _3 F W您可以通过扩展Widget类来创建自己的自定义窗口小部件。这样做需要在用户方面付出更多的努力,但也将完全控制小部件绘制的所有像素。您的自定义窗口小部件不一定使用任何现有的窗口小部件,而是通过指定像素的颜色来定义应如何绘制。自定义窗口小部件方法通常还将具有较小的内存占用空间,这在某些情况下非常重要。
3 E+ R. m t$ ~$ t- #ifndef QR_CODE_WIDGET_HPP
1 r7 Z' x, D$ r, g" D5 \. T - #define QR_CODE_WIDGET_HPP
B% Y: z( |( X1 J& Q" u - s6 _, I: c, v0 q
- #include <touchgfx/widgets/Widget.hpp>
) Q- w" T% ~ C+ g) G# ? - 以这种方法重载widget窗口,但是如果不是有特殊需要的话还是建议用容器去做。7 } l- f' h" d
- class QRCodeWidget : public touchgfx::Widget
1 x5 [0 f* o8 Z4 n - {
- B% y% w* ?6 e* u, a - public: Z' F) d" p3 p
- QRCodeWidget();! T4 t& d* u& Z) D; V$ `2 R; E
- : C; d& I& k3 A
- virtual void draw(const touchgfx::Rect& invalidatedArea) const;
9 Y: S4 V# w2 i - virtual touchgfx::Rect getSolidRect() const;
1 L4 |# E' m0 @+ H; ~; e4 Y- { - # R% o4 }" j' P" z% c. ]# Q
- void setQRCodeData(QRCodeData* data);4 c1 p' e2 j# s4 h, F3 v' t
- void setScale(uint8_t s);
8 i3 z( U, ~8 A; u
- A! y; f% \ b: X I- private:
, }/ ~4 B; F. F! q2 S - void updateSize();
+ _! F* Q, U3 c! T9 G$ Y - 3 k6 w; |3 C! O+ |
- QRCodeData* data;5 V' k' @+ w6 i6 b' k9 Z5 j
- uint8_t scale;
! W* _# Y9 G" S' w J7 a1 v - };" ^2 M: f. q0 Z0 E
- #endif/ P. e. s$ r' D! z* P# j0 |2 e
复制代码
$ L, s8 h' C8 e9 f) g4 w [具体类中的继承和重载请参照官方的API文档。
% Q) ]' {+ ~" V! m7 x( z: J
& T7 b9 d _: M) K图片等资源放置位置: o9 X5 w1 r- O% Y5 M8 C& q! B
好了说了这么多也可以大致的制作界面了,但是界面在开发过程中需要放入一些图片资源或者字库资源,这些地方放在TouchGFX\assets中,进入后可以看见放入资源的文件夹,但是注意图片格式为png。
" l; X W8 R. ~9 `
2 h8 w3 n$ Z, t [3 Q1 Y
) m3 n; ~/ F$ x$ A
0 q. H6 ]1 K# w* R; W' ]: ]! B8 r
2 j+ d- v7 b; Z) \4 G/ r+ B2 Z3 ]% h' I
到这里大体的框架都给大家介绍完毕了,之后会给大家介绍几个细节性的控件。4 |7 j" t- D9 s" o2 l" ^
————————————————7 |3 a' c ]' a P9 D- g$ ?
版权声明:空闲的程序员
& N# I" \! \) Q P( B
3 T" I3 F( J' M) S% P' |$ r1 {0 ]+ M
|