Search code examples
gtkbackground-color

Highlight a widget partially in GTK+


I have a list box in part of my interface, and I want to highlight the GtkListBoxRows individually by progress. You load several files, and my program works on it each file individually, and I want to highlight the list box row like a progress bar. It is very similar to a progress bar, just the contents inside are buttons and some text. Is there a specific Cairo/Pango function that allows the recoloring?


Solution

  • I have a solution here using Gtkmm (should be easily translatable to C). I have a series of 5 buttons aligned horizontally inside a container and a "Make progress" button. When you click on it, child buttons in the container are updated to show the progress:

    #include <iostream>
    #include <gtkmm.h>
    
    class MainWindow : public Gtk::ApplicationWindow
    {
    
    public:
    
        MainWindow();
    
    private:
    
        Gtk::Grid m_container;
        Gtk::Button m_progressButton;
    
        int m_progressTracker = 0;
    };
    
    MainWindow::MainWindow()
    : m_progressButton("Make progress...")
    {
        // Add five buttons to the container (horizontally):
        for(int index = 0; index < 5; ++index)
        {
            Gtk::Button* button = Gtk::make_managed<Gtk::Button>("B" + std::to_string(index));
            m_container.attach(*button, index, 0, 1, 1);
        }
    
        // Add a button to control progress:
        m_container.attach(m_progressButton, 0, 1, 5, 1);
    
        // Add handler to the progress button.
        m_progressButton.signal_clicked().connect(
            // Each time the button is clicked, the "hilighting" of the buttons
            // in the container progresses until completed:
            [this]()
            {
                Gtk::Widget* child = m_container.get_child_at(m_progressTracker, 0);
                if(child != nullptr)
                {
                    std::cout << "Making progress ..." << std::endl;
    
                    // Change the button's background color:
                    Glib::RefPtr<Gtk::CssProvider> cssProvider = Gtk::CssProvider::create();
                    cssProvider->load_from_data("button {background-image: image(cyan);}");
                    child->get_style_context()->add_provider(cssProvider, GTK_STYLE_PROVIDER_PRIORITY_USER);
        
                    // Update for next child...
                    ++m_progressTracker;
                }
            }
        );
    
        // Make m_container a child of the window:
        add(m_container);
    }
    
    int main(int argc, char *argv[])
    {
        std::cout << "Gtkmm version : " << gtk_get_major_version() << "."
                                        << gtk_get_minor_version() << "."
                                        << gtk_get_micro_version() << std::endl;
    
        auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
      
        MainWindow window;
        window.show_all();
      
        return app->run(window);
    }
    

    In your case, you will have to adapt the container and the signal (maybe you will need something else to trigger the redraw), but it should work pretty much the same as far as changing the background color is concerned. You can build this (using Gtkmm 3.24) with:

    g++ main.cpp -o example.out `pkg-config --cflags --libs gtkmm-3.0`