GTK+ 3: Como fazer rolagem de um Gtk::TextView para última linha inserida?

1. GTK+ 3: Como fazer rolagem de um Gtk::TextView para última linha inserida?

M.
XProtoman

(usa Fedora)

Enviado em 20/10/2017 - 22:09h

Boa noite a todos,

Estou com problema com rolagem automática numa textview em GTK.

Minha tentativa de rolagem, depois de um tempo o programa encerrar por "falha de segmentação":

#include <iostream>
#include <thread>
#include <unistd.h>
#include <gtkmm.h>

void imprimir(bool *estado, Gtk::TextView *visao_de_texto, Glib::RefPtr <Gtk::TextBuffer> buffer_de_texto)
{
for ( size_t segundos = 1;
*estado;
segundos++ )
{
sleep(1);
buffer_de_texto->insert(buffer_de_texto->end(), std::string("Dormir ") + std::to_string(segundos) + std::string(" segundos...\n"));
// Minha tentativa
visao_de_texto->scroll_to(buffer_de_texto->get_insert(), 0, 0, 0);
}
}

int main(int argc, char *argv[])
{
Glib::RefPtr <Gtk::Application> aplicacao = Gtk::Application::create(argc, argv, "Exemplo.com");
// TextBuffer
Glib::RefPtr <Gtk::TextBuffer> buffer_de_texto = Gtk::TextBuffer::create();
// TextView
Gtk::TextView visao_de_texto;
visao_de_texto.property_editable() = false;
visao_de_texto.set_buffer(buffer_de_texto);
visao_de_texto.show();
// ScrolledWindow
Gtk::ScrolledWindow janela_de_rolamento;
janela_de_rolamento.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
janela_de_rolamento.add(visao_de_texto);
janela_de_rolamento.show();
// Window
Gtk::Window janela;
janela.set_default_size(320, 240);
janela.add(janela_de_rolamento);
janela.show();
// Thread
bool estado = true;
std::thread thread(imprimir, &estado, &visao_de_texto, buffer_de_texto);
// Resultado
int resultado = aplicacao->run(janela);
estado = false;
thread.join();
return resultado;
}


Para compilar:
g++ -O2 -std=c++11 -pedantic-errors -Wall -Werror -Wextra -fstack-protector-all -pthread `pkg-config --cflags --libs gtkmm-3.0` teste.cpp -o teste.run 



  


2. Re: GTK+ 3: Como fazer rolagem de um Gtk::TextView para última linha inserida?

M.
XProtoman

(usa Fedora)

Enviado em 20/10/2017 - 23:02h

Encontrei esse exemplo, mas ele parece ser imperfeito(não faz rolagem em algums momentos):
https://developer.gnome.org/gtkmm-tutorial/stable/sec-multithread-example.html.en

O exemplo também além de não resolver completamente o problema é um pouco complicado.

____________________
“Mas nós sabemos que a razão de a maioria estar aqui, é a nossa afinidade com a desobediência!” (Morpheus)


3. Re: GTK+ 3: Como fazer rolagem de um Gtk::TextView para última linha inserida?

M.
XProtoman

(usa Fedora)

Enviado em 20/10/2017 - 23:33h

Acho que encontrei a solução, mas ainda estou testando para ver se falha também:
#include <iostream>
#include <thread>
#include <unistd.h>
#include <gtkmm.h>

//void imprimir(bool *estado, Gtk::TextView *visao_de_texto, Glib::RefPtr <Gtk::TextBuffer> buffer_de_texto)
void imprimir(bool *estado, Glib::RefPtr <Gtk::TextBuffer> buffer_de_texto, Gtk::ScrolledWindow *janela_de_rolamento)
{
Glib::RefPtr <Gtk::Adjustment> adj;
for ( size_t segundos = 1;
*estado;
segundos++ )
{
sleep(1);
buffer_de_texto->insert(buffer_de_texto->end(), std::string("Dormir ") + std::to_string(segundos) + std::string(" segundos...\n"));
adj = janela_de_rolamento->get_vadjustment();
adj->set_value(adj->get_upper());
janela_de_rolamento->set_vadjustment(adj);
// Minha tentativa
//visao_de_texto->scroll_to(buffer_de_texto->get_insert(), 0, 0, 0);
}
}

int main(int argc, char *argv[])
{
Glib::RefPtr <Gtk::Application> aplicacao = Gtk::Application::create(argc, argv, "Exemplo.com");
// TextBuffer
Glib::RefPtr <Gtk::TextBuffer> buffer_de_texto = Gtk::TextBuffer::create();
// TextView
Gtk::TextView visao_de_texto;
visao_de_texto.property_editable() = false;
visao_de_texto.set_buffer(buffer_de_texto);
visao_de_texto.show();
// ScrolledWindow
Gtk::ScrolledWindow janela_de_rolamento;
janela_de_rolamento.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
janela_de_rolamento.add(visao_de_texto);
janela_de_rolamento.show();
// Window
Gtk::Window janela;
janela.set_default_size(320, 240);
janela.add(janela_de_rolamento);
janela.show();
// Thread
bool estado = true;
std::thread thread(imprimir, &estado, buffer_de_texto, &janela_de_rolamento);
// Resultado
int resultado = aplicacao->run(janela);
estado = false;
thread.join();
return resultado;
}


EDIT: Durantes os testes falhou também, porém o comportamento é o que quero, o comportamento está correto.
EDIT 2: Parece um bug de thread, porque estou usando um thread.

____________________
“Mas nós sabemos que a razão de a maioria estar aqui, é a nossa afinidade com a desobediência!” (Morpheus)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts