From c21c3b0befeb46a51b6bf3758ffa30813bea0ff0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:22 +0100 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- ml/dlib/examples/gui_api_ex.cpp | 231 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 ml/dlib/examples/gui_api_ex.cpp (limited to 'ml/dlib/examples/gui_api_ex.cpp') diff --git a/ml/dlib/examples/gui_api_ex.cpp b/ml/dlib/examples/gui_api_ex.cpp new file mode 100644 index 000000000..4d947b756 --- /dev/null +++ b/ml/dlib/examples/gui_api_ex.cpp @@ -0,0 +1,231 @@ +// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt +/* + + This is an example illustrating the use of the gui api from the dlib C++ Library. + + + This is a pretty simple example. It makes a window with a user + defined widget (a draggable colored box) and a button. You can drag the + box around or click the button which increments a counter. +*/ + + + + +#include +#include +#include + + +using namespace std; +using namespace dlib; + +// ---------------------------------------------------------------------------- + +class color_box : public draggable +{ + /* + Here I am defining a custom drawable widget that is a colored box that + you can drag around on the screen. draggable is a special kind of drawable + object that, as the name implies, is draggable by the user via the mouse. + To make my color_box draggable all I need to do is inherit from draggable. + */ + unsigned char red, green,blue; + +public: + color_box ( + drawable_window& w, + rectangle area, + unsigned char red_, + unsigned char green_, + unsigned char blue_ + ) : + draggable(w), + red(red_), + green(green_), + blue(blue_) + { + rect = area; + set_draggable_area(rectangle(10,10,400,400)); + + // Whenever you make your own drawable widget (or inherit from any drawable widget + // or interface such as draggable) you have to remember to call this function to + // enable the events. The idea here is that you can perform whatever setup you + // need to do to get your object into a valid state without needing to worry about + // event handlers triggering before you are ready. + enable_events(); + } + + ~color_box ( + ) + { + // Disable all further events for this drawable object. We have to do this + // because we don't want any events (like draw()) coming to this object while or + // after it has been destructed. + disable_events(); + + // Tell the parent window to redraw its area that previously contained this + // drawable object. + parent.invalidate_rectangle(rect); + } + +private: + + void draw ( + const canvas& c + ) const + { + // The canvas is an object that represents a part of the parent window + // that needs to be redrawn. + + // The first thing I usually do is check if the draw call is for part + // of the window that overlaps with my widget. We don't have to do this + // but it is usually good to do as a speed hack. Also, the reason + // I don't have it set to only give you draw calls when it does indeed + // overlap is because you might want to do some drawing outside of your + // widget's rectangle. But usually you don't want to do that :) + rectangle area = c.intersect(rect); + if (area.is_empty() == true) + return; + + // This simple widget is just going to draw a box on the screen. + fill_rect(c,rect,rgb_pixel(red,green,blue)); + } +}; + +// ---------------------------------------------------------------------------- + +class win : public drawable_window +{ + /* + Here I am going to define our window. In general, you can define as + many window types as you like and make as many instances of them as you want. + In this example I am only making one though. + */ +public: + win( + ) : // All widgets take their parent window as an argument to their constructor. + c(*this), + b(*this), + cb(*this,rectangle(100,100,200,200),0,0,255), // the color_box will be blue and 101 pixels wide and tall + mbar(*this) + { + // tell our button to put itself at the position (10,60). + b.set_pos(10,60); + b.set_name("button"); + + // let's put the label 5 pixels below the button + c.set_pos(b.left(),b.bottom()+5); + + + // set which function should get called when the button gets clicked. In this case we want + // the on_button_clicked member to be called on *this. + b.set_click_handler(*this,&win::on_button_clicked); + // Alternatively, if you have a compiler which supports the lambda functions from the + // new C++ standard then you can use a lambda function instead of telling the click + // handler to call one of the member functions. So for example, you could do this + // instead (uncomment the code if you have C++0x support): + /* + b.set_click_handler([&](){ + ++counter; + ostringstream sout; + sout << "Counter: " << counter; + c.set_text(sout.str()); + }); + */ + // In general, all the functions which register events can take either member + // functions or lambda functions. + + + // Let's also make a simple menu bar. + // First we say how many menus we want in our menu bar. In this example we only want 1. + mbar.set_number_of_menus(1); + // Now we set the name of our menu. The 'M' means that the M in Menu will be underlined + // and the user will be able to select it by hitting alt+M + mbar.set_menu_name(0,"Menu",'M'); + + // Now we add some items to the menu. Note that items in a menu are listed in the + // order in which they were added. + + // First let's make a menu item that does the same thing as our button does when it is clicked. + // Again, the 'C' means the C in Click is underlined in the menu. + mbar.menu(0).add_menu_item(menu_item_text("Click Button!",*this,&win::on_button_clicked,'C')); + // let's add a separator (i.e. a horizontal separating line) to the menu + mbar.menu(0).add_menu_item(menu_item_separator()); + // Now let's make a menu item that calls show_about when the user selects it. + mbar.menu(0).add_menu_item(menu_item_text("About",*this,&win::show_about,'A')); + + + // set the size of this window + set_size(430,380); + + counter = 0; + + set_title("dlib gui example"); + show(); + } + + ~win( + ) + { + // You should always call close_window() in the destructor of window + // objects to ensure that no events will be sent to this window while + // it is being destructed. + close_window(); + } + +private: + + void on_button_clicked ( + ) + { + // when someone clicks our button it will increment the counter and + // display it in our label c. + ++counter; + ostringstream sout; + sout << "counter: " << counter; + c.set_text(sout.str()); + } + + void show_about( + ) + { + message_box("About","This is a dlib gui example program"); + } + + unsigned long counter; + label c; + button b; + color_box cb; + menu_bar mbar; +}; + +// ---------------------------------------------------------------------------- + +int main() +{ + // create our window + win my_window; + + + // wait until the user closes this window before we let the program + // terminate. + my_window.wait_until_closed(); + + return 0; +} + +// ---------------------------------------------------------------------------- + +// Normally, if you built this application on MS Windows in Visual Studio you +// would see a black console window pop up when you ran it. The following +// #pragma directives tell Visual Studio to not include a console window along +// with your application. However, if you prefer to have the console pop up as +// well then simply remove these #pragma statements. +#ifdef _MSC_VER +# pragma comment( linker, "/entry:mainCRTStartup" ) +# pragma comment( linker, "/SUBSYSTEM:WINDOWS" ) +#endif + +// ---------------------------------------------------------------------------- + -- cgit v1.2.3