Is it Possible to set "Windows On-Screen Keyboard" as an input in sg.InputText field ( PySimpleGUI)? - input

Dears,
Is it Possible to set "Windows On-Screen Keyboard" as an input in sg.InputText field?
Thanks in advance
enter image description here ==> The Code
enter image description here ==> Desired Output
enter image description here ==> Split Keyboard to lines using "Menu Option"

Here's the demo code for you. Some functions for backspace key not built under PySimpleGUI, so tkinter code is required, like element.widget. The event for button 'OK' not included here. You can replace the keyboard string with yours.
import PySimpleGUI as sg
keys = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"]
chars = ''.join(keys)
lines = list(map(list, keys))
lines[0] += ["\u232B", "Esc"]
col = [[sg.Push()] + [sg.Button(key) for key in line] + [sg.Push()] for line in lines]
layout = [
[sg.Text("Username"), sg.Push(), sg.Input(key="Username")],
[sg.Text("Password"), sg.Push(), sg.Input(key="Password")],
[sg.Push(), sg.Button("OK"), sg.Button("Cancel"),sg.Push(), sg.Button("Keyboard")],
[sg.pin(sg.Column(col, visible=False, expand_x=True, key='Column', metadata=False), expand_x=True)],
]
window = sg.Window('ACCESS', layout)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Cancel"):
break
elif event == "Keyboard":
visible = window["Column"].metadata = not window["Column"].metadata
window["Column"].update(visible=visible)
elif event in chars:
element = window.find_element_with_focus()
if isinstance(element, sg.Input):
if element.widget.select_present():
element.widget.delete(sg.tk.SEL_FIRST, sg.tk.SEL_LAST)
element.widget.insert(sg.tk.INSERT, event)
elif event == "\u232B":
element = window.find_element_with_focus()
if element.widget.select_present():
element.widget.delete(sg.tk.SEL_FIRST, sg.tk.SEL_LAST)
else:
insert = element.widget.index(sg.tk.INSERT)
if insert > 0:
element.widget.delete(insert-1, insert)
window.close()
With MenuOption element, there's option enable_events, so tkinter call required here. There are three-line different keyboard, so each Column element for each keyboard line.
import PySimpleGUI as sg
def callback(var, index, mode):
window.write_event_value("Optionmenu", window['Optionmenu'].TKStringVar.get())
keys = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"]
chars = ''.join(keys)
lines = list(map(list, keys))
lines[0] += ["\u232B", "Esc"]
layout = [
[sg.Text("Username"), sg.Push(), sg.Input(key="Username")],
[sg.Text("Password"), sg.Push(), sg.Input(key="Password")],
[sg.Push(), sg.Button("OK"), sg.Button("Cancel"),sg.Push(), sg.OptionMenu([f"Keyboard Line {i+1}" for i in range(3)], key='Optionmenu')],
[sg.Column([[sg.Push()] + [sg.Button(key) for key in line] + [sg.Push()]], key=f"Keyboard Line {i+1}", expand_x=True, visible=False) for i, line in enumerate(lines)],
]
window = sg.Window('ACCESS', layout, finalize=True)
window['Optionmenu'].TKStringVar.trace("w", callback) # enable events
keyboard = None
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Cancel"):
break
elif event == "Optionmenu":
if keyboard is not None:
window[keyboard].update(visible=False)
keyboard = values["Optionmenu"]
window[keyboard].update(visible=True)
elif event in chars:
element = window.find_element_with_focus()
if isinstance(element, sg.Input):
if element.widget.select_present():
element.widget.delete(sg.tk.SEL_FIRST, sg.tk.SEL_LAST)
element.widget.insert(sg.tk.INSERT, event)
elif event == "\u232B":
element = window.find_element_with_focus()
if element.widget.select_present():
element.widget.delete(sg.tk.SEL_FIRST, sg.tk.SEL_LAST)
else:
insert = element.widget.index(sg.tk.INSERT)
if insert > 0:
element.widget.delete(insert-1, insert)
window.close()

Related

Query regarding a desired feature in PySimpleGUI TK version

I have built a graphic oriented package using the Graph element. I need to do keyboard input based on Graph Element coordinates. Currently I am using the events that come in from the keyboard to place characters on the Graph element using draw_text. It works but is a bit slow and I get into problems with interpreting the key codes I get back from different platforms and the overhead with me doing the echoing back on to the Graph element does not help.
My Question. In PySimpleGui(Tk) is there a way to use the Tk Entry function directly on Graph Coordinates?
IMO, it can be done like your request, but much complex.
Here only a simple way to enter text on a Graph element.
import PySimpleGUI as sg
font = ('Courier New', 16, 'bold')
layout = [
[sg.Input(expand_x=True, key='INPUT')],
[sg.Graph((320, 240), (0, 0), (320, 240), enable_events=True, key='GRAPH',
background_color='green')],
]
window = sg.Window('Draw Text', layout, margins=(0, 0), finalize=True)
entry, graph = window['INPUT'], window['GRAPH']
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'GRAPH':
location, text = values['GRAPH'], values['INPUT']
if text:
graph.draw_text(text, location, font=font, color='white', text_location=sg.TEXT_LOCATION_LEFT)
window.close()
Here, something like your request, but much complex and tkinter code required.
import PySimpleGUI as sg
def entry_callback(event, graph, entry_id, font, location, color):
widget = event.widget
text = widget.get()
graph.widget.delete(entry_id)
if text:
graph.draw_text(text, location=location, font=font, color=color, text_location='sw')
font = ('Courier New', 16, 'bold')
layout = [
[sg.Graph((320, 240), (0, 0), (320, 240), enable_events=True, key='GRAPH',
background_color='green')],
]
window = sg.Window('Draw Text', layout, margins=(0, 0), finalize=True)
graph = window['GRAPH']
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'GRAPH':
location = tuple(map(int, graph._convert_xy_to_canvas_xy(*values['GRAPH'])))
entry = sg.tk.Entry(graph.widget, font=font, fg='white', bg='green', width=45)
entry_id = graph.widget.create_window(*location, window=entry, anchor="sw")
entry.bind('<Return>', lambda event, graph=graph, entry_id=entry_id, font=font, location=values['GRAPH'], color='white':entry_callback(event, graph, entry_id, font, location, color))
entry.focus_force()
window.close()

how to ignore input to dialog based application while QProcess is running

I created a basic "Dialog without buttons" application using Qt5 Designer. I have a context menu that starts a QProcess that allows the user to view/edit a file. The main dialog seems disabled while the QProcess is running, but it is still processing input and when the user closes the editor, the main dialog processes all of its queued up input events. I would like the dialog to ignore all input while the QProcess is running. I would like the main dialog to be modal, but I can't seem to make it modal. How can I ignore all input to the main dialog while the QProcess is running?
class Ui_GitStatusDialog(QDialog):
# member variables
startDirs = []
exceptDirs = []
isVerbose = False
terminal = ''
standardView = ''
imageView = ''
def __init__(self):
super().__init__()
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setWindowModality(QtCore.Qt.ApplicationModal)
Dialog.resize(724, 612)
...
def eventFilter(self, source, event):
if event.type() == QEvent.ContextMenu and source is self.fileList:
path = self.repositoryList.currentItem().text()
file = source.currentItem().text()
ext = file[1 + file.find('.'):]
endOfFile = 2 + file.find(':')
contextMenu = QMenu()
normAct = None
diffAct = None
imageAct = None
bDisplayMenu = False
action = None
if ext == 'png' or ext == 'jpg' or ext == 'bmp':
imageAct = contextMenu.addAction('image view')
bDisplayMenu = True
elif file.startswith('modified: '):
diffAct = contextMenu.addAction('difference view')
normAct = contextMenu.addAction('normal view')
endOfFile += 1
bDisplayMenu = True
elif file.startswith('untracked: ') or \
file.startswith('added: ') or \
file.startswith('copied: ') or \
file.startswith('renamed: '):
normAct = contextMenu.addAction('normal view')
endOfFile += 1
bDisplayMenu = True
elif endOfFile == 1:
normAct = contextMenu.addAction('normal view')
bDisplayMenu = True
if bDisplayMenu:
action = contextMenu.exec_(event.globalPos())
if action != None:
if action == imageAct:
command = self.imageView + ' ' + path + file[endOfFile:]
process = QProcess(self)
# self.btnClose.setEnabled(False) - this doesn't work
# self.btnRefresh.setEnabled(False) - this doesn't work
# self.hide() - this doesn't work
self.setModal(True) - this doesn't work
process.start(command)
process.waitForFinished()
# self.btnClose.setEnabled(True)
# self.btnRefresh.setEnabled(True)
return True
elif action == normAct:
...

PyGtk Serialization

I am currently working on a Note taking app in pyGtk and have set up a TextView where a user can type and add text tags for Bold Underline and Italics.
However, when it comes to saving the formatted text I cannot figure out how to do so.
I am trying to save in Gtk's native tagset format however after using
tag_format = TextBuffer.register_serialize_tagset()
content = TextBuffer.serialize(self, tag_format, start,end)
I cannot write this to a file with
open(filename, 'w').write(content)
because I get an error which states that it cannot write in bytes and needs a string instead.
I am currently working on a Note taking app in pyGtk and have set up a TextView where a user can type and add text tags for Bold Underline and Italics.
However, when it comes to saving the formatted text I cannot figure out how to do so.
I am trying to save in Gtk's native tagset format however after using
tag_format = TextBuffer.register_serialize_tagset()
content = TextBuffer.serialize(self, tag_format, start,end)
I cannot write this to a file with
open(filename, 'w').write(content)
because I get an error which states that it cannot write in bytes and needs a string instead.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango
I am currently working on a Note taking app in pyGtk and have set up a TextView where a user can type and add text tags for Bold Underline and Italics.
However, when it comes to saving the formatted text I cannot figure out how to do so.
I am trying to save in Gtk's native tagset format however after using
tag_format = TextBuffer.register_serialize_tagset()
content = TextBuffer.serialize(self, tag_format, start,end)
I cannot write this to a file with
open(filename, 'w').write(content)
because I get an error which states that it cannot write in bytes and needs a string instead.
File "example.py", line 87, in save_file
open(filename, 'w').write(content)
TypeError: write() argument must be str, not bytes
Here is sample code you can run and test by typing and then saving
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Pango
class MainWindow(Gtk.ApplicationWindow):
def __init__(self):
Gtk.Window.__init__(self, title = "TwoNote")
self.grid = Gtk.Grid()
self.toolbar = Gtk.Toolbar()
self.grid.add(self.toolbar)
#buttons for toolbar
self.button_bold = Gtk.ToggleToolButton()
self.button_italic = Gtk.ToggleToolButton()
self.button_underline = Gtk.ToggleToolButton()
self.button_save = Gtk.ToolButton()
self.button_open = Gtk.ToolButton()
self.mytext = TextSet(self.button_bold, self.button_italic, self.button_underline)
self.button_bold.set_icon_name("format-text-bold-symbolic")
self.toolbar.insert(self.button_bold, 0)
self.button_italic.set_icon_name("format-text-italic-symbolic")
self.toolbar.insert(self.button_italic, 1)
self.button_underline.set_icon_name("format-text-underline-symbolic")
self.toolbar.insert(self.button_underline, 2)
self.toolbar.insert(self.button_save, 3)
self.toolbar.insert(self.button_open, 4)
self.button_open.set_icon_name("document-open-data")
self.button_save.set_icon_name("document-save")
self.button_save.connect("clicked", self.save_file)
self.button_open.connect("clicked", self.open_file)
self.button_bold.connect("toggled", self.mytext.on_button_clicked, "Bold", self.button_italic, self.button_underline)
self.button_italic.connect("toggled", self.mytext.on_button_clicked, "Italic", self.button_bold, self.button_underline)
self.button_underline.connect("toggled", self.mytext.on_button_clicked, "Underline", self.button_bold, self.button_italic)
self.grid.attach_next_to(self.mytext, self.toolbar, Gtk.PositionType.BOTTOM, 10,30)
self.add(self.grid)
filename = "Untitled"
def open_file(self, widget):
open_dialog = Gtk.FileChooserDialog("Open an existing file", self, Gtk.FileChooserAction.OPEN,(Gtk.STOCK_CANCEL,Gtk.ResponseType.CANCEL,Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
open_response = open_dialog.run()
if open_response == Gtk.ResponseType.OK:
filename = open_dialog.get_filename()
text = open(filename).read()
self.mytext.get_buffer().set_text(text)
open_dialog.destroy()
elif open_response == Gtk.ResponseType.CANCEL:
print("Cancel clicked")
open_dialog.destroy()
def save_file(self, widget):
savechooser = Gtk.FileChooserDialog('Save File', self, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
allfilter = Gtk.FileFilter()
allfilter.set_name('All files')
allfilter.add_pattern('*')
savechooser.add_filter(allfilter)
txtFilter = Gtk.FileFilter()
txtFilter.set_name('Text file')
txtFilter.add_pattern('*.txt')
savechooser.add_filter(txtFilter)
response = savechooser.run()
if response == Gtk.ResponseType.OK:
filename = savechooser.get_filename()
print(filename, 'selected.')
buf = self.mytext.get_buffer()
start, end = buf.get_bounds()
tag_format = buf.register_serialize_tagset()
content = buf.serialize(buf, tag_format, start, end)
try:
open(filename, 'w').write(content)
except SomeError as e:
print('Could not save %s: %s' % (filename, err))
savechooser.destroy()
elif response == Gtk.ResponseType.CANCEL:
print('Closed, file not saved.')
savechooser.destroy()
class TextSet(Gtk.TextView):
def __init__(self, buttonBold, buttonItalic, buttonUnderline, interval = 1 ):
# Textview Setup
Gtk.TextView.__init__(self)
self.set_vexpand(True)
self.set_indent(10)
self.set_top_margin(90)
self.set_left_margin(20)
self.set_right_margin(20)
self.set_wrap_mode(Gtk.WrapMode.CHAR)
self.tb = TextBuffer()
self.set_buffer(self.tb)
# Thread setup
self.button_bold = buttonBold
self.button_italic = buttonItalic
self.button_underline = buttonUnderline
def on_button_clicked(self, widget, tagname, widget1, widget2):
state = widget.get_active()
name = widget.get_icon_name()
bounds = self.tb.get_selection_bounds()
self.tagname = tagname
if(state):
widget1.set_active(False)
widget2.set_active(False)
#highlighting
if(len(bounds) != 0):
start, end = bounds
myIter = self.tb.get_iter_at_mark(self.tb.get_insert())
myTags = myIter.get_tags()
if(myTags == [] and state == True):
self.tb.apply_tag_by_name(tagname, start, end)
elif(myTags != [] and state == True):
self.tb.remove_all_tags(start, end)
self.tb.apply_tag_by_name(tagname, start, end)
else:
for i in range(len(myTags)):
if(myTags[i].props.name == tagname):
self.tb.remove_tag_by_name(tagname,start,end)
myTags = []
self.tb.markup(widget, tagname)
def mouse_clicked(self, window, event):
self.button_bold.set_active(False)
self.button_italic.set_active(False)
self.button_underline.set_active(False)
class TextBuffer(Gtk.TextBuffer):
def __init__(self):
Gtk.TextBuffer.__init__(self)
self.connect_after('insert-text', self.text_inserted)
# A list to hold our active tags
self.taglist_on = []
# Our Bold tag.
self.tag_bold = self.create_tag("Bold", weight=Pango.Weight.BOLD)
self.tag_none = self.create_tag("None", weight=Pango.Weight.NORMAL)
self.tag_italic = self.create_tag("Italic", style=Pango.Style.ITALIC)
self.tag_underline = self.create_tag("Underline", underline=Pango.Underline.SINGLE)
def get_iter_position(self):
return self.get_iter_at_mark(self.get_insert())
def markup(self, widget, tagname):
self.tag_name = tagname
self.check = True
''' add "bold" to our active tags list '''
if(widget.get_active() == True):
if(self.tag_name == 'Bold'):
if 'Bold' in self.taglist_on:
del self.taglist_on[self.taglist_on.index('Bold')]
else:
self.taglist_on.append('Bold')
if(self.tag_name == 'Italic'):
if 'Italic' in self.taglist_on:
del self.taglist_on[self.taglist_on.index('Italic')]
else:
self.taglist_on.append('Italic')
if(self.tag_name == 'Underline'):
if 'Underline' in self.taglist_on:
del self.taglist_on[self.taglist_on.index('Underline')]
else:
self.taglist_on.append('Underline')
else:
self.check = False
def text_inserted(self, buffer, iter, text, length):
# A text was inserted in the buffer. If there are ny tags in self.tags_on, apply them
#if self.taglist_None or self.taglist_Italic or self.taglist_Underline or self.taglist_Bold:
if self.taglist_on:
# This sets the iter back N characters
iter.backward_chars(length)
# And this applies tag from iter to end of buffer
if(self.check == True):
if(self.tag_name == 'Italic'):
self.apply_tag_by_name('Italic', self.get_iter_position(), iter)
if(self.tag_name == 'Bold'):
self.apply_tag_by_name('Bold', self.get_iter_position(), iter)
if(self.tag_name == 'Underline'):
self.apply_tag_by_name('Underline', self.get_iter_position(), iter)
else:
self.remove_all_tags(self.get_iter_position(), iter)
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
I figured it out rather than using
open(filename, 'w').write(content)
to save the content I imported GLib and used
GLib.file_set_contents(filename, content)

Pygame .Rect won't "collide" with mouse

I am working on a simple game and with small circle "systems". I would like to be able to click each system so that I can do more with it later in game but I am having difficulty recognizing only a single click. I pass the randomly generated coords to a dictionary and then the collision for each rect should be checked with the mouse position but for some reason that is not working anymore. Any help is appreciated.
Here is some of the more relevent code.
for i in range(NumSystems):
SysSize = random.randint(3,SystemSize)
SysY = random.randint(SystemSize*2,GVPHEIGHT-SystemSize*2)
SysX = random.randint(OverLayWidth+SystemSize*2,WINWIDTH-SystemSize*2)
SysList[str('SysNum')+str(i)] = ((SysSize,(SysX,SysY)))
SysCoords[str('SysNum')+str(i)] = pygame.draw.circle(DISPLAYSURF, WHITE, (SysX,SysY), SysSize, 0)
pygame.display.update()
#time.sleep(.25)
#Code above is putting the random Coords into a dictionary.
while True:
MousePos=mouse.get_pos()
for event in pygame.event.get():
if event.type == QUIT:
pygame.QUIT()
sys.exit()
elif event.type == KEYDOWN:
# Handle key presses
if event.key == K_RETURN:
#Restarts the map
main()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
SysClicky(MousePos)
if SysClicked == True:
print('Clicked System')
elif SysClicked == False:
print('Something Else Clicked')
def SysClicky(MousePos):
for i in range(NumSystems):
print('Made to the SysClicky bit')
if SysCoords['SysNum'+str(i)].collidepoint(MousePos):
SysClicked = True
print(SysClicked)
return SysClicked
else:
SysClicked = False
return SysClicked
I'm not clear on What SysList / SysX/Y, SysCoords are. Does it hold width,height of the items in SysCoords? If so, that's already in Rect()
below systems is your dict of Rects.
Here's the code:
def check_collisions(pos):
# iterate dict, check for collisions in systems
for k,v in systems.items():
if v.collidepoint(pos):
print("clicked system:", k)
return
print("clicked something else")
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
check_collisions(event.pos)
# render
Pygame rect objects have a collidepoint inbuilt method which takes a coordinate and returns a boolean based on collision. You can input the mouses coordinate into function like so:
MousePos=mouse.get_pos()
if mySurface.get_rect().collidepoint(MousePos):
doSomething()

GTK / PyGTK make ComboBox searchable with keyboard

Is it possible to make a ComboBox searchable ? If yes, how ?
I want to be able, when the ComboBox is active and a letter is typed with the keyboard, to select the first item beginning with this letter inside the ComboBox and so on with the next letters.
The is the same functionality of a ComboBox inside a webpage, for example.
I can't find any option the achieve this on the ComboBox or on the ListStore containing the data in the same way as the TreeView has the methods set_enable_search and set_search_column.
How to: an introduction to GTK+ treeviews and autocompletion.
I finally decided to write my own completion function :
def func(menu, user_data, (widget, window)):
return (widget.get_allocation().x + window.get_position()[0],widget.get_allocation().y + window.get_position()[1],True)
def completion(self, widget, event):
alphanum = re.compile(r'[a-zA-Z0-9-]')
keyval = event.keyval
key = event.string
if keyval == 65288:
#DEL
self.text = self.text[:-1]
elif alphanum.match(key):
self.text = self.text+key
else:
self.yTree.get_widget("comp_menu").popdown()
self.text = ''
return
self.yTree.get_widget("comp_menu").popup( None, None, self.func, 1, event.time, (widget, self.wTree.get_widget('main_window')))
widget.grab_focus()
m = widget.get_model()
j = 0
for i in m:
if i[0].lower().startswith(self.text):
widget.set_active(j)
return
j+=1