I'm trying replace a image from event_box but doesn't work.
When the user click in a Event box, I try remove the image from the event box and add another, but when I run just remove the image and not add another.
void selecFichas(GtkWidget *casillaAtril, gpointer data){
int i;
for(i = 0; i < LETRAS; i++)
if(casillaAtril == atrilJugador1[i]){
Element = i;
break;
}
gtk_container_remove(GTK_CONTAINER(atrilJugador1[Element]), fichasABC[coordImagen[Element][0]][coordImagen[Element][1]]);
gtk_container_add(GTK_CONTAINER(atrilJugador1[Element]), casillasAtriles[Element]);
}
Have you made sure to call gtk_widget_show() on the image that you added?
You can open up the GTK Inspector with Ctrl+D or Ctrl+I and check whether the new image is actually in there or not, and whether it is visible or not.
Related
We have a GTK3 user interface (coded in C) in an embedded system that must stay fixed width/height in order to fit the screen.
Basically it's a fixed grid of buttons on a touchscreen, where the buttons can contain a text label or a graphical image - and the grid MUST stay fixed, all buttons the same width & height, and fitting the screen 100%.
However, on updating button text/labels with longer strings the button expands to fit which is not what we want at all.
I can't post all the code but I believe this is the relevant button creation code that would affect what we're trying to do;
// Number buttons 1..n
buttonId = n;
bid = buttonId - 1; // Because zero-indexing, natch
dbp = &_context->buttons[bid]; // Data about button
// Create new button, attach to global buttons
dbp->btn = gtk_button_new();
// Button name != Button CSS#ID
snprintf(value, SHORT_STR, "BTN_%02d", buttonId );
gtk_widget_set_name(dbp->btn, value);
gtk_button_set_relief(GTK_BUTTON(dbp->btn), GTK_RELIEF_NORMAL/*GTK_RELIEF_NONE*/);
// Set text label
strncpy(dbp->text, value, MAX_BUTTON_TEXT);
gtk_button_set_label (GTK_BUTTON(dbp->btn), dbp->text);
// Attempt to make labels wrap - does nothing
label = gtk_bin_get_child(GTK_BIN(dbp->btn));
gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
//gtk_label_set_max_width_chars(GTK_LABEL(label), 0);
// Create new blank (&transprent) image
dbp->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, _context->innerButton.width, _conte$
gdk_pixbuf_fill(dbp->pixbuf, 0x00000000);
// Image holds pixbuf
dbp->image = (GtkImage*)gtk_image_new_from_pixbuf(dbp->pixbuf);
dbp->image_modified = 0;
// Attach image to button
gtk_button_set_image(GTK_BUTTON(dbp->btn), GTK_WIDGET(dbp->image));
// Adds an individual CSS provider per button to allow style changes
GtkStyleContext *context = gtk_widget_get_style_context(dbp->btn);
dbp->bp = gtk_css_provider_new();
// Set default colour from table of default colours
dbp->bg = get_default_colour(bid);
dbp->fg = get_label_colour(dbp->bg);
BuildButtonCSS("btnid_", buttonId, dbp->bg, dbp->fg, tstr, NULL);
// Convert CSS to provider
gtk_css_provider_load_from_data(dbp->bp, tstr, -1, NULL);
// Add provider to button
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(dbp->bp), GTK_STYLE_PROVIDER_PRIO$
// Give the button the CSS style/class corresponding to the one we just created for it
snprintf(value, SHORT_STR, "btnid_%02d", buttonId);
gtk_style_context_add_class(context, value);
g_object_unref(dbp->bp);
// Discourage expansion (again, doesn't appear to work when label gets too long)
gtk_widget_set_hexpand(dbp->btn, FALSE);
gtk_widget_set_vexpand(dbp->btn, FALSE);
// Attach button to grid
gtk_grid_attach(GTK_GRID(_grid), dbp->btn, c, r, 1, 1);
g_signal_connect(dbp->btn, "button_press_event", G_CALLBACK(button_press_callback), GINT_TO_P$
g_signal_connect(dbp->btn, "button_release_event", G_CALLBACK(button_release_callback), GINT_$
dbp->initialised = 1;
However when we update text within a button, it renders as a single (non-wrapped) line of text and causes the button to expand and totally bu&&er up the layout.
There's two problems here;
The text should wrap, the buttons have plenty of height but the text remains a single line
The buttons should be absoltuely FIXED width & height no matter what
This feels like it should be simple to do, but I'm not very familiar with GTK and all the examples out there seem to assume that you'd want everything to flex and resize itself all the time.
Edit: Tried Alexander Dmitriev's suggestion to use ellipsize - didn't seem to work although threw no errors;
// Experiment; ellipsize
label = gtk_bin_get_child(GTK_BIN(dbp->btn));
gtk_label_set_ellipsize(GTK_LABEL(label),PANGO_ELLIPSIZE_END);
gtk_label_set_max_width_chars(GTK_LABEL(label), 14);
I also tried this exmaple by creating a GtkWidget label, applying the properties to it and then adding it to the button - but it seems gtk_button_set_label will only accept a string not a label.
is there any thing got changed for images. Circular button shows different with projections. Button use to display proper circle before. Please see the screenshots for reference. Please advise.
Button b;
Button finished = new Button("");
FontImage.setMaterialIcon(finished, FontImage.MATERIAL_CHECK, 8.0f);
Test.makeBorderRound(finished);
Style bg = finished.getDisabledStyle();
finished.setDisabledStyle(bg);
b = finished;
b.setDisabledStyle(bg);
public static void makeBorderRound(Component cmp) {
makeBorderRound(cmp.getUnselectedStyle());
makeBorderRound(cmp.getSelectedStyle());
makeBorderRound(cmp.getPressedStyle());
makeBorderRound(cmp.getDisabledStyle());
}
public static void makeBorderRound(Style stl) {
stl.setBorder(RoundBorder.create().
rectangle(true).
color(stl.getBgColor()).
opacity(stl.getBgTransparency() & 0xff));
stl.setPaddingUnit(Style.UNIT_TYPE_DIPS);
stl.setPaddingLeft(1);
stl.setPaddingRight(1);
}
That's the icon peaking out from the edges of the round border. We fixed a bug where the background wasn't painted for some cases.
A simple workaround would be:
Button finished = new Button("");
finished.getAllStyles().setBgTransparency(0);
FontImage.setMaterialIcon(finished, FontImage.MATERIAL_CHECK, 8.0f);
finished.getAllStyles().setBgTransparency(255);
Test.makeBorderRound(finished);
By setting the bg transparency to 0 the icon will have transparency, this will then get overwritten by the second line after the icons are created.
I have UserControl in wpf 4.0 which contains buttons , labels , textboxes etc....
I want to loop those controls and when I get a buuton , I want to take it's name and save it to my list . Basically , all I want to do is to create a Names_list of all my buttons in the UserControl.
I have a method that iterates all the controls and if it finds a button , it saves it's name -
public void EnumVisual(Visual myVisual)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
{
// Retrieve child visual at specified index value.
Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
Button _button = childVisual as Button;
if (_button != null)
{
Class_Button _newButtonClass = new Class_Button();
if (_button.Name != null)
{
_newButtonClass.ButtonName = _button.Name;
}
ButtonsList.Add(_newButtonClass);
}
// Enumerate children of the child visual object.
EnumVisual(childVisual);
}
}
I always get an empty list.
When I enter in to the code by debugging it and I watch the VisualTree of my UserControl , I see all the Panels and GroupBoxes and Grids but I dont see buttons , labels and texboxes although every control has a x:Name and every control is x:FieldModifier="public". This is very odd....And I cant understand the reason for that as well as how to solve this problem...
can anyone tell what I am doing wrong?
thanks
As suggested by #GazTheDestroyer you want to make sure the control template has been applied before trying to use VisualTreeHelper. Try:
public void EnumVisual(Visual myVisual)
{
if(myVisual is FrameworkElement)
((FrameworkElement)myVisual).ApplyTemplate();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
{
// Retrieve child visual at specified index value.
Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);
Button _button = childVisual as Button;
if (_button != null)
{
Class_Button _newButtonClass = new Class_Button();
if (_button.Name != null)
{
_newButtonClass.ButtonName = _button.Name;
}
ButtonsList.Add(_newButtonClass);
}
// Enumerate children of the child visual object.
EnumVisual(childVisual);
}
}
You can use a tool like Snoop
or WPF Inspector
to examine the visual tree of your control.
If these tools are able to do so, the error must be somewhere in your code, right?
Hopefully this is an easy question to answer! I am trying to use GtkEntryCompletion (a la the example here) but while this code works I can't seem to get the GtkEntry to present the autocomplete results when I set the text of the field programatically. What I am trying to accomplish is a semi pre-filled text entry that is already presenting the user with some autocomplete options.
To set the text I have tried using the functions gtk_entry_set_text(...), gtk_entry_buffer_insert_text(...) and even gtk_entry_buffer_emit_inserted_text(...) but to no avail. Is there a way to do this in such a way as to act like regular user input and display the suggestions?
I think you need to call gtk_entry_completion_complete after setting the text.
EDIT
Sorry #Tylter, but wow, this is way more difficult than I imagined. The only way I can figure out how to do it is to actually send the keypress event to the window.
gtk_widget_grab_focus(entry);
GdkEvent new_event;
new_event.key.type = GDK_KEY_PRESS;
new_event.key.window = gtk_widget_get_parent_window(entry);
new_event.key.send_event = TRUE;
new_event.key.time = GDK_CURRENT_TIME;
new_event.key.keyval = 0x053; // capital S
new_event.key.state = GDK_KEY_PRESS_MASK;
new_event.key.length = 0;
new_event.key.string = 0;
new_event.key.hardware_keycode = 0;
new_event.key.group = 0;
gdk_event_put((gpointer)&new_event);
EDIT 2
Are you using a GtkDialog for your pop-up? I coded this up really quick and it seems to work. Here you would be creating the dialog in a button click event:
static void click_event( GtkWidget *widget,
gpointer data )
{
GtkWidget* window = gtk_dialog_new ();
completion = create_completion();
entry = gtk_entry_new();
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
// add entry to dialog
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
entry, TRUE, TRUE, 0);
gtk_widget_show(entry);
gtk_widget_show(window); // you must show the window before sending the keypress event
gtk_widget_grab_focus(entry);
GdkEvent new_event;
new_event.key.type = GDK_KEY_PRESS;
new_event.key.window = gtk_widget_get_parent_window(entry);
new_event.key.send_event = TRUE;
new_event.key.time = GDK_CURRENT_TIME;
new_event.key.keyval = 0x053; // capital S
new_event.key.state = GDK_KEY_PRESS_MASK;
new_event.key.length = 0;
new_event.key.string = 0;
new_event.key.hardware_keycode = 0;
new_event.key.group = 0;
gdk_event_put((gpointer)&new_event);
}
The only gotcha I saw with this is that your must show the dialog window before sending the keypress event.
I'd like to do some custom drawing to my windows desktop such that it appears to replace the desktop background (wallpaper). My first try was to get a DC for desktopListView and draw to it:
IntPtr desktopDC = GetWindowDC(desktopListView);
Graphics g = Graphics.FromHwnd(desktopDC); //<-- fails on out of memory error
I then tried to create a NativeWindow and capture the WM_PAINT message by assigning the native window's handle to the desktop and do my own drawing, but I was unable to see any messages to the desktop.
Ideally I'd like to do this in WPF and not windows forms at all. Any clue how to create a WPF window that I can draw to that sits beneath the desktop icons but on top of the wallpaper such that it ignores any mouse messages and the desktop continues to work normally?
If you get the window handle of the desktop, you can create a new window and add your own custom window as a child of that. Putting it behind the list view may give you the result you need, though I'm not 100% sure how well the transparency will work.
Found some code - Most of what you need is in the first part if you don't need to deal with multiple screens that change shape.
public void SetDesktopWindows()
{
Thread.Sleep(0);
while (this.Count < Screen.AllScreens.Length)
{
OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = new OrangeGuava.Desktop.DesktopWindow.DesktopControl();
User32.SetParent(dtc.Handle, User32.FindWindow("ProgMan", null));
this.Add(dtc);
}
int minx = 0;
int miny = 0;
foreach (Screen screen in Screen.AllScreens)
{
if (screen.Bounds.Left < minx) minx = screen.Bounds.Left;
if (screen.Bounds.Top < miny) miny = screen.Bounds.Top;
}
for (int i = Screen.AllScreens.Length; i < Count; i++)
{
OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = (OrangeGuava.Desktop.DesktopWindow.DesktopControl)this[i];
dtc.Hide();
}
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
OrangeGuava.Desktop.DesktopWindow.DesktopControl dtc = (OrangeGuava.Desktop.DesktopWindow.DesktopControl)this[i];
dtc.DeviceId = i.ToString();
Rectangle r = Screen.AllScreens[i].WorkingArea;
r.X -= minx;
r.Y -= miny;
dtc.SetBounds(r.X, r.Y, r.Width, r.Height);
dtc.displaySettingsChanged(null, null);
}
}
I've done this by having my window respond to the WM_WINDOWPOSCHANGING message by setting WINDOWPOS.hWndInsertAfter = HWND_BOTTOM. This says to the OS: make sure my window is underneath all other windows, and makes it appear as though your window is glued to the desktop.