Как избежать ошибки экрана с использованием MSS при использовании класса для окна TK?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как избежать ошибки экрана с использованием MSS при использовании класса для окна TK?

Сообщение Anonymous »

Идея состоит в том, чтобы контролировать вторичный экран без необходимости физического монитора. Изображение переходит к проектору в другой комнате.root2: You clicked at 295 284
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.12/tkinter/__init__.py", line 1967, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/tkinter/__init__.py", line 861, in callit
func(*args)
File "/media/rh/Win11/Python/cv2-player/cv2_mss2.py", line 65, in after_capture
im_brg = self.sct.grab(self.bounding_box)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rh/.local/lib/python3.12/site-packages/mss/base.py", line 101, in grab
screenshot = self._grab_impl(monitor)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/rh/.local/lib/python3.12/site-packages/mss/linux.py", line 428, in _grab_impl
ximage = self.xlib.XGetImage(
^^^^^^^^^^^^^^^^^^^^
File "/home/rh/.local/lib/python3.12/site-packages/mss/linux.py", line 230, in _validate
raise ScreenShotError(msg, details=details)
mss.exception.ScreenShotError: XGetImage() failed
< /code>
Код, который работает без ошибок, и без участия в классе: < /p>
from mss import mss
from PIL import Image
from PIL import ImageTk
import tkinter as tk

root2 = None
root2_is_splash = False

# screen 2: 1366x768
def root2_init(is_splash=False):
global root2

root2 = tk.Toplevel( root )
root2.transient( root )
root2.title( "Screen 2" )
root2.configure(background="blue")

root2.geometry("1366x768+1920+0") # left: 1920 (right of screen 1), top: 0
root2.bind("", on_root2_click)

if is_splash == True:
root2.wm_attributes('-type', 'splash') # splash: hide title bar

def on_root_click(event):
print("root: You clicked at", event.x, event.y)
root.destroy()

def on_root2_click(event):
global root2_is_splash

print("root2: You clicked at", event.x, event.y)
root2.destroy()

if root2_is_splash == False:
root2_init(True)
root2_is_splash = True
else:
root2_init(False)
root2_is_splash = False

def after_capture():
global label1
im_brg = sct.grab(bounding_box)

im_rgb = Image.frombytes('RGB', im_brg.size, im_brg.bgra, 'raw', 'BGRX')

im_rgb2 = im_rgb.resize((640, 480))

photo1 = ImageTk.PhotoImage(im_rgb2)
label1.configure(image=photo1)
label1.image = photo1

root.after(10, after_capture)

bounding_box = {'top': 0, 'left': 1366, 'width': 1366, 'height': 768}

sct = mss(with_cursor=True)

# screen 1: 1920x1080
root = tk.Tk()
root.title("Tk Example")
root.minsize(200, 200)
root.maxsize(500, 500)
root.geometry("800x600+50+50")
root.bind("", on_root_click)

canvas1 = tk.Canvas(root)
canvas1.pack(fill='both', expand=True)
photo1 = tk.PhotoImage(width=64, height=64)
label1 = tk.Label(canvas1, image=photo1)
label1.pack()
label1.image = photo1
canvas1.create_window((0, 0), anchor='nw', window=label1, tags='label1_tag')

root2_init()

after_capture()

if __name__ == "__main__":
root.mainloop()
< /code>
Код, который дает ошибку, используя класс app (): < /p>
from mss import mss
from PIL import Image
from PIL import ImageTk
import tkinter as tk

class App(tk.Tk):
def __init__(self):
super().__init__()

self.bounding_box = {'top': 0, 'left': 1366, 'width': 1366, 'height': 768}

self.sct = mss(with_cursor=True)

# screen 1: 1920x1080
self.title("Tk Example")
self.geometry("800x600+50+50")

self.canvas1 = tk.Canvas(self)
self.canvas1.pack(fill='both', expand=True)
photo1 = tk.PhotoImage(width=64, height=64)
self.label1 = tk.Label(self.canvas1, image=photo1)
self.label1.pack()
self.label1.image = photo1
self.canvas1.create_window((0, 0), anchor='nw', window=self.label1, tags='label1_tag')

self.bind("", self.on_root_click)

self.root2_is_splash = False

self.root2_init()

self.after_capture()

# screen 2: 1366x768
def root2_init(self, is_splash=False):
# global root2

self.root2 = tk.Toplevel( self )
self.root2.transient( self )
self.root2.title( "Screen 2" )
self.root2.configure(background="blue")

self.root2.geometry("1366x768+1920+0") # left: 1920 (right of screen 1), top: 0
self.root2.bind("", self.on_root2_click)

if is_splash == True:
self.root2.wm_attributes('-type', 'splash') # splash: hide title bar

def on_root_click(self, event):
print("root: You clicked at", event.x, event.y)
self.destroy()

def on_root2_click(self, event):
print("root2: You clicked at", event.x, event.y)
self.root2.destroy()

if self.root2_is_splash == False:
self.root2_init(True)
self.root2_is_splash = True
else:
self.root2_init(False)
self.root2_is_splash = False

def after_capture(self):
im_brg = self.sct.grab(self.bounding_box)

im_rgb = Image.frombytes('RGB', im_brg.size, im_brg.bgra, 'raw', 'BGRX')

im_rgb2 = im_rgb.resize((640, 480))

photo1 = ImageTk.PhotoImage(im_rgb2)
self.label1.configure(image=photo1)
self.label1.image = photo1

self.after(10, self.after_capture)

if __name__ == "__main__":
App().mainloop()
< /code>
Изменить: Мне удалось сделать адаптацию для перезапуска захвата, но было бы интересно избежать ошибки захвата MSS. Таким образом, захват не застрял.from mss import mss
from PIL import Image
from PIL import ImageTk
import tkinter as tk

class App(tk.Tk):
def __init__(self):
super().__init__()

self.bounding_box = {'top': 0, 'left': 1366, 'width': 1366, 'height': 768}

# screen 1: 1920x1080
self.title("Tk Example")
self.geometry("800x600+50+50")

self.canvas1 = tk.Canvas(self)
self.canvas1.pack(fill='both', expand=True)
photo1 = tk.PhotoImage(width=64, height=64)
self.label1 = tk.Label(self.canvas1, image=photo1)
self.label1.pack()
self.label1.image = photo1
self.canvas1.create_window((0, 0), anchor='nw', window=self.label1, tags='label1_tag')

self.bind("", self.on_root_click)

self.root2_is_splash = False

self.root2_init()

self.after_capture()

# screen 2: 1366x768
def root2_init(self, is_splash=False):
# global root2

self.sct = mss(with_cursor=True)

self.root2 = tk.Toplevel( self )
self.root2.transient( self )
self.root2.title( "Screen 2" )
self.root2.configure(background="blue")

self.root2.geometry("1366x768+1920+0") # left: 1920 (right of screen 1), top: 0
self.root2.bind("", self.on_root2_click)

if is_splash == True:
self.root2.wm_attributes('-type', 'splash') # splash: hide title bar

def on_root_click(self, event):
print("root: You clicked at", event.x, event.y)
self.destroy()

def on_root2_click(self, event):
print("root2: You clicked at", event.x, event.y)
self.root2.destroy()

if self.root2_is_splash == False:
self.root2_init(True)
self.root2_is_splash = True
else:
self.root2_init(False)
self.root2_is_splash = False

self.after_capture()

def after_capture(self):
try:
im_brg = self.sct.grab(self.bounding_box)

im_rgb = Image.frombytes('RGB', im_brg.size, im_brg.bgra, 'raw', 'BGRX')

im_rgb2 = im_rgb.resize((640, 480))

photo1 = ImageTk.PhotoImage(im_rgb2)
self.label1.configure(image=photo1)
self.label1.image = photo1

self.after(10, self.after_capture)
except:
print('after_capture() finished')

if __name__ == "__main__":
App().mainloop()


Подробнее здесь: https://stackoverflow.com/questions/794 ... -tk-window
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»