I think there was a question almost similar to this one. The idea is to, eg, use the focus-in-event
and focus-out-event
to check the text buffer content.
Example:
- Set placeholder text as a variable
- Set the placeholder text as the default treeview text buffer
content
- On focus in, if the text buffer equals the placeholder, means no
previous input, so delete the text (placeholder text). Otherwise
keep the content.
- On focus out, if the text buffer has no text then set the content
as the placeholder text. Otherwise do nothing.
The idea is that if no text or the existing text is the placeholder text it means there's no user input.
Python example
Glade ui file (save it as placeholder-textview.ui):
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkTextBuffer" id="textbuffer1">
<property name="text" translatable="yes">Please input text here...</property>
</object>
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="placeholder_text" translatable="yes">This is an entry and below is a textview</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTextView" id="textview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="vexpand">False</property>
<property name="buffer">textbuffer1</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Python code:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
def onFocusIn(self, event):
if (textbuf.get_text(textbuf.get_start_iter(), textbuf.get_end_iter(), True) == placeholderStr):
textbuf.set_text("")
return False
def onFocusOut(self, event):
if (textbuf.get_text(textbuf.get_start_iter(), textbuf.get_end_iter(), True) == ""):
textbuf.set_text(placeholderStr)
return False
placeholderStr = "This is the placeholder text..."
builder = Gtk.Builder()
builder.add_from_file("placeholder-textview.ui")
window = builder.get_object("window1")
textbuf = builder.get_object("textbuffer1")
textbuf.set_text(placeholderStr)
textview = builder.get_object("textview1")
textview.connect("focus-in-event", onFocusIn)
textview.connect("focus-out-event", onFocusOut)
window.connect ("destroy", Gtk.main_quit)
window.show_all()
Gtk.main()
Resulting UI:

Added a few widgets to keep the initial focus on other widgets.
Compare the behavior with the Gtk.Entry. It's very similar.