in ,

Introduction to SerenityOS GUI programming, Hacker News

    

This post will give you a quick intro to the basics of GUI programming for SerenityOS .


Hello friends! Let’s cut to the chase and go straight to some code!

The smallest possible GUI program

   #include  
 int  
 (main)  int  (char)   argv )   {     
 GUI   ::  Application 
 app  (  argc  ,   argv        return  app   exec  ();       

The above program creates a GUI :: Application object and enters the main event loop. That’s it. It then does nothing until you interrupt it with ^ C .

Details: GUI :: Application is created on the stack in main () and will exist throughout the program's lifetime. It can be reached globally as GUI :: Application :: the () . Let’s add a window!

   #include  #include   
 int  
 (main)  int  (char)   argv )   {     
 GUI   ::  Application 
 app  (  argc  ,   argv       
 auto  (window)  (GUI)         
 window  -> 
set_title
(

) My window! ";       
 window  -> 

set_rect ( 300 , );     

 window  -> 

show ();      return app exec ();

The above program creates a window and sets its title, screen location and size. It then displays the window on screen and enters the main event loop.

Details: (Windows are represented by GUI :: Window , which inherits from Core :: Object , a foundational building block of the Serenity userspace programming environment. Core :: Object is reference-counted, and is constructed using its construct () helper. The value you get back is a reference-counting smart pointer, in this case a NonnullRefPtr Let’s add a button!

   #include  #include 

#include

 int  
 (main)  int  (char)   argv )   {     
 GUI   ::  Application 
 app  (  argc  ,   argv       
 auto  (window)  (GUI)         
 window  -> 
set_title
(

) My window! ";       
 window  -> 

set_rect ( 300 , );     

 auto 
 &   button = (window)  ->  (set_main_widget)    (:: ) ()  (;      
 button   on_click = [&]  {         
 app  (quit ) ();      ;       
 window  -> 

show ();      return app exec ();

The above program creates a GUI :: Button widget and makes it the main widget of the window. We install a callback for the on_click hook that calls GUI :: Application :: quit () . Clicking the button exits the event loop and terminates the program.

Details: A window's main widget is the root of its widget tree. It fills up all the space in the window (and follows along with resizing.) The main widget is owned by the window. Let's use a layout to have more than one widget!

   #include  #include Example 3 #include 

#include #include #include

 int  
 (main)  int  (char)   argv )   {     
 GUI   ::  Application 
 app  (  argc  ,   argv       
 auto  (window)  (GUI)         
 window  -> 
set_title
(

) My window! ";       
 window  -> 

set_rect ( 300 , );     

 window  -> 

show ();     

 auto 
 &  widget 
= (window) -> (set_main_widget) (:: () ();      widget set_fill_with_background_color ()      widget set_layout (: (VerticalBoxLayout) >      widget (add ) (: (Label) ( ( “Hello!” ;      widget (add ) (: (Button) > ( “Friends!” ;      return app exec ();

The above program uses a generic GUI :: Widget as the window's main widget, and assigns a layout to it. LibGUI currently offers two layouts: HorizontalBoxLayout and VerticalBoxLayout Once a layout is assigned to a widget, it will manage the location and shape of that widget’s immediate children.

We add two children to the main widget, a label and button, causing them to get laid out vertically in insertion order, label up top, button down below.

Details: Using the layout system is optional (but preferred due to its simplicity.) It's also possible to place and size children directly by calling `GUI :: Widget :: set_relative_rect (x, y, width, height) on them. To build complex user interfaces, layouts can be nested arbitrarily by adding layouts to the children of the main widget, etc. Widgets have size policies and preferred size that can be used to adjust layout. Widgets own their children. Okay, let's make a custom widget!

For our final example, let’s make something a little more advanced…

   #include  #include  #include  #include   
 class   MyWidget   (final  :   GUI   (::   {     C_OBJECT   (  MyWidget  ; : private:       MyWidget  ()  {}  )     
 virtual   paint_event  (  GUI) :  (PaintEvent)  &     (override) ;      
 virtual   (mousedown_event ) (  GUI) :  (MouseEvent)  &     (override) ;       
 Vector   )    m_points ;    void  (MyWidget) :   paint_event   ( GUI   )  {     
 GUI   ::  Painter  painter   (  (this );       painter   fill_rect   (  rect    Gfx   ::  Color  ::  White        painter   draw_text  (  rect    :) :) ,  Gfx   ::   (TextAlignment)  ::   Center  );        Gfx   ::   Point  last_point  ;       ( (  &   point  :  (m_points )              painter   (draw_line ) ( last_point   (point ) ,   Gfx  :  (Red) ;           last_point  =  ;          void  (MyWidget) :   mousedown_event  ( GUI  (MouseEvent)  event    {      m_points   (append ) ()  (position   ());       update  () ;   
 int  
 (main)  int  (char)   argv )   {     
 GUI   ::  Application 
 app  (  argc  ,   argv       
 auto  (window)  (GUI)         
 window  -> 
set_title
(

) My window! ";       
 window  -> 

set_rect ( 300 , );     

 window  -> 

show ();     

 window  -> 
set_main_widget (MyWidget) ();      return app exec ();

The above program defines a custom GUI :: Widget subclass called MyWidget . It implements its own behavior for the mousedown and paint events. When you click somewhere in the window, it will draw a line from the last place you clicked to the new place you clicked.

The SerenityOS GUI is event-driven, and most of the logic is about widgets handling events. The following virtual functions from GUI :: Widget can be overridden to handle specific events:

   virtual  void   change_event   GUI   Event  ;      
 virtual   child_event 
( Core : (ChildEvent) &     

 virtual   click_event  (  GUI) :  (MouseEvent)  &       
 virtual   context_menu_event   (  GUI) : (ContextMenuEvent) 
 &       
 virtual   doubleclick_event  (  GUI) : (MouseEvent)  &       
 virtual   drag_move_event   (  GUI) : (DragEvent)  &       
 virtual   drop_event  (  GUI) :  DropEvent       
 virtual 

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

GIPHY App Key not set. Please check settings

This PS5 Design 'Leak' Is Hilariously Fake – But Boy, Is It Exotic, Crypto Coins News

This PS5 Design 'Leak' Is Hilariously Fake – But Boy, Is It Exotic, Crypto Coins News

Google cancels I / O developer conference amid coronavirus concerns, Ars Technica

Google cancels I / O developer conference amid coronavirus concerns, Ars Technica