Related
Lately I have been using Autohotkey to help me get past my left hands injury and the pain I get when I "push it" by reaching out for keys, especially, when my other hand is on the mouse
I recently had this brilliant idea that will let me eliminate reaching out for keys, by using a keypad instead of a full sized keyboard.
My idea is to use a VIM style hotkey\editing (The Linux\text editing tool) design.
when I tap NumpadSub, then first tap of NumpadMult should perform a special action. After this first tap of NumpadMult future taps should perform the default windows function, as if no AHK scripts were running.
The thing is, to make up for the small number of keys available, I want to use EvilC's TapHoldManager library to achieve this. I have spent the past few days increasing my knowledge of this library.
Using THIS post and u\ExpiredDebitCard answer HERE I came up with this:
#include <TapHoldManger>
THMLeader:= new TapHoldManager(200,400,2)
THMLeader.Add("NumpadSub", Func("LeaderKey__NumpadSub"))
THMLeader.Add("NumPadMult", Func("LeaderKey__NumPadMult"))
LeaderKey__NumpadSub(isHold, taps, state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, THMLeader Tap x1
TestFlag := 1
}
else
{
if (state)
{
Tooltip, THMLeader Hold x1
}
; else
; {
; }
}
}
LeaderKey__NumPadMult(isHold, taps, state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, LeaderKey__NumPadMult Tap x1
}
else
{
if (state)
{
Tooltip, LeaderKey__NumPadMult Hold x1
}
; else
; {
; }
}
}
TestFlag := 1
Hotkey If,TestFlag == 1
;Hotkey If,(TestFlag == 1)
THMSubKey:=New TapHoldManager(200,400,2)
THMSubKey.Add("NumpadMult", Func("SubKey__NumPadMult"))
#If
SubKey__NumPadMult(isHold,taps,state)
{
if (taps == 1)
if (isHold == 0)
{
Tooltip, SubKey__NumPadMult Tap x1
TestFlag := 0
}
else
{
if (state)
{
Tooltip, SubKey__NumPadMult Hold x1
TestFlag := 0
}
; else
; {
; }
}
}
My intention with the above code is that, SubKey__NumPadMult code block should only ever be active if variable TestFlag is set to 1. Only single tap of NumpadSub can set TestFlag to 1. so
So in short,
A single tap of NumpadSub followed by NumpadMult will print SubKey__NumPadMult Tap x1.
A single tap of NumpadMult NOT preceded by a tap of NumpadSub will print LeaderKey__NumPadMult Tap x1
I am having issues with getting Hotkey If,TestFlag == 1 to work though. Running the above code gives me a runtime error:
Error: Parameter #2 must match an existing #If expression.
Changing it around like. Hotkey If,(TestFlag == 1) has not helped either.
What am I doing wrong here? I have tried many things, nothing seems to be giving in. Any help or ideas would be great.
Thanks for any help
I have a script that runs fine on dell, but seems to work only 70% on mac.
It basically let's the user select different parameters (dates, files, from lists etc), on a while loop until the user presses one of the create buttons that closes the loop.
I removed some parameters for security, but this is the base of the code. The while loop doesn't seem to work, the 3 create buttons don't work, the datepicker doesn't work.
These is my first question, please be kind :)
sg.theme("LightBlue3")
func = ['get_positions_by_account', 'get_positions_by_platform', 'get_positions_by_platform_and_account']
select_all = sg.Listbox(POSITIONS_COLS, select_mode='multiple', key="-IN7-", size=(30,12))
layout = [
[sg.Text("Select account and press go or press PASS to move to select platform:")],
[sg.Combo(ALL_ACCOUNT, key="-IN1-",change_submits=True), sg.Button("GO"), sg.Button("PASS")],
[sg.Text("Select platform:"), sg.Combo([], key="-IN2-",change_submits=True)],
[sg.Text("select run date or date of local file:"), sg.Input(size=(20, 1), key="-IN5-", change_submits=True),
sg.CalendarButton('select', target="-IN5-", key="-IN5-", format='%Y%m%d', default_date_m_d_y=(11, None, 2021))],
[sg.Text("select minimal purchase date:"), sg.Input(size=(20, 1), key="-IN6-", change_submits=True),
sg.CalendarButton('select', target="-IN6-", key="-IN6-", format='%Y-%m-%d', default_date_m_d_y=(11, None, 2021))],
[sg.Text("If local file select file: "), sg.InputText(key="-IN3-", change_submits=True), sg.FileBrowse(key="-IN13-")],
[sg.Text("Select function to run:"), sg.Combo(func, key="-IN4-",change_submits=True)],
[sg.Text('Select position columns:'), sg.Button("Select All"), sg.Button("Top 23"), sg.Button("Clear All")],
[select_all],
[sg.Button("Create position file"), sg.Button("Create transfer file"), sg.Button("Create Talya file"),sg.Button("Exit")]]
window = sg.Window('PIZZA SLICER - Maya Moshe 2021', layout, size=(600, 500))
if __name__ == '__main__':
account, platform, func1, date, pos_file, position, purchase_d = "", "", "", "", "", "", ""
while True:
event, values = window.read()
account = values["-IN1-"]
platform = values["-IN2-"]
pos_file = values["-IN3-"]
func1 = values["-IN4-"]
date = values["-IN5-"]
purchase_d = values["-IN6-"]
pos_cols = values["-IN7-"]
if event == sg.WIN_CLOSED or event == "Exit":
print('Exiting program')
exit()
elif event == "GO":
window["-IN2-"].update(value='', values=ACCOUNTS_PLATFORMS[account])
platform = values["-IN2-"]
elif event == "PASS":
window["-IN2-"].update(value='', values=ALL_PLATFORMS)
platform = values["-IN2-"]
elif event == 'Select All':
cols = POSITIONS_COLS
window.Element('-IN7-').SetValue(cols)
elif event == 'Top 23':
cols = top20
window.Element('-IN7-').SetValue(cols)
elif event == "Clear All":
window.Element('-IN7-').set_value([])
elif event == 'Create position file':
window.close()
now = datetime.datetime.now().replace(microsecond=0)
if pos_file:
position = pd.read_csv(pos_file, dayfirst=True)
eval(func1 + "(date=date, account=account, platform=platform, position=position, purchase_d=purchase_d, cols=pos_cols)")
diff = datetime.datetime.now().replace(microsecond=0) - now
print(f'pos filter, run time {diff}')
exit()
elif event == "Create transfer file":
window.close()
now = datetime.datetime.now().replace(microsecond=0)
if pos_file:
position = pd.read_csv(pos_file, dayfirst=True)
get_positions_by_account(date=date, account=account, platform=platform, position=position, purchase_d=purchase_d, cols=pos_cols, transfer_flag=True)
diff = datetime.datetime.now().replace(microsecond=0) - now
print(f'Create transfer file, run time {diff}')
exit()
break
elif event == "Create Talya file":
window.close()
now = datetime.datetime.now().replace(microsecond=0)
if pos_file:
position = pd.read_csv(pos_file, dayfirst=True)
get_positions_by_account(date=date, account=account, platform=platform, position=position, purchase_d=purchase_d, cols=pos_cols, talya_flag=True)
diff = datetime.datetime.now().replace(microsecond=0) - now
print(f'Create Talya file, run time {diff}')
exit()
Example Code here to show both of buttons Exit and Select All work. Nothing wrong found, maybe wrong code missed in your demo code.
import PySimpleGUI as sg
lst1 = list("ABCDEFGHIJ")
layout = [
[sg.Button('Select All')],
[sg.Listbox(lst1, size=(5, 10), select_mode='multiple', key='-IN7-')],
]
window = sg.Window("test", layout, finalize=True)
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Exit'):
print('Exiting program')
break
# Get value of elements should be here to prevent value of `values` is None when sg.WINDOW_CLOSED
pos_cols = values["-IN7-"]
if event == 'Select All':
window['-IN7-'].set_value(lst1)
window.close()
I have a button that runs a loop and updates the window accordingly. I want another "pause" button that pauses this loop but it doesn't seem like I can do that while the loop is running. Perhaps threading is the solution (I tried GLib.timeout_add_seconds without success) - what is the easiest way to make this work?
I have attached my faulty code:
import sys
from time import sleep
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
class LoopButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
self.message = "1"
button = Gtk.Button.new_with_label("Run")
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
msg = int(self.message)
while self.GUI.is_paused == False:
self.GUI.restart_window(str(msg))
msg += 1
while Gtk.events_pending():
Gtk.main_iteration()
sleep(1)
self.GUI.is_paused = True
class PauseButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
button = Gtk.Button.new_with_label("Pause")
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
self.GUI.is_paused = True
class GUI:
def __init__(self):
self.is_paused = False
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Default label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.box.pack_start(LoopButton(self), True, True, 0)
self.box.pack_start(PauseButton(self), True, True, 0)
self.window_grid.add(self.box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Default label"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
Depending on what you really do in the loop there may be more necessary details, but below is an example of how looping is normally avoided in GLib/Gtk. The caveats of this method are: A) one iteration must be fast enough to not affect UI updates (a few milliseconds at most). B) The timing is not exact: the timeout function might not be called exactly 2 seconds after the previous call.
import gi
from gi.repository import GLib
class GUI:
def __init__(self):
# initialize the UI here...
# setup updates every two seconds
GLib.timeout_add_seconds(2, self.timeout_update)
def timeout_update(self):
# update your widgets here
print ("Updating UI now...")
# yes, we want to be called again
return True
I am developing an application using pyqt 4 so hopefully I am only making a rookie mistake.
I found I cannot move a QGraphicsItems and QGraphicsItemGroups in a scene once I use custom event handlers for mousePressEvent() and mouseMoveEvent().
My application permits me to draw arbitrary shapes however I press CTRL key modifier to set my event handlers so that I can select objects (and add them to QGraphicsItemGroup) to move all selected objects.
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.view = View(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.view)
self.setMouseTracking(True)
def __init__(self, parent):
QtGui.QGraphicsView.__init__(self, parent)
self.activeScene=QtGui.QGraphicsScene(self)
self.setScene(self.activeScene)
self.setInteractive(True)
self.setSceneRect(QtCore.QRectF(self.viewport().rect()))
self.startpos = None
self.endpos = None
self.multiSegmentLine = QtGui.QGraphicsItemGroup(scene=self.activeScene)
self.multiSegmentLine.setFlags(QtGui.QGraphicsItemGroup.ItemIsSelectable)
self.linePen=QPen(Qt.green, 3, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
self.linesegment=QtGui.QGraphicsLineItem
# Create a group of selected items to move as a group
self.createMoveGroup = QtGui.QGraphicsItemGroup(scene=self.activeScene)
self.createMoveGroup.setFlags(QtGui.QGraphicsItemGroup.ItemIsMovable)
# TESTING
self.boxxy = self.activeScene.addRect(10,10,100,100,self.linePen)
self.boxxy.setFlags(QtGui.QGraphicsItem.ItemIsMovable)
# Booleans for state machine
self.stateNewLine=True # Flag to determine line state True = new line, False = continuation of multisegment line
self.stateSelectItems=False # Flag to help determine True = item selection mode enabled, False = line drawing mode enabled
# Create event handler
def mousePressEvent(self, event):
if event.button()==QtCore.Qt.LeftButton:
# If CTRL key is not pressed then self.stateSelectItems is FALSE and
# mouse handling is normal
if self.stateSelectItems == False:
# New line has been started so no end point has been determined
if self.stateNewLine == True:
# Record starting position if creating a new line. This is used as
# origin for line drawn from start position to mouse tip.
self.startpos = QtCore.QPointF(self.mapToScene(event.pos()))
# The line is not new but rather is a multiple segment line.
elif self.stateNewLine == False:
# Update the length of the run
UserLineList.updateRunLength(self.linesegment.line())
self.startpos = self.endpos # Start new line at endpoint of previous segment
self.segmentCount = self.segmentCount+1 # increment segment count
#self.multiSegmentLine.setFlag(QtGui.QGraphicsItem.ItemIsMovable)
# Add line from starting position to location of mouse click
#self.linesegment=self.scene().addLine(QtCore.QLineF(self.startpos,self.endpos))
self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))
self.linesegment.setPen(self.linePen)
# Add newly created line to item group
self.multiSegmentLine.addToGroup(self.linesegment)
self.activeScene.addItem(self.multiSegmentLine)
self.activeScene.removeItem(self.linesegment)
# If CTRL key is pressed thenself.stateSelectItems == True and mouse
# handling has to change to support moving one or more screen items
elif self.stateSelectItems==True:
print("ENTERED MOVEMENT MODE!")
currentItem=self.activeScene.itemAt(self.mapToScene(event.pos()))
if currentItem != None:
self.createMoveGroup.addToGroup(currentItem)
self.stateSelectItems = True # set stateSelectItems flag to control mouse event handling
def mouseDoubleClickEvent(self,event):
#def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.startpos=None
self.stateNewLine=True # multisegment line has ended
# Create a record of the multisegment line
UserLineList.addMultiSegmentLine(self.multiSegmentLine)
def mouseMoveEvent(self,event):
# If CTRL key is not pressed then self.stateSelectItems is FALSE and
# mouse handling is normal
if self.stateSelectItems == False:
# If this is a new line use start position at click
if self.stateNewLine == True:
self.endpos = QtCore.QPointF(self.mapToScene(event.pos()))
self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))
self.linesegment.setPen(self.linePen)
self.stateNewLine = False
# If this line builds upon an existing segment
elif self.stateNewLine == False:
self.endpos = QtCore.QPointF(self.mapToScene(event.pos()))
self.scene().removeItem(self.linesegment)
self.linesegment = self.activeScene.addLine(QtCore.QLineF(self.startpos,self.endpos))
self.linesegment.setPen(self.linePen)
# If CTRL key is pressed thenself.stateSelectItems == True and mouse
# handling has to change to support moving one or more screen items
elif self.stateSelectItems == True:
self.createMoveGroup.mouseMoveEvent(self, event)
def keyPressEvent(self,event):
keyModifier = QtGui.QApplication.keyboardModifiers() #Listen for keyboard modifier keys
if keyModifier == QtCore.Qt.ControlModifier:
print("keyEvent Control Key is pressed")
self.stateSelectItems=True
def keyReleaseEvent(self,event):
keyModifier = QtGui.QApplication.keyboardModifiers() #Listen for keyboard modifier keys
if keyModifier == QtCore.Qt.ControlModifier:
self.stateSelectItems=False
self.createMoveGroup.ungrabMouse() # Selected items lose mouse grab
self.activeScene.destroyItemGroup(self.createMoveGroup) # Remove all selected items from move group
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
Like in the answer to this question, you might want to do a call to the base-class in order to keep the existing event handling of the respective event. E.g. in the mouse press event handler you would add a line like:
def mousePressEvent(self, event):
...
super(Window, self).mousePressEvent(event)
...
Do this in a similar way for all your custom event handlers.
I came across this rather unexpected problem. I have a gtk.TreeView with a single text column, that is rendered by gtk.CellRendererText. What I want is that the user can mark the displayed text using the mouse and get it into the clipboard by pressing ctrl+c. (I am referring to the very basic feature present in every webbrowser and texteditor). However, gtk won't let me do it. I have a simple example here, with non-markable / non-highlightable text:
import gtk
class TreeViewExample(gtk.TreeView):
def __init__(self):
gtk.TreeView.__init__(self)
self.get_selection().set_mode(gtk.SELECTION_NONE)
self.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_HORIZONTAL)
# create model
self.list_store = gtk.ListStore(str)
self.list_store.append(['Hello, this is some \n multiline text.'])
self.list_store.append(['Another text.'])
self.set_model(self.list_store)
# create text column
col = gtk.TreeViewColumn('Text Column')
self.append_column(col)
cell = gtk.CellRendererText()
col.pack_start(cell, True)
col.add_attribute(cell, 'text', 0)
class MasterWindow(object):
def destroy(self, widget, data=None):
gtk.main_quit()
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
self.window.connect("destroy", self.destroy)
self.window.add(TreeViewExample())
self.window.show_all()
if __name__ == '__main__':
mw = MasterWindow()
gtk.main()
I could of course make the cell editable, because the editable mode provides the feature. But that is far from elegant, because it is some kind of popup, that breaks the line wrap and, well, edits the text. What i need is a cell, that is not selectable, editable or anything, but has text, that can be copied.
Does anyone have a solution? Thanks!
I made some changes in the code.
Try the code below, this example works well and I am sure that is the answer to your question.
Hope this helps you in the future of their knowledge and coding.
import gtk
class TreeViewExample():
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
model = gtk.ListStore(str)
model.append(['a'])
model.append(['b'])
model.append(['c'])
treeview = gtk.TreeView(model)
self.renderer = gtk.CellRendererText()
self.renderer.set_property('editable', True)
treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=0)
self.window.add(treeview)
self.window.show_all()
if __name__ == '__main__':
TreeViewExample()
gtk.main()
I made some changes in the code. Trying to answer questions of #Flimm.I hpe Helps you #Flimm.
import gtk
class TreeViewExample():
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_size_request(500,500)
self.model = gtk.ListStore(str,str)
self.model.append(['a','b'])
self.model.append(['c','a'])
self.model.append(['d','a'])
self.model.append(['e','a'])
self.treeview = gtk.TreeView(self.model)
self.renderer = gtk.CellRendererText()
self.renderer.set_property('editable', True)
self.renderer.connect('edited', self._text_changed, 0)
self.treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=0)
self.treeview.insert_column_with_attributes(-1, 'Copy-Pastable-Editable String', self.renderer, text=1)
self.window.add(self.treeview)
self.window.show_all()
def _text_changed( self, w, row, new_value, column):
self.model[row][column] = new_value
if __name__ == '__main__':
TreeViewExample()
gtk.main()