Related
The code is building successfully but when I run the code I have the following error -
The following is a new check for GLUT 3.0; update your code.
GLUT: Fatal Error in D:\6th Sem\4. CG UCS505\EasyAlgo\Project1\Debug\Project1.exe: redisplay needed for window 1, but no display callback.
I've tried everything but am not able to figure it out, am new with open gl and vs. Thank you for your help.
Here is the .cpp file code -
source.cpp
#include <GL/glut.h>
#include <debug.hpp>
#include <config.hpp>
#include <blobs.hpp>
#include <fonts.hpp>
#include <draw.hpp>
#include <highlight.hpp>
#include <animation.hpp>
#include <unistd.h>
#include <iostream>
using namespace std;
unsigned short mainWindow, subWindow1, subWindow2;
void Init(float, float, float);
void Init(float, float, float, int, int);
void mainInit();
void display();
void onClick(int, int, int, int);
void keyPress(unsigned char, int, int);
int main(int argc, char** argv)
{
#ifdef DEBUG
mode = "InsertionSort";
b1.bv.resize(7, blobs());
int rad[7] = { 28,32,20,28,36,45,31 };
for (int p = 0; p < 7; p++)
b1.bv[p].radius = (float)rad[p];
b1.min = 20;
b1.max = 45;
#endif
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WindowWidth, WindowHeight);
std::string title = "AlgoLucidator " + AL_VERSION;
mainWindow = glutCreateWindow(title.c_str());
glutPositionWindow(WIN_POS_X, WIN_POS_Y);
mainInit();
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
subWindow1 = glutCreateSubWindow(mainWindow, 0, 0, WindowWidth / 4, WindowHeight);
Init(0.80f, 0.80f, 0.60f);
glutKeyboardFunc(keyPress);
glutDisplayFunc(display);
subWindow2 = glutCreateSubWindow(mainWindow, WindowWidth / 4, 0, 3 * WindowWidth / 4, WindowHeight);
Init(0.65f, 0.75f, 0.70f);
std::string mainInstruct = "Press 1. InsertionSort 2. BubbleSort 3. Dijkstra";
printText(0, 0, 0, -(5 * mainInstruct.size()), 540, mainInstruct);
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void Init(float r, float g, float b)
{
int CurrWindowWidth = glutGet(GLUT_WINDOW_WIDTH);
int CurrWindowHeight = glutGet(GLUT_WINDOW_HEIGHT);
glClearColor(r, g, b, 1);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-CurrWindowWidth, CurrWindowWidth, -CurrWindowHeight, CurrWindowHeight);
drawTitle(CurrWindowWidth, CurrWindowHeight);
}
void Init(float r, float g, float b, int width, int height)
{
glClearColor(r, g, b, 1);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-width, width, -height, height);
drawTitle(width, height);
}
void mainInit()
{
int CurrWindowWidth = glutGet(GLUT_WINDOW_WIDTH);
int CurrWindowHeight = glutGet(GLUT_WINDOW_HEIGHT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, CurrWindowWidth, 0, CurrWindowHeight);
glClearColor(0, 0, 0, 0.80f);
glClear(GL_COLOR_BUFFER_BIT);
}
void display()
{
glFlush();
}
void onClick(int button, int state, int oldx, int oldy)
{}
void keyPress(unsigned char key, int x, int y)
{
int activeWindow = glutGetWindow();
switch (key)
{
case 13: if (b1.pushreq)
{
b1.bv.push_back(blobs((float)base_radius));
}
if (activeWindow != subWindow2)
glutSetWindow(subWindow2);
if (mode == "InsertionSort")
{
drawInsertionSort();
}
else if (mode == "BubbleSort")
{
drawBubbleSort();
}
break;
case 27: glutDestroyWindow(mainWindow); //Esc
break;
case 49: mode = "InsertionSort";
b1.reset();
glutSetWindow(subWindow2);
glutMouseFunc(onClick2);
Init2(0.65f, 0.75f, 0.70f);
drawTitle3(960, 640);
break;
case 50: mode = "BubbleSort";
glutSetWindow(subWindow2);
glutMouseFunc(onClick3);
glutIdleFunc(display);
Init3(0.65f, 0.75f, 0.70f);
drawTitle4(960, 640);
break;
default:;
}
}
The error message is pretty much exactly telling what's wrong and how to fix it (QFT):
The following is a new check for GLUT 3.0; update your code. GLUT: Fatal Error in (…) Project1.exe: redisplay needed for window 1, but no display callback.
For first window you create, window one, the one created with glutCreateWindow you don't specify a display callback:
mainWindow = glutCreateWindow(title.c_str());
glutPositionWindow(WIN_POS_X, WIN_POS_Y);
mainInit();
glutMouseFunc(onClick);
glutKeyboardFunc(keyPress);
/// <<<<<<<< something is missing here
subWindow1 = glutCreateSubWindow(mainWindow, 0, 0, WindowWidth / 4, WindowHeight);
Give that first window you create a display callback and the error will go away.
On a second note: Nothing of what's happening in the …Init functions is initialization at all. OpenGL is a state machine, and everything done in …Init is state prepration that ought to happen at the start of rendering a frame.
I would like to be able to display in a Dicom image in a Qt project with the same render as a Dicom Viewer Program could give.
I was able to do it but with a very bad contrast. I heard you need to operate on the pixels but I'm not sure. Do you have a working example ?
EDIT: I add my code in case it helps you, I commented a lot of things because I noticed the result was exactly the same
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#undef UNICODE
#undef _UNICODE
#include <dcmtk/config/osconfig.h>
#include <dcmtk/dcmdata/dctk.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include <QPixmap>
#include <QLabel>
#include <QImageReader>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//int sizeX = 600;
// int sizeY = 600;
//initialize random seed
//srand (time(NULL));
//QImage image = QImage( sizeX, sizeY, QImage::Format_RGB32 );
/*for( int l=0; l<sizeX; l++ )
{
for( int c=0; c<sizeY; c++ )
{
///Random color for each pixel
//image.setPixel( l, c, qRgb(rand() % 256, rand() % 256, rand() % 256) );
///Fixed color for each pixel
image.setPixel( l, c, qRgb(100, 150, 200) );
}
}*/
const char *file = "/home/x4rkz/project/Laura/QTImage/IMG00000";
DicomImage *image = new DicomImage(file);
if (image != NULL)
{
if (image->getStatus() == EIS_Normal)
{
Uint8 *pixelData = (Uint8 *)(image->getOutputData(8 )); // bits per sample
// Uint8 is a pointer to internal memory buffer
if (pixelData != NULL)
{
// do something useful with the pixel data
QImage img(pixelData,image->getWidth(), image->getHeight(), QImage::Format_Indexed8 );
/*QColor color;
QImage *img;
void *pDicomDibits;
uchar *px;
// uchar pixel[4];
const int width = (int)(image->getWidth());
const int height = (int)(image->getHeight());
if (image->isMonochrome()){
img = new QImage(width, height, QImage::Format_Indexed8);
img->setColorCount(256);
// define gray palette here
for (int i=0; i<256; i++) {
color.setRgb(i, i, i);
img->setColor(i, color.rgb());
}
image->createWindowsDIB(pDicomDibits, 0, 0, 8, 0, 1);
unsigned char * pd;
pd=(unsigned char *)pDicomDibits;
for (int y=0; y < (long) height; y++)
{
px = img->scanLine(y);
for (int x=0; x < (long) width; x++)
{
px[x] = (unsigned char) (*pd);
pd++;
}
}*/
QGraphicsScene * graphic = new QGraphicsScene( this );
graphic->addPixmap( QPixmap::fromImage( img ) );
ui->graphicsView->setScene(graphic);
/* }else
cout << "Non monochrome image" << endl;*/
}
} else
cerr << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << endl;
}
}
MainWindow::~MainWindow()
{
delete ui;
}
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#undef UNICODE
#undef _UNICODE
#include <dcmtk/config/osconfig.h>
#include <dcmtk/dcmdata/dctk.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include <QPixmap>
#include <QLabel>
#include <QImageReader>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
As you cant see, the result has no constrast.
As you cant see, the result has no constrast.
If the rendered image has such a low contrast, you should try to set an appropriate VOI (Value of Interest) window, e.g. using image->setMinMaxWndow(). See API documentation for details.
I'm trying to run an example GLUT program, but it only creates a white window and then freezes the application. I found it freezes when calling glutMainLoop (same if I call glutCheckLoop in a loop). Something I may be missing?
Here's the the sample code I found:
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Question 1: In a GLUT program, how is control passed
// back to the programmer? How is this set up during
// initialization?
int win_width = 512;
int win_height = 512;
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
}
void reshape( int w, int h )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// Question 3: What do the calls to glOrtho()
// and glViewport() accomplish?
glOrtho( 0., 1., 0., 1., -1., 1. );
glViewport( 0, 0, w, h );
win_width = w;
win_height = h;
glutPostRedisplay();
}
void keyboard( unsigned char key, int x, int y ) {
switch(key) {
case 27: // Escape key
exit(0);
break;
}
}
int main (int argc, char *argv[]) {
glutInit( &argc, argv );
// Question 2: What does the parameter to glutInitDisplayMode()
// specify?
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( win_width, win_height );
glutCreateWindow( "Intro Graphics Assignment 1" );
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
int main is not where you want glutMainLoop(), mate.
You should have that in your init method ie initGlutDisplay().
#include <stdlib.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
// Question 1: In a GLUT program, how is control passed
// back to the programmer? How is this set up during
// initialization?
int win_width = 512;
int win_height = 512;
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
glutSwapBuffers();
}
void reshape( int w, int h )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// Question 3: What do the calls to glOrtho()
// and glViewport() accomplish?
glOrtho( 0., 1., 0., 1., -1., 1. );
glViewport( 0, 0, w, h );
win_width = w;
win_height = h;
glutPostRedisplay();
}
void keyboard( unsigned char key, int x, int y ) {
switch(key) {
case 27: // Escape key
exit(0);
break;
}
}
int initGlutDisplay(int argc, char* argv[]){
glutInit( &argc, argv );
// Question 2: What does the parameter to glutInitDisplayMode()
// specify?
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( win_width, win_height );
glutCreateWindow( "Intro Graphics Assignment 1" );
glutDisplayFunc( display );
glutReshapeFunc( reshape );
glutKeyboardFunc( keyboard );
glutMainLoop();
return 0;
}
int main (int argc, char *argv[]) {
int win_width = 512;
int win_height = 512;
initGlutDisplay(argc, argv);
}
The above code should work perfectly.
EDIT
According to opengl
AGL is the old Carbon-based API with C bindings. The Carbon part
needed for windowing and event handling are not thread-safe. There is
no 64 bit version of this API.
I wonder if this is your issue. I would review the opengl Programming guide by apple to see if you missed any steps that might solve your problem.
It was a bug in the compiler (works now with gcc)
I can find questions/answers for iPhone/Windows but none for X11.
Also if there is anyone with a ton of OpenGL experience who can explain the general concepts involved for any windowing system?
Yes it is possible. I modified a example program written by fungus to create a RGBA OpenGL window. If a compositor is enabled the results look like in the video I posted here: http://www.youtube.com/watch?v=iHZfH1Qhonk
/*------------------------------------------------------------------------
The simplest possible Linux OpenGL program? Maybe...
Modification for creating a RGBA window (transparency with compositors)
by Wolfgang 'datenwolf' Draxinger
(c) 2002 by FTB. See me in comp.graphics.api.opengl
(c) 2011 Wolfgang Draxinger. See me in comp.graphics.api.opengl and on StackOverflow
License agreement: This source code is provided "as is". You
can use this source code however you want for your own personal
use. If you give this source code to anybody else then you must
leave this message in it.
--
<\___/>
/ O O \
\_____/ FTB.
--
datenwolf
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glx.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
typedef struct
{
Visual *visual;
VisualID visualid;
int screen;
unsigned int depth;
int klass;
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
int colormap_size;
int bits_per_rgb;
} XVisualInfo_CPP;
/*------------------------------------------------------------------------
Something went horribly wrong
------------------------------------------------------------------------*/\
static void fatalError(const char *why)
{
fprintf(stderr, "%s", why);
exit(0x666);
}
/*------------------------------------------------------------------------
Global vars
------------------------------------------------------------------------*/
static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo_CPP *visual;
static XRenderPictFormat *pictFormat;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext RenderContext;
static Window Xroot, WindowHandle, GLXWindowHandle;
static int width, height; /* Size of the window */
int const tex_width=512;
int const tex_height=512;
static GLuint texture;
static int VisData[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None
};
/*------------------------------------------------------------------------
Create a window
------------------------------------------------------------------------*/
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
return (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}
static void createTheWindow()
{
XEvent event;
int x,y, attr_mask;
XSizeHints hints;
XWMHints *StartupState;
XTextProperty textprop;
XSetWindowAttributes attr;
static char *title = "FTB's little OpenGL example";
/* Connect to the X server */
Xdisplay = XOpenDisplay(NULL);
if (!Xdisplay) {
fatalError("Couldn't connect to X server\n");
}
Xscreen = DefaultScreen(Xdisplay);
Xroot = RootWindow(Xdisplay, Xscreen);
fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs);
for(int i = 0; i<numfbconfigs; i++) {
visual = (XVisualInfo_CPP*) glXGetVisualFromFBConfig(Xdisplay, fbconfigs[i]);
if(!visual)
continue;
pictFormat = XRenderFindVisualFormat(Xdisplay, visual->visual);
if(!pictFormat)
continue;
if(pictFormat->direct.alphaMask > 0) {
fbconfig = fbconfigs[i];
break;
}
}
/* Create a colormap - only needed on some X clients, eg. IRIX */
cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone);
/* Prepare the attributes for our window */
attr.colormap = cmap;
attr.border_pixel = 0;
attr.event_mask =
StructureNotifyMask |
EnterWindowMask |
LeaveWindowMask |
ExposureMask |
ButtonPressMask |
ButtonReleaseMask |
OwnerGrabButtonMask |
KeyPressMask |
KeyReleaseMask;
attr.background_pixmap = None;
attr_mask =
CWBackPixmap|
CWColormap|
CWBorderPixel|
CWEventMask; /* What's in the attr data */
/* Create the window */
width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
x=width/2, y=height/2;
/* Create the window */
WindowHandle = XCreateWindow( Xdisplay, /* Screen */
Xroot, /* Parent */
x, y, width, height,/* Position */
1,/* Border */
visual->depth,/* Color depth*/
InputOutput,/* klass */
visual->visual,/* Visual */
attr_mask, &attr);/* Attributes*/
if( !WindowHandle ) {
fatalError("Couldn't create the window\n");
}
/* Configure it... (ok, ok, this next bit isn't "minimal") */
textprop.value = (unsigned char*)title;
textprop.encoding = XA_STRING;
textprop.format = 8;
textprop.nitems = strlen(title);
hints.x = x;
hints.y = y;
hints.width = width;
hints.height = height;
hints.flags = USPosition|USSize;
StartupState = XAllocWMHints();
StartupState->initial_state = NormalState;
StartupState->flags = StateHint;
XSetWMProperties(Xdisplay, WindowHandle,&textprop, &textprop,/* Window title/icon title*/
NULL, 0,/* Argv[], argc for program*/
&hints, /* Start position/size*/
StartupState,/* Iconised/not flag */
NULL);
XFree(StartupState);
/* Open it, wait for it to appear */
XMapWindow(Xdisplay, WindowHandle);
XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&WindowHandle);
/* Set the kill atom so we get a message when the user tries to close the window */
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
XSetWMProtocols(Xdisplay, WindowHandle, &del_atom, 1);
}
}
/*------------------------------------------------------------------------
Create the OpenGL rendering context
------------------------------------------------------------------------*/
static void createTheRenderContext()
{
/* See if we can do OpenGL on this visual */
int dummy;
if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) {
fatalError("OpenGL not supported by X server\n");
}
/* Create the OpenGL rendering context */
RenderContext = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True);
if (!RenderContext) {
fatalError("Failed to create a GL context\n");
}
GLXWindowHandle = glXCreateWindow(Xdisplay, fbconfig, WindowHandle, NULL);
/* Make it current */
if (!glXMakeContextCurrent(Xdisplay, GLXWindowHandle, GLXWindowHandle, RenderContext)) {
fatalError("glXMakeCurrent failed for window\n");
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
/*------------------------------------------------------------------------
Window messages
------------------------------------------------------------------------*/
static int updateTheMessageQueue()
{
XEvent event;
XConfigureEvent *xc;
while (XPending(Xdisplay))
{
XNextEvent(Xdisplay, &event);
switch (event.type)
{
case ClientMessage:
if (event.xclient.data.l[0] == del_atom)
{
return 0;
}
break;
case ConfigureNotify:
xc = &(event.xconfigure);
width = xc->width;
height = xc->height;
break;
}
}
return 1;
}
/*------------------------------------------------------------------------
Redraw the window
------------------------------------------------------------------------*/
float const light_dir[]={1,1,1,0};
float const light_color[]={1,0.95,0.9,1};
static void redrawTheWindow()
{
int size;
static float a=0;
static float b=0;
static float c=0;
glViewport(0,0,width,height);
/* Clear the screen */
// glClearColor(0.750,0.750,1.0,0.5);
glClearColor(0.0,0.0,0.0,0.);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float)width/(float)height, 1, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glLightfv(GL_LIGHT0, GL_POSITION, light_dir);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
glTranslatef(0,0,-5);
glRotatef(a, 1, 0, 0);
glRotatef(b, 0, 1, 0);
glRotatef(c, 0, 0, 1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glutSolidTeapot(1);
a=fmod(a+0.1, 360.);
b=fmod(b+0.5, 360.);
c=fmod(c+0.25, 360.);
/* Swapbuffers */
glXSwapBuffers(Xdisplay, GLXWindowHandle);
}
/*------------------------------------------------------------------------
Program entry point
------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
/* instead of a triangle I wanted a teapot. GLUT has it.
GLUT is NOT used for window creation, but just the teapot
primitive. Nevertheless it must be initialized */
glutInit(&argc, argv);
createTheWindow();
createTheRenderContext();
while (updateTheMessageQueue()) {
redrawTheWindow();
}
return 0;
}
I've been trying to detect click on a Gtk::Image with gtkmm for over 2 hours, but I couldn't get it to work. It does compile and execute fine, but the event is never triggered.
Some stuff I tried, that compiles, does not crash, but doesn't work:
m_image = manage(new Gtk::Image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_BUTTON));
m_image->add_events(Gdk::ALL_EVENTS_MASK);
m_hbox->pack_start(*m_image, Gtk::PACK_SHRINK);
m_image->signal_button_release_event()
.connect(sigc::hide(sigc::mem_fun(*this, &Todo::switchStatus)));
m_image->show();
or
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/stock.h>
#include <gtkmm/image.h>
#include <iostream>
using namespace std;
class Win : public Gtk::Window
{
public:
Win();
bool link(GdkEventButton* e);
private:
Gtk::Image image;
};
Win::Win()
: image(Gtk::Stock::APPLY, Gtk::ICON_SIZE_BUTTON)
{
cerr << "created" << endl;
image.add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
image.signal_button_release_event().connect(sigc::mem_fun(*this, &Win::link));
image.show();
add(image);
}
bool Win::link(GdkEventButton* e)
{
cerr << "kuh" << endl;
}
int main(int argc, char *argv[])
{
Gtk::Main app(argc, argv);
Gtk::Window window;
window.resize(300, 500);
Win win;
Gtk::Main::run(win);
return 0;
}
From http://developer.gnome.org/gtkmm/unstable/classGtk_1_1Image.html:
Gtk::Image is a "no window" widget (has no Gdk::Window of its own), so by default does not receive events. If you want to receive events on the image, such as button clicks, place the image inside a Gtk::EventBox, then connect to the event signals on the event box
So I guess try to put a signal on an eventbox after wrapping the image with the EventBox.
I like to put a button overtop of the image with an opacity of 0. Then you can use the click event from it instead.
This thread is quite old but still popular. I came across the same problem and I coded this code, maybe it can help someone save tim. My code detects the click ONLY if the pointer is hovering the image.
#include <gtk/gtk.h>
//compile with cc `pkg-config --cflags gtk+-3.0` text.c `pkg-config --libs gtk+-3.0` -o text
static void click_callback(GtkWidget *widget, GdkEventButton *event, gpointer );
static gboolean inRange(gint value, gint min, gint max);
static gboolean pointInRect(gint mouseX, gint mouseY, gint wx, gint wy, gint width, gint height);
GtkWidget *image;
GtkWidget *image2;
int main (int argc, char *argv[])
{
GtkWidget *event_box;
GtkWidget *window;
GtkWidget *box;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
/* GTK_ALIGN_CENTER is necessary otherwise
* the callback triggers from the space on
* the top and the bottom of the image */
gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
image = gtk_image_new_from_file("image1.png");
image2 = gtk_image_new_from_file("image2.png");
gtk_box_pack_start(GTK_BOX(box), image, TRUE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(box), image2, TRUE, FALSE, 0);
event_box = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (event_box), box);
gtk_container_add (GTK_CONTAINER (window), event_box);
g_signal_connect(window, "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect( event_box, "button_press_event", G_CALLBACK( click_callback ), image);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window), "Image click event");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
static void click_callback(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
GtkAllocation alloc;
GtkAllocation alloc2;
gtk_widget_get_allocation(image, &alloc);
gtk_widget_get_allocation(image2, &alloc2);
if (pointInRect(event->x, event->y, alloc.x, alloc.y, alloc.width, alloc.height))
g_print("You clicked from image\n");
if (pointInRect(event->x, event->y, alloc2.x, alloc2.y, alloc2.width, alloc2.height))
g_print("You clicked from image2\n");
}
static gboolean pointInRect(gint mouseX, gint mouseY, gint wx, gint wy, gint width, gint height)
{
return inRange(mouseX, wx, wx + width) &&
inRange(mouseY, wy, wy + height);
}
static gboolean inRange(gint value, gint min, gint max)
{
return (value >= min && value <= max);
}