How to print only blue characters in textview - python

I want to get the characters printed only in blue.
How to do it?
Here is the sample program code, which is a fragment of most of the program.
I would be very grateful for your help.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
class TextViewWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="awesome gui")
self.set_resizable(True)
self.set_default_size(700, 550)
self.grid = Gtk.Grid()
self.add(self.grid)
self.create_textview()
self.buffer = []
def create_textview(self):
scrolledwindow = Gtk.ScrolledWindow()
scrolledwindow.set_hexpand(True)
scrolledwindow.set_vexpand(True)
self.grid.attach(scrolledwindow, 0, 2, 80, 1)
self.textview = Gtk.TextView()
scrolledwindow.add(self.textview)
self.textbuffer = self.textview.get_buffer()
self.textview.set_editable(False)
self.textview.set_cursor_visible(False)
self.textview.connect("key-press-event", self.on_key_down)
def on_key_down(self, widget, event, data=None):
znak_p = event.string
end_iter_m = self.textbuffer.get_iter_at_line_offset(1, 1)
qwerty_tag = self.textbuffer.create_tag(None, editable=True, foreground="blue")
self.textbuffer.insert_with_tags(end_iter_m, znak_p, qwerty_tag)
win = TextViewWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

Your on_key_down handler is wrong:
you are creating an anonymous tag every time you're pressing a key
you are using an invalid string for the GtkTextTag:foreground property
you are not returning a value from the callback telling GTK whether you handled the event (and thus should stop the event propagation) or not.
The GtkTextTag:foreground property uses the same format as the gdk_rgba_parse() function; if you want a blue color, you should use rgba(0.0, 0.0, 1.0, 1.0) instead of "blue".
A correct handler is:
def on_key_down(self, widget, event, data=None):
znak_p = event.string
end_iter_m = self.textbuffer.get
self.textbuffer.insert_with_tags(end_iter_m, znak_p, self.qwerty_tag)
return True

Related

python Gtk3 - Set label of button to default value of None

I am trying to reset a label of a button to its initial (default) value of None, which does not work as expected. Here's the minimal example:
from gi import require_version
require_version('Gtk', '3.0')
from gi.repository import Gtk
class GUI(Gtk.Window):
def __init__(self):
super().__init__()
self.connect('destroy', Gtk.main_quit)
self.set_position(Gtk.WindowPosition.CENTER)
self.grid = Gtk.Grid(hexpand=True, vexpand=True)
self.add(self.grid)
button = Gtk.Button(hexpand=True, vexpand=True)
self.grid.attach(button, 0, 0, 1, 1)
button.connect('clicked', self.on_button_clicked)
def on_button_clicked(self, button: Gtk.Button) -> None:
print(label := button.get_label(), type(label))
button.set_label(label)
def main() -> None:
win = GUI()
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
Result:
$ python example.py
None <class 'NoneType'>
Traceback (most recent call last):
File "/home/neumann/example.py", line 21, in on_button_clicked
button.set_label(label)
TypeError: Argument 1 does not allow None as a value
What's the correct way to do this?
Note: Before somebody suggests it: I do not want to set the label to an empty string, since that will change the size of the button, which is noticeable on a larger grid of buttons:
from gi import require_version
require_version('Gtk', '3.0')
from gi.repository import Gtk
class GUI(Gtk.Window):
def __init__(self):
super().__init__()
self.connect('destroy', Gtk.main_quit)
self.set_position(Gtk.WindowPosition.CENTER)
self.grid = Gtk.Grid(hexpand=True, vexpand=True)
self.add(self.grid)
for x in range(3):
button = Gtk.Button(hexpand=True, vexpand=True)
button.connect('clicked', self.on_button_clicked)
self.grid.attach(button, x, 0, 1, 1)
def on_button_clicked(self, button: Gtk.Button) -> None:
print(label := button.get_label(), type(label))
button.set_label('')
def main() -> None:
win = GUI()
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
I'm not sure what your use case is, but you can try adding a GtkLabel child and set the string there:
from gi import require_version
require_version('Gtk', '3.0')
from gi.repository import Gtk
class GUI(Gtk.Window):
def __init__(self):
super().__init__()
self.connect('destroy', Gtk.main_quit)
self.set_position(Gtk.WindowPosition.CENTER)
self.grid = Gtk.Grid(hexpand=True, vexpand=True)
self.add(self.grid)
for x in range(3):
button = Gtk.Button(hexpand=True, vexpand=True)
label = Gtk.Label()
button.add(label)
button.connect('clicked', self.on_button_clicked)
self.grid.attach(button, x, 0, 1, 1)
def on_button_clicked(self, button: Gtk.Button) -> None:
label = button.get_child()
print(text := label.get_label(), type(text))
label.set_label('')
# or hide it if you want
# label.hide()
def main() -> None:
win = GUI()
win.show_all()
Gtk.main()
if __name__ == '__main__':
main()
GtkButton may be creating the internal GtkLabel child only when a label is set (which should be a valid string). And since the hexpand and vexpand for the GtkButton are set to True, they may be getting propagated to the internal GtkLabel.
If you simply want all the buttons to have same width and height, you may only need grid.set_row_homogeneous() and grid.set_column_homogeneous()

Adding widget in callback in GTK

How can I add a new widget from a callback function within a class? For example, I have a Gtk.Box and Gtk.Button and I want to add Gtk.Label to the Gtk.Box from callback function connected to button click. (this code doesn't work)
import gi
import os
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk, GObject, Gio
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Delete Screenshots")
self.main_grid = Gtk.Grid()
self.main_grid.set_row_homogeneous(True)
self.add(self.main_grid)
self.screen_label = Gtk.Label()
self.screen_label.set_text("Test Label")
self.screen_label2 = Gtk.Label()
self.screen_label2.set_text("Test Label2")
self.label_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.label_box.homogeneous = True
self.button_search = Gtk.Button(label="Search")
self.button_search.connect("clicked", self.on_button_search_clicked)
self.button_delete = Gtk.Button(label="Delete")
self.button_delete.connect("clicked", self.on_button_delete_clicked)
self.main_grid.add(self.button_search);
self.main_grid.attach(self.button_delete, 1, 0, 1, 1);
self.main_grid.attach(self.label_box, 0, 1, 1, 1)
def on_button_search_clicked(self, widget):
self.label_box.pack_start(self.screen_label, True, True, 0)
def on_button_delete_clicked(self, widget):
print("Delete")
win = MainWindow()
win.set_default_size(50, 30)
win.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
How to add something to label_box from on_button_search_clicked?
Your code is basically correct. However all widgets need to be shown by either calling show() on them or show_all() on a parent widget. In your code, show_all() is called on the MainWindow instance. At that time, the widget you are adding in your callback is not attached to the window or any of its children. It will thus not be included in the show_all() call.
To fix this, simply call show() on your label in the callback:
...
def on_button_search_clicked(self, widget):
self.label_box.pack_start(self.screen_label, True, True, 0)
self.screen_label.show()
...

Python Gtk3 - Scroll TextView inside of ScrolledWindow by mouse and courser position

I have some text in a Gtk.TextView
When I select the text with my mouse or navigate the cursor beyond the bottom edge I cannot se my selection because it does not scroll.
So I think I need to get cursor position and set treeview to this position.
And mouse position while button is clicked and move treeview to this position.
https://lazka.github.io/pgi-docs/Gtk-3.0/classes/TreeView
https://lazka.github.io/pgi-docs/Gtk-3.0/classes/ScrolledWindow
https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Widget
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class ScrolledWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(200, 200)
self.connect("destroy", Gtk.main_quit)
self.scrolledwindow = Gtk.ScrolledWindow()
self.add(self.scrolledwindow)
box = Gtk.Box()
self.scrolledwindow.add(box)
textview = Gtk.TextView()
box.pack_start(textview, True, True, 10)
textview.connect("move-cursor", self.move_cursor_event) # arrow keys
textview.connect("key-press-event", self.key_press_event) # keyboard input
textview.connect("button-press-event", self.button_press_event) # mouse click
textbuffer = textview.get_buffer()
text = 50*"Hello World\n"
textbuffer.set_text(text, len(text))
def move_cursor_event(self, tree_view, step, count, extend_selection):
print "move_cursor_event", step, count, extend_selection
def key_press_event(self, widget, event):
print "key_press_event", event
def button_press_event(self, widget, event):
print "button_press_event", event.x, event.y
position = self.scrolledwindow.get_vadjustment()
position.set_value(350)
self.scrolledwindow.set_vadjustment(position) #scroll to the middle of the scolled window
window = ScrolledWindow()
window.show_all()
Gtk.main()
Thanks
edit1
here is a very basic solution I found for scrolling the window to the cursor position changed by arrow keys:
def move_cursor_event(self, tree_view, step, count, extend_selection):
rect = tree_view.get_cursor_locations()
self.scroll_y(rect.strong.y)
def scroll_y(self, ypos):
vadj = self.scrolled_window.get_vadjustment()
vadj.set_value(ypos-80)
self.scrolled_window.set_vadjustment(vadj)
The problem here is that textview is put inside a box, which is then put inside self.scrolledwindow. When the TextView is inside a Box, it prevents the ScrolledWindow from recognizing that the TextView needs to be scrolled. Placing the TextView directly in the ScrolledWindow should fix this problem. Here is what the code should look like:
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class ScrolledWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_default_size(200, 200)
self.connect("destroy", Gtk.main_quit)
self.scrolledwindow = Gtk.ScrolledWindow()
self.add(self.scrolledwindow)
textview = Gtk.TextView()
self.scrolledwindow.add(textview)
textbuffer = textview.get_buffer()
text = 50*"Hello World\n"
textbuffer.set_text(text, len(text)) #scroll to the middle of the scolled window
window = ScrolledWindow()
window.show_all()
Gtk.main()

How to properly show and hide GTK window in python

So I have the following code (python 2.7) that checks for a combination of keypresses and shows/hides a gtk window with a few gtk entry boxes. The show/hide works until the window locks up and stops responding, and the inner part of the window turns black. I have to kill the process and start it up again once that window turns black. I've tried all different combinations of show_all() and returning True after hiding the window to no avail. I'm not sure what I'm doing wrong here.
In the end I'd like to be able to press this key combination and show/hide this window without the contents going away.
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import pyxhook
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Configurator")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.ipEntry = Gtk.Entry()
self.ipEntry.set_text("IP Address")
self.maskEntry = Gtk.Entry()
self.maskEntry.set_text("NetMask")
self.gatewayEntry = Gtk.Entry()
self.gatewayEntry.set_text("gatewayEntry")
self.button1 = Gtk.Button(label="Save")
self.button1.connect("clicked", self.on_button1_clicked)
self.box.pack_start(self.ipEntry, True, True, 0)
self.box.pack_start(self.maskEntry, True, True, 0)
self.box.pack_start(self.gatewayEntry, True, True, 0)
self.box.pack_start(self.button1, True, True, 0)
#catch window destroy event and stop it from happening
self.connect('delete-event', self.on_destroy)
def on_button1_clicked(self, widget):
print("Hello")
def on_destroy(self, widget=None, *data):
print("tried to destroy")
self.hide()
return True
#list of ascii keypresses to test if a certain combination of keys is pressed
keypresses = []
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
win.set_keep_above(True)
def OnKeyboardEvent(event):
#ascii 227 is l_control, ascii 225 is l_shift, ascii 120 is x
#bring the following external variables into the scope of this function
global keypresses
global win
#check if gtk window is hidden or visible
isVisible = win.get_property("visible")
#store our keypress if it is worthy of being stored (we started with a control character)
if event.Ascii == 227 or ( len(keypresses) >= 1 and keypresses[0] == 227 ):
print("here" + str(len(keypresses)))
keypresses.append(event.Ascii)
#check if we have three items in keypresses to compare, then see if it's the right combination
if len(keypresses) == 3 and keypresses[0] == 227 and keypresses[1] == 225 and keypresses[2] == 120:
#show/hide our window
if isVisible:
win.hide()
del keypresses[:]
keypresses = []
else:
win.show_all()
#clear out our list to compare again
del keypresses[:]
keypresses = []
elif len(keypresses) >= 3:
del keypresses[:]
keypresses = []
#create instance of hook manager
HookManager = pyxhook.HookManager()
#define our callback to fire when a key is pressed
HookManager.KeyDown = OnKeyboardEvent
#hook the keyboard
HookManager.HookKeyboard()
#start our listener
HookManager.start()
Gtk.main()
#close the hook listener when gtk main loop exits
HookManager.cancel()
Here is a small hack that tests the window show/hide when pressing F5. When you press it a second window will show or hide and i've tested for sometime without problems. Maybe it's the HookManager that somehow is messing with the Gtk/Glib mainloop. Nonetheless my method only works if there is a window to grab the key presses, so you will need, indeed, some form of grabbing key presses if your goal is to have no GUI:
#!/usr/bin/python
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gdk
#import pyxhook
class MyWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Configurator")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.ipEntry = Gtk.Entry()
self.ipEntry.set_text("IP Address")
self.maskEntry = Gtk.Entry()
self.maskEntry.set_text("NetMask")
self.gatewayEntry = Gtk.Entry()
self.gatewayEntry.set_text("gatewayEntry")
self.button1 = Gtk.Button(label="Save")
self.button1.connect("clicked", self.on_button1_clicked)
self.box.pack_start(self.ipEntry, True, True, 0)
self.box.pack_start(self.maskEntry, True, True, 0)
self.box.pack_start(self.gatewayEntry, True, True, 0)
self.box.pack_start(self.button1, True, True, 0)
#catch window destroy event and stop it from happening
self.connect('delete-event', self.on_destroy)
self.connect('key-press-event', self.on_keypress)
def on_keypress(self, widget, event):
global w
if event.keyval == Gdk.KEY_F5:
isVisible = w.get_property("visible")
if (isVisible):
w.hide()
else:
w.show()
print("Keypress")
def on_button1_clicked(self, widget):
print("Hello")
def on_destroy(self, widget=None, *data):
print("tried to destroy")
self.hide()
return False
w = MyWindow()
win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
win.set_keep_above(True)
Gtk.main()

GTK: How can the size of a TextView be set manually?

I am reworking a GUI from scratch using Glade + Python. It was previously done in Tkinter and I could set the height and width of several consoles.
Now, in GTK (newbie) I can't find a proper solution to this: specify a size to the TextView. I imagine it is done by nesting it in a block that sets the size. What's my best option?
Here's my case: http://pastebin.com/dx07HZnC
And a preview: http://www.tiikoni.com/tis/view/?id=24e83d2
As you can see the textView widgets are very short.
PyGTK2
textview = gtk.TextView()
textview.set_size_request(300,200) # W x H
textview.show()
window.add(textview)
I can't see your case, but I think that I can help you:
import pygtk
pygtk.require('2.0')
import gtk
import pango
class MyGUI:
def __init__( self, title):
self.window = gtk.Window()
self.title = title
self.window.set_title("Title")
self.window.set_size_request(260, 300) ***where 260 is Width and 300 is Height***
self.window.connect( "destroy", self.destroy)
self.create_interior()
self.window.show_all()
def create_interior( self):
self.mainbox = gtk.VBox()
self.window.add( self.mainbox)
# the textview
self.textview = gtk.TextView()
self.textbuffer = self.textview.get_buffer()
self.mainbox.pack_start( self.textview)
self.textview.show()
h_tag = self.textbuffer.create_tag( "h", size_points=16, weight=10)
position = self.textbuffer.get_end_iter()
self.textbuffer.insert( position, "Text...")
self.mainbox.show()
def main( self):
gtk.main()
def destroy( self, w):
gtk.main_quit()
if __name__ == "__main__":
m = MyGUI( "TextView example.")
m.main()

Categories