да.>self - конкретный экземпляр класса?Правильно?
не знаю почему.>в начале модуля нового плагина подвешивает CudaText!
первый раз вижу что в плагине юзают gtk.
Ну не нашел иных решений по перехвату clipboard changed для Python 3.main Alexey wrote:да.>self - конкретный экземпляр класса?Правильно?не знаю почему.>в начале модуля нового плагина подвешивает CudaText!
первый раз вижу что в плагине юзают gtk.
Code: Select all
import gi
from gi.repository import Gdk
Code: Select all
from gi.repository import Gtk
Code: Select all
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clipboard.set_text("It worked!, -1)
def clipboardChanged(clipboard, owner_change):
print("New owner is", owner_change.owner.get_xid())
clipboard.connect('owner-change', clipboardChanged)
I found in the web a solution using GTK:
Code: Select all
from gi.repository import Gtk, Gdk
def callBack(*args):
print("Clipboard changed. New value = " + clip.wait_for_text())
clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clip.connect('owner-change', callBack)
Gtk.main()
Согласен!main Alexey wrote:clipboard catcher видимо трудно сделать. из за ограничений АПИ - нет тредов, нет gtk/gdk.
mix-7 wrote: Ну не нашел иных решений по перехвату clipboard changed для Python 3.
1. В WikidPad он работал в фоне с возможностью редактирования страниц, но непонятно, как.
Могу привести код.
2. Может, есть возможность самому написать hook/interceptor (?)
The following contains my little app that detects changes to the clipboard and displays them in the GUI. I did my best using my limited knowledge of Python, but I have a feeling that I can definitely improve the program. It works, but Python's CPU usage shoots up to 20% whenever I run the program - which is due to my use of multiple threads and infinite loops I'm sure.
Code: Select all
#! python3
#GUI
import tkinter
#needed for the clipboard event detection
import time
import threading
#listener class that inherits from Thread
class ClipListener(threading.Thread):
#overriding Thread constructor
def __init__(self, pause = .5):
#from documentation: If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
super().__init__() #calls Thread class constructor first
#initialize parameters
self.pause = pause
self.stopping = False
#initialize event to communicate with main thread
self.copyevent = threading.Event()
#override run method
def run(self):
last_value = tkinter.Tk().clipboard_get() #initialize last_value as
#continue until self.stopping = true
while not self.stopping:
#grab clip_board value
temp_value = tkinter.Tk().clipboard_get()
#if last value is not equal to the temp_value, then (obviously) a change has occurred
if temp_value != last_value:
#set last value equal to current (temp) value and print
last_value = temp_value
print("set")
#set the event if clipboard has changed
self.copyevent.set()
time.sleep(self.pause) #sleep for indicated amount of time (.5 by default)
#override stop method to work with our paramter 'stopping'
def stop(self):
self.stopping = True
#GUI extends Frame, serving as main container for a root window
class GUI(tkinter.Frame):
#constructor for GUI - intializes with a default height and width if none are given
def __init__(self, master, ht=600, wt=800):
#uses the parent class' constructor
super().__init__(master, height=ht, width=wt)
self.var = tkinter.StringVar()
self.var.set("No copied text")
self.pack_propagate(False) #window will use it's own width and height as parameters instead of child's dimensions
self.pack()
self.label = tkinter.Label(self, textvariable=self.var)
self.label.pack()
#method to update the label
def update_label(self, newText):
self.var.set(newText)
self.label.pack()
def main():
#good practice to have a variable to stop the loop
running = True
#GUI initialized
root = tkinter.Tk()
gui = GUI(root)
#start thread containing Clipboard Listener
listener = ClipListener(.100)
listener.start()
#loop to keep updating the program without blocking the clipboard checks (since mainloop() is blocking)
while running:
#update the gui
root.update();
#wait .1 seconds for event to be set to true
event_set = listener.copyevent.wait(.100)
#if true then update the label and reset event
if event_set:
gui.update_label(root.clipboard_get())
listener.copyevent.clear()
#only run this program if it is being used as the main program file
if __name__ == "__main__":
main()
Код на странице.Ему советует "урезать марш" и проверять буфер обмена каждые 0.5 секунды:
Don't use threads
You don't need the complexities of threading for this problem. You can use the Tkinter method after to run a function periodically. Threading is necessary if the function you are running takes a long time, but that is not the case here.
You can use a class, but to keep this answer simple I'll only show the function.
Also, note that I use an existing window rather than tkinter.Tk() on each call. There's no need to create a new root window every time you do the check.
...
To start running, simply call run_listener once, and it will continue to run every 500 milliseconds:
...
Code: Select all
...
import threading
import time
...
def clip_loop():
print (app_proc(PROC_GET_CLIP, ""))
return
class Command:
def __init__(self):
global option_int
global option_bool
option_int = int(ini_read(fn_config, 'op', 'option_int', str(option_int)))
option_bool = str_to_bool(ini_read(fn_config, 'op', 'option_bool', bool_to_str(option_bool)))
def dialog(self):
global copy_clips
thread = threading.Thread(target=clip_loop)
thread.start()
Code: Select all
__init__.py - CudaText
Code: Select all
t1=" "
print (app_proc(PROC_GET_CLIP, t1))
Code: Select all
# print (app_proc(PROC_GET_CLIP, ""))
Code: Select all
print (app_proc(PROC_GET_CLIP, ""))
не знаю почему. но плагина который бы читал clipboard в треде, еще не было.появляется модальное окно небольшого размера
то есть 'ed'? ed - всегда ссылка на текущий (с фокусом) редактор.А, наверное, в clip_loop() надо передать среду окружения, ED?