As seen in the Gtk documentation here there is a method to set the visual of the Widget which seems to be missing from gtkmm (C++ wrapper).
While trying to port a Gtk application from C to C++ using gtkmm-3.0, quickly discovered that the set_visual() method is missing. Although there is a get_visual() that returns the visual of the widget.
The C code looks like this:
GdkScreen *screen = gtk_widget_get_screen(widget);
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
if (visual == NULL)
visual = gdk_screen_get_system_visual(screen);
gtk_widget_set_visual(widget, visual);
Does anyone know how can i set the widget visual with a custom one?
If the C++ wrapper does not provide what you need, you can always get a pointer to the underlying C GObject instance and work with it as you would in a typical GTK C application. Check out this method for Gtk::Widget:
GtkWidget* Gtk::Widget::gobj()
So you can call this on your widget, get a C GtkWidget pointer and call gtk_widget_set_visual on it like you are doing in your question. Note that this solution works all across Gtkmm, which in my opinion is a really nice feature that other wrappers do not have.
Related
I made a GUI in Glade. I have this kind of structure:
_ A GtkWindow named winTimer
__ A GtkVBox
___ A GtkHBox
____ A GtkAlignment called alignTimer with absolutely nothing inside.
My structure (gif)
I do:
controlli->alignTimer=GTK_WIDGET(gtk_builder_get_object(builder,"alignTimer"));
controlli->pbTimerComposito = gdk_pixbuf_new(GDK_COLORSPACE_RGB,0,8,320,200);
controlli->imgTimer = GTK_WIDGET(gtk_image_new_from_pixbuf(controlli->pbTimerComposito));
gtk_container_add(GTK_CONTAINER(controlli->alignTimer),controlli->imgTimer); /* warning */
gtk_widget_show(controlli->imgTimer);
Where controlli is a pointer to a struct that has, among other things:
GtkWidget *alignTimer;
GdkPixbuf *pbTimerComposito;
GtkWidget *imgTimer;
I get this at runtime:
Gtk-WARNING **: Attempting to add a widget with type GtkImage to a GtkAlignment, but as a GtkBin subclass a GtkAlignment can only contain one widget at a time; it already contains
a widget of type GtkImage
But that is not true! It's the first and only widget that I'm adding! What's happening? I had done the exact same thing in another part of my app and it's been working perfectly for years.
My environment:
- Windows XP SP3
- MinGW
- GCC 4.8.1
- GTK 2.24.10
PS I know I'm using an old version of GTK, deprecated widgets and an ancient OS, but I code just for fun so I'm OK with that. Any help will be very appreciated.
Problem solved (or, rather, there was no problem).
The function that contained the code I posted above was called twice. Facepalm for myself.
I am trying to compile and run an example of gtk+3, unfortunately, the example is from gtk+2 manual, I can't find anything useful on gtk+3 and I can't download gtk+2.
On the example there are a couple of function like this:
void entry_toggle_editable( GtkWidget *checkbutton,
GtkWidget *entry )
{
gtk_editable_set_editable(GTK_EDITABLE(entry),GTK_TOGGLE_BUTTON(checkbutton)->active);
}
When compiling I got this error:
'GtkToggleButton {aka struct _GtkToggleButton}' has no member named 'active'
I looked in all manuals. I was able to find in order to get around the problem, I understand that probably it is a release compatibility problem, but gtk+3 manuals are really useless for somebody approaching for the first time Gtk.
One of the biggest changes between GTK+ 2 and GTK+ 3 is that GTK+ 3 gets rid of all public structure fields, replacing them with GObject properties. So instead of saying
GTK_TOGGLE_BUTTON(checkbutton)->active
you say
gboolean active;
g_object_get(checkbutton, "active", &active, NULL);
(The NULL is because g_object_get() can get multiple properties from the same object at the same time; the NULL says "that is all I need from this call".)
GTK+ also provides accessor methods to add type checking, so you can also say
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton))
Using these when available is preferable to calling g_object_get() directly.
The GTK+ documentation does come with a tutorial. As you probably realized, you cannot use GTK+ 2 examples to learn GTK+ 3 without modification; you will need to spend more time finding GTK+ 3 examples.
I'm working on a pet project solely for the purpose of learning a few API's. It's not intended to have practical value, but rather to be relatively simple excercise to get me comfortable with libpcap, gtk+, and cairo before I use them for anything serious. This is a graphical program, implemented in C and using Gtk+ 2.x. It's eventually going to read frames with pcap (currently I just have a hardcoded test frame), then use cairo to generate pretty pictures using color values generated from the raw packet (at this stage, I'm just using cairo_show_text to print a text representation of the frame or packet). The pictures will then be drawn to a custom widget inheriting from GtkDrawingArea.
My first step, of course, is to get a decent grasp of the Gtk+ runtime environment so I can implement my widget. I've already managed to render and draw text using cairo to my custom widget. Now I'm at the point where I think the widget really needs private storage for things like the cairo_t context pointer and a GdkRegion pointer (I had not planned to use Gdk directly, but my research indicates that it may be necessary in order to call gdk_window_invalidate_region() to force my DrawingArea to refresh once I've drawn a frame, not to mention gdk_cairo_create()). I've set up private storage as a global variable (the horror! Apparently this is conventional for Gtk+. I'm still not sure how this will even work if I have multiple instances of my widget, so maybe I'm not doing this part right. Or maybe the preprocessor macros and runtime environment are doing some magic to give each instance its own copy of this struct?):
/* private data */
typedef struct _CandyDrawPanePrivate CandyDrawPanePrivate;
struct _CandyDrawPanePrivate {
cairo_t *cr;
GdkRegion *region;
};
#define CANDY_DRAW_PANE_GET_PRIVATE(obj)\
(G_TYPE_INSTANCE_GET_PRIVATE((obj), CANDY_DRAW_PANE_TYPE, CandyDrawPanePrivate))
Here's my question: Initializing the pointers in my private data struct depends on members inherited from the parent, GtkWidget:
/* instance initializer */
static void candy_draw_pane_init(CandyDrawPane *pane) {
GdkWindow *win = NULL;
/*win = gtk_widget_get_window((GtkWidget *)pane);*/
win = ((GtkWidget*)pane)->window;
if (!win)
return;
/* TODO: I should probably also check this return value */
CandyDrawPanePrivate *priv = CANDY_DRAW_PANE_GET_PRIVATE(((CandyDrawPane*)pane));
priv->cr = gdk_cairo_create(win);
priv->region = gdk_drawable_get_clip_region(win);
candy_draw_pane_update(pane);
g_timeout_add(1000, candy_draw_pane_update, pane);
}
When I replaced my old code, which called gdk_cairo_create() and gdk_drawable_get_clip_region() during my event handlers, with this code, which calls them during candy_draw_pane_init(), the application would no longer draw. Stepping through with a debugger, I can see that pane->window and pane->parent are both NULL pointers while we are within candy_draw_pane_init(). The pointers are valid later, in the Gtk event processing loop. This leads me to believe that the inherited members have not yet been initialized when my derived class' "_init()" method is called. I'm sure this is just the nature of the Gtk+ runtime environment.
So how is this sort of thing typically handled? I could add logic to my event handlers to check priv->cr and priv->region for NULL, and call gdk_cairo_create() and gdk_drawable_get_clip_region() if they are still NULL. Or I could add a "post-init" method to my CandyDrawPane widget and call it explicitly after I call candy_draw_pane_new(). I'm sure lots of other people have encountered this sort of scenario, so is there a clean and conventional way to handle it?
This is my first real foray into object-oriented C, so please excuse me if I'm using any terminology incorrectly. I think one source of my confusion is that Gtk has separate concepts of instance and class initialization. C++ may do something similar "under the hood," but if so, it isn't as obvious to the coder.
I have a feeling that if this was C++, most of the the code that's going into candy_draw_pane_init() would be in the class constructor, and any secondary initialization that depended on the constructor having completed would go into an "Init()" method (which of course is not a feature of the language, but just a commonly used convention). Is there an analogous convention for Gtk+? Or perhaps someone can give a good overview of the flow of control when these widgets are instantiated. I have not been very impressed with the quality of the official Gnome documentation. Much of it is either too high-level, contains errors and typos in code, or has broken links or missing examples. And of course the heavy use of macros makes it a little harder to follow even my own code (in this respect it reminds me of Win32 GUI development). In short, I'm sure I can struggle through this on my own and make it work, but I'd like to hear from someone experienced with Gtk+ and C what the "right" way to do this is.
For completeness, here is the header where I set up my custom widget:
#ifndef __GTKCAIRO_H__
#define __GTKCAIRO_H__ 1
#include <gtk/gtk.h>
/* Following tutorial; see gtkcairo.c */
/* Not sure about naming convention; may need revisiting */
G_BEGIN_DECLS
#define CANDY_DRAW_PANE_TYPE (candy_draw_pane_get_type())
#define CANDY_DRAW_PANE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CANDY_DRAW_PANE_TYPE, CandyDrawPane))
#define CANDY_DRAW_PANE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass)CANDY_DRAW_PANE_TYPE, CandyDrawPaneClass))
#define IS_CANDY_DRAW_PANE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CANDY_DRAW_PANE_TYPE))
#define IS_CANDY_DRAW_PANE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CANDY_DRAW_PANE_TYPE))
// official gtk tutorial, which seems to be of higher quality, does not use this.
// #define CANDY_DRAW_PANE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CANDY_DRAW_PANE_TYPE, CandyDrawPaneClass))
typedef struct {
GtkDrawingArea parent;
/* private */
} CandyDrawPane;
typedef struct {
GtkDrawingAreaClass parent_class;
} CandyDrawPaneClass;
/* method prototypes */
GtkWidget* candy_draw_pane_new(void);
GType candy_draw_pane_get_type(void);
void candy_draw_pane_clear(CandyDrawPane *cdp);
G_END_DECLS
#endif
Any insight is much appreciated. I do realize I could use a code-generating IDE and crank something out more quickly, and probably dodge having to deal with some of this stuff, but the whole point of this exercise is to get a good grasp of the Gtk runtime, so I'd prefer to write the boilerplate by hand.
This article, A Gentle Introduction to GObject Construction, may help you. Here are some tips that I thought of while looking at your code and your questions:
If your priv->cr and priv->region pointers have to change whenever the widget's GDK window changes, then you could also move that code into a signal handler for the notify::window signal. notify is a signal that fires whenever an object's property is changed, and you can narrow down the signal emission to listen to a specific property by appending it to the name of the signal like that.
You don't need to check the return value from the GET_PRIVATE macro. Looking at the source code for g_type_instance_get_private(), it can return NULL in the case of an error, but it's really unlikely, and will print warnings to the terminal. My feeling is that if GET_PRIVATE returns NULL then something has gone really wrong and you won't be able to recover and continue executing the program anyway.
You're not setting up private storage as a global variable. Where are you declaring this global variable? I only see a struct and typedef declaration at the global level. What you are most likely doing, and what is the usual practice, is calling g_type_class_add_private() in the class_init function. This reserves space within each object for your private struct. Then when you need to use it, g_type_instance_get_private() gives you a pointer to this space.
The init method is the equivalent to a constructor in C++. The class_init method has no equivalent, because all the work done there is done behind the scenes in C++. For example, in a class_init function, you might specify which functions override the parent class's virtual functions. In C++, you simply do this by defining a method in the class with the same name as the virtual method you want to override.
As far as I can tell, the only problem with your code is the fact that the GdkWindow of a GtkWidget (widget->window) is only set when the widget has been realized, which normally happens when gtk_widget_show is called. You can tell it to realize earlier by calling gtk_widget_realize, but the documentation recommends connecting to the draw or realize signal instead.
I am currently trying to write a UI for a Data Acquistion System in Visual Studio C++ 2010, and I am having a lot of trouble dealing with the interfacing of the third party libraries I am using and Windows Forms. The two libraries I am using are DAQX, a C library for a Data Acqustion System, and VITCam, a C++ library for a 1394 High Speed Camera. It's extremely frustrating trying to work with these libraries and any UI library that VS has to offer, as none of the function arguments ever get along.
DAQX uses windows types like WORD and DWORD, in normal C fashion, and when I'm writing a normal program, no UI involved, it works fine, but Windows Forms seems to hate anytime I want to make a simple DWORD Array inside the class.
VITCam is even worse. I can open the camera fine, but I am completely lost when it comes to trying to put the image on the screen somehow. I haven't uncovered an equivalanet, easy to follow way for putting it to the screen as to how the documentation puts it:
CDC* pDC=GetDC(); // obtain the device context for your window...
// move the image data
::SetDIBitsToDevice(pDC->m_hDC,0,0,
(int) (MyCam.GetDispBuf()->bmiHeader.biWidth),
(int) (MyCam.GetDispBuf()->bmiHeader.biHeight),
0,0,0,(WORD) (WORD) MyCam.GetDispBuf()->bmiHeader.biHeight,
MyCam.GetDispPixels(),MyCam.GetDispBuf(),
DIB_RGB_COLORS);
I can barely follow it as is. So, without doing to much blathering, How do most people work with static unmanaged libraries that were not developed with Windows Forms in mind? I've tried MFC as the VITCam documentations mentioned it, but it makes very little sense and isn't as intuitive as Windows Forms feels.
Edit:
This is the error message I get when trying to use a normal (at least to me) array.
Error 1 error C4368: cannot define 'buffer' as a member of managed 'WirelessHeadImpact::Form1': mixed types are not supported
And it points to this line:
private:
WORD buffer[BUFFSIZE*CHANCOUNT];
What I had before was this:
static array<WORD>^ _buffer;
And within a function I create the former array, pass it to the function, then return the latter after looping through and updating the array.
WORD buffer[BUFFSIZE*CHANCOUNT];
DWORD scansCollected = 0;
while (total_scans < SCANS) {
daqAdcTransferBufData(_handle, buffer, BUFFSIZE, DabtmWait, &scansCollected);
if (scansCollected > 0) {
for (WORD i=0;i<scansCollected;i++) {
_buffer[i] = buffer[i];
}
mixed type support is removed in Visual C++ 2005. If you want to associate a DWORD array to a managed class, use new (not gcnew) to allocate the array itself on the native heap and save the pointer of the array in the class.
by the way, you cannot pass addresses of objects on the managed heap to a native function without pinning the object, otherwise the GC is free to move the object at any time. If you want to pass a managed value to a native function, make sure your pass by value or the object is pinned.
It helps the readers if you post the actual error message you are getting, instead of having to guess out from your question.
what is the difference between these two function calls:
menu_item_new_with_labelex vs gtk_menu_item_new_with_label
gtk_menu_item_new_with_label() is a standard gtk constructor that creates a GtkMenuItem containing a GtkAccelLabel with the specified text.
gtk_menu_item_new_with_labelex() is not a standard function; it does not exist in any of the gtk header files; in fact, google has never heard of it. If you see it in your code, it's probably some sort of a wrapper created by another person in your team.