raspberry pi1 중ltkmm의 2

개요


raspberry pi1로 gtkmm 해봤어요.
한번 해 보았다.

사진.



샘플 코드

#include <gtkmm.h>
#include <gtkmm/application.h>
#include <sstream>
#include <chrono>
#include <iostream>
#include <thread>
#include <mutex>

class ExampleWindow;
class ExampleWorker
{
public:
    ExampleWorker();
    void do_work(ExampleWindow * caller);
    void get_data(double * fraction_done, Glib::ustring * message) const;
    void stop_work();
    bool has_stopped() const;
private:
    mutable std::mutex m_Mutex;
    bool m_shall_stop;
    bool m_has_stopped;
    double m_fraction_done;
    Glib::ustring m_message;
};
class ExampleWindow: public Gtk::Window
{
public:
    ExampleWindow();
    void notify();
private:
    void on_start_button_clicked();
    void on_stop_button_clicked();
    void on_quit_button_clicked();
    void update_start_stop_buttons();
    void update_widgets();
    void on_notification_from_worker_thread();
    Gtk::Box m_VBox;
    Gtk::ButtonBox m_ButtonBox;
    Gtk::Button m_ButtonStart;
    Gtk::Button m_ButtonStop;
    Gtk::Button m_ButtonQuit;
    Gtk::ProgressBar m_ProgressBar;
    Gtk::ScrolledWindow m_ScrolledWindow;
    Gtk::TextView m_TextView;
    Glib::Dispatcher m_Dispatcher;
    ExampleWorker m_Worker;
    std::thread * m_WorkerThread;
};


ExampleWorker::ExampleWorker():
    m_Mutex(),
    m_shall_stop(false),
    m_has_stopped(false),
    m_fraction_done(0.0),
    m_message()
{
}
void ExampleWorker::get_data(double * fraction_done, Glib::ustring * message) const
{
    std::lock_guard<std::mutex> lock(m_Mutex);
    if (fraction_done) * fraction_done = m_fraction_done;
    if (message) * message = m_message;
}
void ExampleWorker::stop_work()
{
    std::lock_guard<std::mutex> lock(m_Mutex);
    m_shall_stop = true;
}
bool ExampleWorker::has_stopped() const
{
    std::lock_guard<std::mutex> lock(m_Mutex);
    return m_has_stopped;
}
void ExampleWorker::do_work(ExampleWindow* caller)
{
    {
        std::lock_guard<std::mutex> lock(m_Mutex);
        m_has_stopped = false;
        m_fraction_done = 0.0;
        m_message = "";
    }
    for (int i = 0; ; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(250));
        {
            std::lock_guard<std::mutex> lock(m_Mutex);
            m_fraction_done += 0.01;
            if (i % 4 == 3)
            {
                std::ostringstream ostr;
                ostr << (m_fraction_done * 100.0) << "% done\n";
                m_message += ostr.str();
            }
            if (m_fraction_done >= 1.0)
            {
                m_message += "Finished";
                break;
            }
            if (m_shall_stop)
            {
                m_message += "Stopped";
                break;
            }
        }
        caller->notify();
    }
    {
        std::lock_guard<std::mutex> lock(m_Mutex);
        m_shall_stop = false;
        m_has_stopped = true;
    }
    caller->notify();
}
ExampleWindow::ExampleWindow():
    m_VBox(Gtk::ORIENTATION_VERTICAL, 5),
    m_ButtonBox(Gtk::ORIENTATION_HORIZONTAL),
    m_ButtonStart("Start work"),
    m_ButtonStop("Stop work"),
    m_ButtonQuit("_Quit", true),
    m_ProgressBar(),
    m_ScrolledWindow(),
    m_TextView(),
    m_Dispatcher(),
    m_Worker(),
    m_WorkerThread(nullptr)
{
    set_title("Multi-threaded example");
    set_border_width(5);
    set_default_size(300, 300);
    add(m_VBox);
    m_VBox.pack_start(m_ProgressBar, Gtk::PACK_SHRINK);
    m_ProgressBar.set_text("Fraction done");
    m_ProgressBar.set_show_text();
    m_ScrolledWindow.add(m_TextView);
    m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
    m_VBox.pack_start(m_ScrolledWindow);
    m_TextView.set_editable(false);
    m_VBox.pack_start(m_ButtonBox, Gtk::PACK_SHRINK);
    m_ButtonBox.pack_start(m_ButtonStart, Gtk::PACK_SHRINK);
    m_ButtonBox.pack_start(m_ButtonStop, Gtk::PACK_SHRINK);
    m_ButtonBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK);
    m_ButtonBox.set_border_width(5);
    m_ButtonBox.set_spacing(5);
    m_ButtonBox.set_layout(Gtk::BUTTONBOX_END);
    m_ButtonStart.signal_clicked().connect(sigc::mem_fun(* this, &ExampleWindow::on_start_button_clicked));
    m_ButtonStop.signal_clicked().connect(sigc::mem_fun(* this, &ExampleWindow::on_stop_button_clicked));
    m_ButtonQuit.signal_clicked().connect(sigc::mem_fun(* this, &ExampleWindow::on_quit_button_clicked));
    m_Dispatcher.connect(sigc::mem_fun(* this, &ExampleWindow::on_notification_from_worker_thread));
    auto buffer = m_TextView.get_buffer();
    buffer->create_mark("last_line", buffer->end(), true);
    update_start_stop_buttons();
    show_all_children();
}
void ExampleWindow::on_start_button_clicked()
{
    if (m_WorkerThread)
    {
        std::cout << "Can't start a worker thread while another one is running." << std::endl;
    }
    else
    {
        m_WorkerThread = new std::thread([this] {
            m_Worker.do_work(this);
        });
    }
    update_start_stop_buttons();
}
void ExampleWindow::on_stop_button_clicked()
{
    if (!m_WorkerThread)
    {
        std::cout << "Can't stop a worker thread. None is running." << std::endl;
    }
    else
    {
        m_Worker.stop_work();
        m_ButtonStop.set_sensitive(false);
    }
}
void ExampleWindow::update_start_stop_buttons()
{
    const bool thread_is_running = m_WorkerThread != nullptr;
    m_ButtonStart.set_sensitive(!thread_is_running);
    m_ButtonStop.set_sensitive(thread_is_running);
}
void ExampleWindow::update_widgets()
{
    double fraction_done;
    Glib::ustring message_from_worker_thread;
    m_Worker.get_data(&fraction_done, &message_from_worker_thread);
    m_ProgressBar.set_fraction(fraction_done);
    if (message_from_worker_thread != m_TextView.get_buffer()->get_text())
    {
        auto buffer = m_TextView.get_buffer();
        buffer->set_text(message_from_worker_thread);
        Gtk::TextIter iter = buffer->end();
        iter.set_line_offset(0);
        auto mark = buffer->get_mark("last_line");
        buffer->move_mark(mark, iter);
        m_TextView.scroll_to(mark);
    }
}
void ExampleWindow::on_quit_button_clicked()
{
    if (m_WorkerThread)
    {
        m_Worker.stop_work();
        if (m_WorkerThread->joinable()) m_WorkerThread->join();
    }
    hide();
}
void ExampleWindow::notify()
{
    m_Dispatcher.emit();
}
void ExampleWindow::on_notification_from_worker_thread()
{
    if (m_WorkerThread && m_Worker.has_stopped())
    {
        if (m_WorkerThread->joinable()) m_WorkerThread->join();
        delete m_WorkerThread;
        m_WorkerThread = nullptr;
        update_start_stop_buttons();
    }
    update_widgets();
}
int main(int argc, char * argv[])
{
    auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
    ExampleWindow window;
    return app->run(window);
}



이상.

좋은 웹페이지 즐겨찾기