Which Gtkmm functions can help me get the position(x,y) of the cursor. According to this, C# has
Gdk.Display.Default.WarpPointer(Gdk.Display.DefaultScreen, 20, 20);
Windows has
GetCursorPos
Qt has
QCursor::pos()
Gtkmm has what?
Here you are.
#include <stdio.h>
#include <gtkmm.h>
int main(int argc, char* argv[]) {
Gtk::Main gtkm(argc, argv);
Glib::RefPtr<Gdk::Display> disp = Gdk::Display::get_default();
Glib::RefPtr<Gdk::Screen> scrn = disp->get_default_screen();
Gdk::ModifierType mods;
int xpos, ypos;
disp->get_pointer(scrn, xpos, ypos, mods);
printf("xpos = %d, ypos = %d\n", xpos, ypos);
return 0;
}
Related
I wrote a simple FLTK program to draw a circle when clicking on the "Draw Circle" button and to draw a line when clicking on the "Draw Line" button. I supposed to have only one graph. But I got two graphs in the panel. I want only one showing and the other disappearing. The following is the code:
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>
using namespace std;
int flag = 0;
class Drawing : public Fl_Box {
void draw() {
fl_color(255, 0, 0);
int x, y, x1, y1;
if (flag == 1) {
double radius = 100;
x = (int)(w() / 2);
y = (int)(h() / 2);
fl_circle(x, y, radius);
}
else if (flag == -1) {
x = (int)(w() / 4);
y = (int)(h() / 4);
x1 = (int)(w() *3/ 4);
y1 = (int)(h() *3/ 4);
fl_line(x, y, x1, y1);
}
}
public:
Drawing(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H) {}
};
Drawing* d;
void circle_cb(Fl_Widget*, void*) {
flag = 1;
fl_overlay_clear();
d->redraw();
} // end sumbit_cb
void line_cb(Fl_Widget*, void*) {
flag = -1;
fl_overlay_clear();
d->redraw();
} // end clear_cb
int main(int argc, char** argv) {
Fl_Window* window = new Fl_Window(600, 550); // create a window, originally(400,400)
Drawing dr(0, 0, 600, 600);
d = &dr;
Fl_Button *b, *c;
b = new Fl_Button(150, 80, 100, 25, "&Draw Circle");
b->callback(circle_cb);
c = new Fl_Button(350, 80, 100, 25, "&Draw Line");
c->callback(line_cb);
window->end(); //show the window
window->show(argc, argv);
return Fl::run();
}
I have used fl_overlay_clear() to clear graph. However it is not working. Any help will be appreciated.
There are several issues that need to be fixed in your program, but first of all using the draw() method as you did is basically correct. However, using fl_overlay_clear(); is useless, you can remove it.
My solution: your widget doesn't have a solid background (boxtype), i.e. your draw method draws over the background over and over again w/o clearing it. There are several ways to solve this, but if you want to learn what happens, try this first: add window->resizable(window); before window->show(argc, argv);, run the program again and resize the window. You'll notice that the previous drawing disappears and only one drawing stays. That's because the background is cleared when you resize the widget.
Next step: add a solid boxtype:
d = &dr;
d->box(FL_DOWN_BOX);
and add Fl_Box::draw(); right at the beginning of your draw() method.
If you do that you may notice that your button(s) disappear when you click one of them - because your buttons are inside the area of your Drawing. The last thing(s) I fixed was to correct the coordinates of buttons and to enlarge the window (it was too small anyway to cover the entire Drawing). Here's my complete result:
#include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>
using namespace std;
int flag = 0;
class Drawing : public Fl_Box {
void draw() {
Fl_Box::draw();
fl_color(255, 0, 0);
int x, y, x1, y1;
if (flag == 1) {
double radius = 100;
x = (int)(w() / 2);
y = (int)(h() / 2);
fl_circle(x, y, radius);
} else if (flag == -1) {
x = (int)(w() / 4);
y = (int)(h() / 4);
x1 = (int)(w() * 3 / 4);
y1 = (int)(h() * 3 / 4);
fl_line(x, y, x1, y1);
}
}
public:
Drawing(int X, int Y, int W, int H)
: Fl_Box(X, Y, W, H) {}
};
Drawing *d;
void circle_cb(Fl_Widget *, void *) {
flag = 1;
// fl_overlay_clear(); // not useful
d->redraw();
} // end sumbit_cb
void line_cb(Fl_Widget *, void *) {
flag = -1;
// fl_overlay_clear(); // not useful
d->redraw();
} // end clear_cb
int main(int argc, char **argv) {
Fl_Window *window = new Fl_Window(600, 660); // create a window, originally(400,400)
Drawing dr(0, 60, 600, 600); // FIXED
d = &dr;
d->box(FL_DOWN_BOX); // ADDED
Fl_Button *b, *c;
b = new Fl_Button(150, 20, 100, 25, "&Draw Circle"); // FIXED
b->callback(circle_cb);
c = new Fl_Button(350, 20, 100, 25, "&Draw Line"); // FIXED
c->callback(line_cb);
window->end(); // show the window
window->resizable(window); // ADDED
window->show(argc, argv);
return Fl::run();
}
I believe this does what you want.
PS: the official FLTK support forum can be found on our website https://www.fltk.org/ and the direct link to the user forum (Google Groups) is https://groups.google.com/g/fltkgeneral
Just a quick addition to what Albrecht put so perfectly: FLTK drawing coordinates are relative to the window, not relative to the widget. You probably want to offset your drawing by the x() and y() coordinates of your widget.
In your handle() methods line_cb() , circle_cb() should call window()->make_current() and then fl_overlay_rect() after FL_DRAG events, and should call fl_overlay_clear() after a FL_RELEASE event. Refer for more details
After creating a window and drawing some shapes in it, I realized I cant make a point and just appear it on the window. I've searched the manual but I cant make anything out of it. Im using the fltk 1.3.0. How can I do it ?
Fltk comes with a bunch of example projects that are helpful. If you look at the line_style example you can easily reduce it to something drawing points like this:
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
class TestWindow : public Fl_Window {
void draw()
{
fl_color(255, 0, 0);
fl_begin_points();
fl_point(50, 50);
fl_point(51, 51);
fl_end_points();
}
public:
TestWindow(int w, int h, const char *l = 0)
: Fl_Window(w, h, l) {}
};
int main(int argc, char ** argv) {
Fl_Window *window = new TestWindow(200, 200);
window->end();
window->show(argc, argv);
return Fl::run();
}
But just as a word of advice, drawing single points directly onto the window is rarely the smart thing to do. Drawing into images/buffers and then displaying them is the better alternative most of the time.
edit:
here's is an example of putting the drawing code in the main function.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
class TestWindow : public Fl_Window {
void draw() {}
public:
TestWindow(int w, int h, const char *l = 0) : Fl_Window(w, h, l) {}
};
int main(int argc, char ** argv) {
Fl_Window *window = new TestWindow(200, 200);
window->end();
window->show(argc, argv);
window->make_current();
fl_color(255, 0, 0);
fl_begin_points();
fl_point(50, 50);
fl_point(51, 51);
fl_end_points();
return Fl::run();
}
You should take notice of the disclaimer for make_current in the manual
Danger: incremental update is very hard to debug and maintain!
None of this is good practise beyond using it for simple exercises.
Based on the previous answer to this question, I found this in the documentation:
fl_begin_points()
Starts drawing a list of points.
Points are added to the list with fl_vertex()
So this is some code that shows some points (I added more to really see the points):
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
class Drawing : public Fl_Window {
void draw(){
fl_begin_points();
//adding cushion to points to be able to see them.
//center at 10,10
fl_vertex(9,9);
fl_vertex(9,10);
fl_vertex(9,11);
fl_vertex(10,9);
fl_vertex(10,10);
fl_vertex(10,11);
fl_vertex(11,9);
fl_vertex(11,10);
fl_vertex(11,11);
fl_end_points();
fl_color(FL_BLACK);
}
public:
Drawing(int w, int h, const char *l = 0) : Fl_Window(w, h, l){}
};
int main(int argc, char **argv){
Fl_Window *window = new Drawing(340,180);
window->end();
window->show(argc, argv);
return Fl::run();
}
I am trying to implement zoom in or zoom out operations using mouse scroll button
by glutMouseWheelFunc in opengl . I have implemted the code as below :
#include<GL/freeglut.h>
void mouseWheel(int button, int dir, int x, int y)
{
printf("in mouse wheel \n");
if (dir > 0)
{
// Zoom in
ztrans = ztrans - 1.0;
printf("scroll in = %0.3f\n ",ztrans);
}
else
{
// Zoom out
ztrans = ztrans + 1.0;
printf("scroll out = %0.3f\n ",ztrans);
}
glutPostRedisplay();
}
int main(int argc, char **argv)
{
// general initializations
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(800, 400);
glutCreateWindow("Rotation");
// register callbacks
glutReshapeFunc(changeSize);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutIgnoreKeyRepeat(1);
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMove);
glutMouseWheelFunc(mouseWheel); // Register mouse wheel function
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
On executing, it is not calling the registered callback function(mouseWheel) . My system has freeglut3 installed.
try using
a static int inside void mouseWheelmethod, and then use it in renderScene
like this
static int k;
static int ztrans
void mouseWheel(int button, int dir, int x, int y)
{
k = dir; // int dir is +1 of -1 based on the direction of the wheel motion
ztrans = ztrans + k;
}
This worked for me,
Try this and feedback, GoodLuck .
I got some problems when creating a Cairo::RefPtr on a Cairo-Context.
I really can't imagine why this segfaults, except the pointer ist pointing on something completely wrong.
This is my code.
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
Gtk::DrawingArea drawarea;
window.add(drawarea);
Cairo::RefPtr<Cairo::Context> ccontext = drawarea.get_window()->create_cairo_context();
Gtk::Allocation allocation = drawarea.get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
Gtk::Main::run(window);
}
And this is what GDB says:
Starting program: /home/marian/Desktop/C++/Langton/Langton [Thread
debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault. 0xb7be852e in
Gdk::Window::create_cairo_context() () from /usr/lib/libgdkmm-3.0.so.1
I compiled this with gcc (GCC) 4.6.1 20110819 (prerelease).
Thanks in advance
Gtk::Widget::get_window() returns a null Glib::RefPtr, since the widget has not been realized just yet.
Based on the GtkDrawingArea documentation, you need to hook onto the "draw" signal to handle drawing, where your Cairo context is already created and handed to you. Going back to the Gtkmm reference, you would use Gtk::Widget::signal_draw() to hook onto that, or you could overload the virtual on_draw() function to handle your drawing.
Additionally, you also need to call .show() on each widget, i.e. your DrawingArea and your Window, and call ccontext->stroke() to get the line actually drawn.
The result would look something like:
#include <gtkmm.h>
bool draw (const Cairo::RefPtr<Cairo::Context> &ccontext, Gtk::DrawingArea *drawarea)
{
Gtk::Allocation allocation = drawarea->get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
ccontext->stroke ();
return true;
}
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
Gtk::DrawingArea drawarea;
drawarea.signal_draw ().connect (sigc::bind (sigc::ptr_fun (&draw),
&drawarea));
window.add(drawarea);
window.show_all ();
Gtk::Main::run(window);
return 0;
}
or alternatively:
#include <gtkmm.h>
class LineBox : public Gtk::DrawingArea
{
protected:
virtual bool on_draw (const Cairo::RefPtr<Cairo::Context> &ccontext);
};
bool LineBox::on_draw (const Cairo::RefPtr<Cairo::Context> &ccontext)
{
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
ccontext->stroke ();
return true;
}
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
LineBox drawarea;
window.add(drawarea);
window.show_all ();
Gtk::Main::run(window);
return 0;
}
Here is my code:
#include <gtk/gtk.h>
G_MODULE_EXPORT void waka(GtkWidget *button, GtkWidget* entry1)
{
printf("%s",gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(waka),entry);
entry = gtk_entry_new();
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE,2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
When I launch it, and try to fill in some string in the entry box, and then click the button, it said 'segmentation fault'. What is going on?
Also, the callback only works with one user data argument. How about if I want two or more arguments, what must I do in the callback function, and in the call to g_signal_connect()?
the problem is that you're trying to use pointer to entry before initializing it. I've changed a bit your code to fix this, see if it will work for you:
#include <gtk/gtk.h>
void waka(GtkWidget *button, GtkWidget* entry1)
{
g_print("entry: %s\n", gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry, *vbox;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
entry = gtk_entry_new();
vbox = gtk_vbox_new(FALSE, 2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(waka), entry);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
hope this helps, regards