Skip to content

Commit

Permalink
MatWidget can strech now.
Browse files Browse the repository at this point in the history
Documentation progressing.
  • Loading branch information
sagi-z committed Jul 4, 2017
1 parent 8345380 commit d462450
Show file tree
Hide file tree
Showing 14 changed files with 367 additions and 43 deletions.
Binary file added doxygen_in/images/tutorials/tut_buttons.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
188 changes: 187 additions & 1 deletion doxygen_in/tut_buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,191 @@ It has text displayed on it and you attach a callback to know when it was presse

[TOC]

# Resizing the image with buttons {#tbtnsec1}
# Resizing the image with buttons {#buttons_s1}

Up to now we've been using WINDOW_AUTOSIZE to avoid stretching the image
when creating the window.

Let's write a small program which allows resizing of the image.

This will be done with 2 buttons "+" and "-" to increse and decrease the
size of the image respectively.

Here we also make an effort to keep a button location aligned to a
changing Canvas size. This won't be needed when you'll learn about the
layout managers.

Read the code and see the notes after it:

~~~~~~~{.cpp}
#include <canvascv/canvas.h>
#include <canvascv/widgets/button.h>
using namespace cv;
using namespace canvascv;
int main(int argc, char **argv)
{
--argc;
++argv;
if (! argc)
{
Canvas::fatal("Must get a path to an image as a parameter" , -1);
}
Mat orig = imread(argv[0]);
if (orig.empty())
{
Canvas::fatal(string("Cannot load image ") + argv[0], -2);
}
Mat image = orig;
namedWindow("Buttons", WINDOW_AUTOSIZE); // disable mouse resize
Canvas c("Buttons", orig.size());
c.enableStatusMsg(); // shows hover over button msgs
c.setMouseCallback();
double ratio = 1.;
auto rightSideButton = Button::create(c, // on the canvas
Point(image.cols - 20, 0), // top-right aligned on the screen
"+", // displayed on button
"increase size", // displayed during mouse hover
[&c, &orig, &image, &ratio](Widget *w) // callback can be a C++11 lambda
{
ratio += 0.05;
cv::resize(orig, image, Size(), ratio, ratio);
c.setImage(image); // change the image during waitKeyEx(0)
w->setLocation(Point(image.cols - 20, 0)); // keep aligned to top right without a layout manager
}
);
Button::create(c, // on the canvas
Point(0, 0), // top-left aligned on the screen
"-", // displayed on button
"decrease size", // displayed during mouse hover
[&c, &orig, &image, &ratio, rightSideButton](Widget*) // callback can be a C++11 lambda
{
ratio -= 0.05;
cv::resize(orig, image, Size(), ratio, ratio);
c.setImage(image); // change the image during waitKeyEx(0)
rightSideButton->setLocation(Point(image.cols - 20, 0)); // keep aligned to top right without a layout manager
}
);
int key = 0;
Mat out;
do
{
c.redrawOn(image, out); // draw the canvas on the image copy
c.imshow(out);
key = c.waitKeyEx(); // GUI and callbacks happen here
} while (key != 'q');
destroyAllWindows();
return 0;
}
~~~~~~~
Notes:
* We only need a variable to widgets we want to acces by code, so only
the rightSideButton has a variable, since we're manually aligning it to
the right on resizing.
* For a single image display, the best practice is to use
canvascv::Canvas::waitKeyEx() (default delay is 0).
#- Since during a zero delay, the Canvas is self updating, it needs to
know that the image has changed, and this is what
canvascv::Canvas::setImage is for.
* We using *enableStatusMsg* since we want the mouse hover over the
buttons to show out status message for it.
* This tutorial is using C++11 lambda expressions as callbacks, but
anything which has the void(Widget*) signature will work here.
* Here is an image decreased by this code:
@image html tut_buttons.png
<BR>

# Text alignment with buttons {#buttons_s2}

This will be more relevant on the *layout managers* tutorial, later on.

Currently, lets assume we have a button with 2 lines of text, a short
line and below it a long line.

We could want the text to be centered, or aligned to left, or aligned to
right.

The way to do this is with anchoring to the flow. If you set your anchor
at some point, then the text can't move the anchor and flows to the
other side. By doing that, it is aligned to the anchored side.

See this code:
~~~~~~~{.cpp}
#include <canvascv/canvas.h>
#include <canvascv/widgets/button.h>
using namespace cv;
using namespace canvascv;
int main(int argc, char **argv)
{
--argc;
++argv;
if (! argc)
{
Canvas::fatal("Must get a path to an image as a parameter" , -1);
}
Mat image = imread(argv[0]);
if (image.empty())
{
Canvas::fatal(string("Cannot load image ") + argv[0], -2);
}
namedWindow("ButTextAlign", WINDOW_AUTOSIZE); // disable mouse resize
Canvas c("ButTextAlign", image.size());
c.enableStatusMsg(); // shows hover over button msgs
c.setMouseCallback();
string buttonText = "short\n"
"a longer line";
auto b1 = Button::create(c, // on the canvas
Point(10,10), // top-right aligned on the screen
buttonText, // displayed on button
"centered"); // displayed during mouse hover
b1->setFlowAnchor(Widget::CENTER);
auto b2 = Button::create(c, // on the canvas
Point(10,110), // top-right aligned on the screen
buttonText, // displayed on button
"left aligned"); // displayed during mouse hover
b2->setFlowAnchor(Widget::LEFT);
auto b3 = Button::create(c, // on the canvas
Point(10,210), // top-right aligned on the screen
buttonText, // displayed on button
"right aligned");// displayed during mouse hover
b3->setFlowAnchor(Widget::RIGHT);
int key = 0;
Mat out;
do
{
c.redrawOn(image, out); // draw the canvas on the image copy
c.imshow(out);
key = c.waitKeyEx(); // GUI and callbacks happen here
} while (key != 'q');
destroyAllWindows();
return 0;
}
~~~~~~~
Notes:
* the canvascv::Widget::setFlowAnchor does the work here.
* Here is a possible outcome this code:
@image html tut_buttons_txt_alignment.png
<BR>

**That's all for this tutorial**
161 changes: 140 additions & 21 deletions doxygen_in/tut_checkboxes.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,162 @@
Using CheckBoxes (and RadioButtons and a SelectionBox) {#tutcheckbox}
======================================================

Giving the user multiple options and collecting them is common to
canvascv::CheckBoxes, canvascv::RadioButtons and canvascv::SelectionBox.

We going to take a look at using the *CheckBoxes* now. The concept is
similar to *RadioButtons* and the *SelectionBox*. In the tutorial about
layout managers we'll see an example frame with all of them.

[TOC]

# CheckBoxes with a callback {#checkbox_s1}

This is the normal and preffered way of working with widgets.

The *CheckBox* alows you to register a canvascv::Widget::CBUserSelection
callback, which will be called on user altering the widget selections.

You get the widget and an index to the item that changed. It is then up
to you to inspect the widget at that index (or other indexes).

See this code example, and read the notes after it:
~~~~~~~{.cpp}
#include <opencv2/highgui.hpp>
#include <canvascv/canvas.h>
#include <canvascv/widgets/checkboxes.h>
using namespace canvascv;
int main(int argc, char **argv)
{
--argc;
++argv;
if (! argc)
{
Canvas::fatal("Must get a path to an image as a parameter" , -1);
}
Mat image = imread(argv[0]);
if (image.empty())
{
Canvas::fatal(string("Cannot load image ") + argv[0], -2);
}
Canvas c("CheckBoxes", image.size());
c.enableScreenText();
c.setScreenText("Use q to exit");
namedWindow("CheckBoxes", WINDOW_AUTOSIZE);
c.setMouseCallback(); // optional for mouse usage (see also example_selectbox.cpp)
CheckBoxes::create(c, {
"Option1",
"Option2",
"Option3"
},
[&c](Widget *w, int)
{
CheckBoxes *checkBoxes = (CheckBoxes *) w;
c.setScreenText(CCV_STR(
"Option1:" << checkBoxes->isChecked(0) << "\n" <<
"Option2:" << checkBoxes->isChecked(1) << "\n" <<
"Option3:" << checkBoxes->isChecked(2) << "\n\n" <<
"Use q to exit"
));
},
{image.cols / 2, image.rows / 2});
int key = 0;
c.setImage(image);
do
{
key = c.waitKeyEx(); // GUI and callbacks happen here
} while (key != 'q');
destroyAllWindows();
return 0;
}
~~~~~~~
Notes:
* This tutorial is using C++11 lambda expressions as callbacks, but
anything which has the void(Widget*,int) signature will work.
* Note the alternate way of displaying images
* use canvascv::Canvas::setImage for the image you're showing.
* use canvascv::Canvas::waitKeyEx() without arguments to refresh
widgets and handle internal events with your image as the background.
* Here is a possible outcome this code:
@image html tut_checkboxes_cb.png
<BR>


#include <canvas.h>
#include <colors.h>
#include <widgets/msgbox.h>
# CheckBoxes with polling {#checkbox_s2}

Using polling might serve you right for some reason...

Instead of using a callback, you can check the values on each iteration.

This is not the recommended way.

See this code and read the notes after it:
~~~~~~~{.cpp}
#include <canvascv/canvas.h>
#include <canvascv/widgets/checkboxes.h>
using namespace std;
using namespace cv;
using namespace canvascv;
int main()
int main(int argc, char **argv)
{
Mat image(600, 800, CV_8UC3);
image = Colors::White;
--argc;
++argv;
if (! argc)
{
Canvas::fatal("Must get a path to an image as a parameter" , -1);
}
Mat image = imread(argv[0]);
if (image.empty())
{
Canvas::fatal(string("Cannot load image ") + argv[0], -2);
}
Canvas c(image.size());
Canvas c("CheckBoxes", image.size());
namedWindow("Canvas",
WINDOW_AUTOSIZE); // diable mouse resize since resizing
// the window will stretch the widgets
namedWindow("CheckBoxes", WINDOW_AUTOSIZE);
c.setMouseCallback("Canvas"); // optional for mouse usage (see also example_selectbox.cpp)
c.setMouseCallback(); // optional for mouse usage (see also example_selectbox.cpp)
auto msgBox = MsgBox::create(c, "Do you really want to do that?", {"Yes", "No"});
auto checkBox = CheckBoxes::create(c, {
"Option1", // index 0
"Option2", // index 1
"Exit" // index 2
},
Widget::CBUserSelection(), // empty callback
Point(image.cols / 2, image.rows / 2));
int delay = 1000/25; // if using a polling API we need a delay
int key = -1;
int key = 0;
int delay = 1000 / 25; // must use a delay when polling
Mat out;
do
{
c.redrawOn(image, out);
imshow("Canvas", out);
key = c.waitKeyEx(delay);
} while (msgBox->getUserSelection() != -1);
cout << "user choose option with index " << msgBox->getUserSelection() << endl;
c.imshow(out);
key = c.waitKeyEx(delay); // GUI and callbacks happen here
} while (! checkBox->isChecked(2));
destroyAllWindows();
return 0;
}
~~~~~~~
Notes:
* When polling is used we need all these stages in the main loop -
* canvascv::Canvas::redrawOn()
* canvascv::Canvas::imshow()
* canvascv::Canvas::waitKeyEx() with a non zero delay
* Here is a possible outcome this code:
@image html tut_checkboxes_poll.png
<BR>

**That's all for this tutorial**
Loading

0 comments on commit d462450

Please sign in to comment.