How to set Placeholder text in Gtk.TextView

2k Views Asked by At

I have been using Gtk Entry till now which offers set_placeholder_text method to set a placeholder text in it however, looking in the documentation , I found no such method for TextView .

Is there any way I can set placeholder text in Gtk Textview ?

1

There are 1 best solutions below

0
On BEST ANSWER

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:

  1. Set placeholder text as a variable
  2. Set the placeholder text as the default treeview text buffer content
  3. On focus in, if the text buffer equals the placeholder, means no previous input, so delete the text (placeholder text). Otherwise keep the content.
  4. 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:

enter image description here

Added a few widgets to keep the initial focus on other widgets.

Compare the behavior with the Gtk.Entry. It's very similar.