Open
Description
I have tried various methods, and all of them have various issues.
- Updating the main thread's form in a child thread, obviously, it failed.
from delphifmx import *
import threading
from pynput.mouse import Listener
import time
class GetMousePosition(threading.Thread):
def __init__(self, form):
super().__init__()
self.form = form
# mouseListener
def on_move(self, x, y):
print(f"Mouse is at: X={x}, Y={y}")
self.position = (x, y)
self.form.update_mouse_position(x, y)
def run(self):
with Listener(on_move=self.on_move) as listener:
listener.join()
class MyForm(Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.prev_position = None
self.mouse_thread = None
self.button = Button(self)
self.button.Text = 'Start Background Task'
self.button.OnClick = self.onStartButtonClick
self.label = Label(self)
self.label.Text = 'Click the button to start the background task'
self.button.Parent = self
self.button.Align = "Top"
self.label.Parent = self
self.label.Align = "Top"
def update_mouse_position(self, x, y):
self.label.Text = f'Mouse Position: ({x}, {y})'
def onStartButtonClick(self, sender):
self.mouse_thread = GetMousePosition(self)
self.mouse_thread.start()
if __name__ == '__main__':
Application.Initialize()
Application.Title = "Hello DelphiFMX"
app = MyForm(Application)
Application.MainForm = app
app.Show()
Application.Run()
app.Destroy()
2.Return data in the child thread, and the main thread uses onTimer to periodically read and update the main thread's form. It works. However, dragging the main interface causes stuttering, and mouse movement seems to be unsmooth as well.
from delphifmx import *
import threading
from pynput.mouse import Listener
import time
class GetMousePosition(threading.Thread):
def __init__(self):
super().__init__()
self.position = ()
self.position_history = []
def on_move(self, x, y):
print(f"Mouse is at: X={x}, Y={y}")
self.position = (x, y)
def run(self):
with Listener(on_move=self.on_move) as listener:
listener.join()
class MyForm(Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.prev_position = None
self.mouse_thread = None
self.button = Button(self)
self.button.Text = 'Start Background Task'
self.button.OnClick = self.onStartButtonClick
self.label = Label(self)
self.label.Text = 'Click the button to start the background task'
self.button.Parent = self
self.button.Align = "Top"
self.label.Parent = self
self.label.Align = "Top"
self.timer = Timer(self)
self.timer.Interval = 1
self.timer.OnTimer = self.update_ui
def update_ui(self, sender):
if self.mouse_thread:
result = self.mouse_thread.position
if result != self.prev_position:
print("result:" + str(result))
self.prev_position = result
self.label.Text = f"Mouse Position: " + str(result)
def onStartButtonClick(self, sender):
self.mouse_thread = GetMousePosition()
self.mouse_thread.start()
if __name__ == '__main__':
Application.Initialize()
Application.Title = "Hello DelphiFMX"
app = MyForm(Application)
Application.MainForm = app
app.Show()
Application.Run()
app.Destroy()
- Using multiprocessing, data is stored in a queue within the child process, and the main thread uses onTimer to periodically read from and update the main thread's form. It also works. However, if the mouse keeps sliding, it will lead to a lot of data in the queue, and when the mouse stops, the form is still queuing to read data from the queue. It looks like the display of the form is somewhat lagging.
from delphifmx import *
from multiprocessing import Process, Queue
from pynput.mouse import Listener
class GetMousePosition(Process):
def __init__(self,queue):
super().__init__()
self.queue = queue
def on_move(self, x, y):
print(f"Mouse is at: X={x}, Y={y}")
self.queue.put([(x, y)])
def run(self):
with Listener(on_move=self.on_move) as listener:
listener.join()
class MyForm(Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.queue = None
self.mouse_thread = None
self.prev_position = None # 用于存储上一次的鼠标位置
self.button = Button(self)
self.button.Text = 'Start Background Task'
self.button.OnClick = self.onStartButtonClick
self.label = Label(self)
self.label.Text = 'Click the button to start the background task'
self.button.Parent = self
self.button.Align = "Top"
self.label.Parent = self
self.label.Align = "Top"
self.timer = Timer(self)
self.timer.Interval = 1
self.timer.OnTimer = self.read_process_output
def onStartButtonClick(self, sender):
self.queue = Queue()
self.mouse_thread = GetMousePosition(self.queue)
self.mouse_thread.start()
def read_process_output(self, sender):
if self.queue:
result = self.queue.get()
print(result)
self.label.Text = f"Mouse Position: " + str(result)
if __name__ == '__main__':
Application.Initialize()
Application.Title = "Hello DelphiFMX"
app = MyForm(Application)
Application.MainForm = app
app.Show()
Application.Run()
app.Destroy()
What is the most correct way to use multithreading or multiprocessing in DelphiFMX4Python? Please let me know, thank you.