如何使用 wxPython 每隔 x 秒显示一个 jpg 图像并在同一面板上更改它?
How to display an jpg image and change it on the same panel every x sec using wxPython?
我需要使用 wx Python 在 GUI 面板上显示远处计算机的屏幕截图。此外,例如,我需要每 0.04 秒用一个新的屏幕截图替换屏幕截图。我正在为此使用线程。当代码不显示除最后一个屏幕截图之外的任何图像时(当我停止程序时),问题就开始了。我的问题是我必须更改我的代码,以便它在同一平台上显示屏幕截图并每 0.04 秒更改一次图像。我正在添加服务器端(向我发送屏幕截图的远方计算机)和客户端(我的计算机)的代码。
客户端:
导入 wx
导入套接字
import threading
import time
import cStringIO
PORT = 1729
IP = '127.0.0.1'
LOCATION = 'C:\stam\stam1.jpg'
class PhotoCtrl(wx.App):
def __init__(self, redirect=False, filename=None):
wx.App.__init__(self, redirect, filename)
self.frame = wx.Frame(None, title='Photo Control')
self.panel = wx.Panel(self.frame)
self.PhotoMaxSize = 240
def createWidgets(self):
imageFile = LOCATION
data = open(imageFile, "rb").read()
stream = cStringIO.StringIO(data)
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.BitmapFromImage( wx.ImageFromStream( stream )))
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.frame)
self.panel.Layout()
self.panel.Center()
self.frame.Show()
class User(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'MiniViewer2017', size=(500, 500))
panel = wx.Panel(self)
button_scan = wx.Button(panel, label='start scanning!')
button_exit = wx.Button(panel, label='exit', pos=(400, 300))
self.Bind(wx.EVT_BUTTON, self.Scan, button_scan)
self.Bind(wx.EVT_BUTTON, self.closebutton, button_exit)
self.Bind(wx.EVT_CLOSE, self.closewindow)
def Scan(self, event):
client_socket = self.connetet_socket('127.0.0.1', PORT)
app = PhotoCtrl()
t1 = threading.Thread(target=self.ScreenThread(client_socket, app))
t1.start()
app.MainLoop()
def recieve_all(self, client_socket):
""" input:socket output: the data we recieved from the server"""
str_length = int(client_socket.recv(1024))
new_data = client_socket.recv(str_length)
return new_data
def connetet_socket(self, ip, port):
""" input : ip and port output : socket """
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, port))
except socket.error as msg:
print msg
client_socket = None
return client_socket
def ask_for_screen_shot(self, client_socket,app):
client_socket.send("Send me your screen")
time.sleep(0.0001)
screen_shot = self.recieve_all(client_socket)
print "i got it"
f = open(LOCATION, 'wb')
f.write(screen_shot)
f.close()
app.createWidgets()
def ScreenThread(self, client_socket,app):
fl=True
while fl:
self.ask_for_screen_shot(client_socket,app)
time.sleep(0.04)
def closebutton(self,event):
self.Close(True)
def closewindow(self, event):
self.Destroy()
def main():
app = wx.PySimpleApp()
frame = User(parent=None, id=-1)
frame.Show()
app.MainLoop()
if __name__ == '__main__':
main()
服务器端:
import ImageGrab, socket, threading
PORT = 1729
def print_screen():
im = ImageGrab.grab()
im.save('C:\stam\stam.jpg') #!!!before starting, make sure you have a folder in C drive named "stam"!!!
with open('C:\stam\stam.jpg', 'rb') as f:
return f.read()
def create_server_socket(ip, PORT):
""" input : ip and port output : server_socket """
try:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((ip, PORT))
server_socket.listen(1)
except socket.error as msg:
server_socket.close()
server_socket = None
print msg
return server_socket
def send_message(client_socket, msg):
#the function sends the client the length of the message(screen shot), and then send the screen shot while the client already set the amount of bits he is about to get.
try:
str_msg = str(msg)
str_msg_length = len(str_msg)
client_socket.send(str(str_msg_length))
client_socket.send(msg)
except socket.error as msg:
client_socket.close()
print msg
def ScreenThread(client_socket):
while True:
r = client_socket.recv(50)
print r
if r == "Send me your screen":
send_message(client_socket, print_screen())
print "The image has been sent successfully!"
else:
pass
def main():
while True:
server_socket_screen = create_server_socket('0.0.0.0', PORT)
if server_socket_screen is not None:
client_socket, address = server_socket_screen.accept()
t1 = threading.Thread(target=ScreenThread(client_socket))
t1.start()
if __name__ == '__main__':
main()
我建议从 wxpython 教程开始,这样您就可以了解它的基本概念。 See Here
我将图片控件更改为继承帧而不是 wx.App。我在整个代码中添加了一些注释来解释一些更改。
有2个框架,'User'框架和图片控制框架。用户框运行线程,然后更新图片控制框上的图片。
import cStringIO
import wx
import os
import threading
import socket
import time
PORT = 1729
IP = '127.0.0.1'
LOCATION = 'C:\stam\stam1.jpg'
class PhotoCtrl(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
size=wx.Size(500, 300), style=wx.DEFAULT_FRAME_STYLE)
self.panel = wx.Panel(self.frame)
self.PhotoMaxSize = 240
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.EmptyBitmap())
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL | wx.EXPAND, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.frame)
self.panel.Layout()
self.panel.Center()
self.frame.Show()
def update_image(self):
imageFile = LOCATION
if not os.path.exists(imageFile):
return
with open(imageFile, "rb") as fileobj:
data = fileobj.read()
stream = cStringIO.StringIO(data)
bmp = wx.BitmapFromImage(wx.ImageFromStream(stream))
self.imageCtrl.SetBitmap(bmp)
class User(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'MiniViewer2017', size=(500, 500))
panel = wx.Panel(self)
button_scan = wx.Button(panel, label='start scanning!')
button_exit = wx.Button(panel, label='exit', pos=(400, 300))
self.Bind(wx.EVT_BUTTON, self.Scan, button_scan)
self.Bind(wx.EVT_BUTTON, self.closebutton, button_exit)
self.Bind(wx.EVT_CLOSE, self.closewindow)
# create the photo ctrl as a child frame
self.photo_ctrl = PhotoCtrl(self)
def Scan(self, event):
client_socket = self.connetet_socket('127.0.0.1', PORT)
# app = PhotoCtrl()
t1 = threading.Thread(target=self.ScreenThread(client_socket, app))
t1.start()
app.MainLoop()
def recieve_all(self, client_socket):
""" input:socket output: the data we recieved from the server"""
str_length = int(client_socket.recv(1024))
new_data = client_socket.recv(str_length)
return new_data
def connetet_socket(self, ip, port):
""" input : ip and port output : socket """
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, port))
except socket.error as msg:
print msg
client_socket = None
return client_socket
def ask_for_screen_shot(self, client_socket, app):
client_socket.send("Send me your screen")
time.sleep(0.0001)
screen_shot = self.recieve_all(client_socket)
print "i got it"
with open(LOCATION, "wb") as fileobj:
fileobj.write(screen_shot) # you could probably just pass the data directly to update_image instead of writing to a file
self.photo_ctrl.update_image()
def ScreenThread(self, client_socket, app):
fl = True
while fl:
self.ask_for_screen_shot(client_socket, app)
time.sleep(0.04)
def closebutton(self, event):
self.Close(True)
def closewindow(self, event):
self.Destroy() # when Frames are deleted they automatically call destroy
app = wx.App()
user = User(None, -1)
user.Show()
app.MainLoop()
我需要使用 wx Python 在 GUI 面板上显示远处计算机的屏幕截图。此外,例如,我需要每 0.04 秒用一个新的屏幕截图替换屏幕截图。我正在为此使用线程。当代码不显示除最后一个屏幕截图之外的任何图像时(当我停止程序时),问题就开始了。我的问题是我必须更改我的代码,以便它在同一平台上显示屏幕截图并每 0.04 秒更改一次图像。我正在添加服务器端(向我发送屏幕截图的远方计算机)和客户端(我的计算机)的代码。 客户端: 导入 wx 导入套接字
import threading
import time
import cStringIO
PORT = 1729
IP = '127.0.0.1'
LOCATION = 'C:\stam\stam1.jpg'
class PhotoCtrl(wx.App):
def __init__(self, redirect=False, filename=None):
wx.App.__init__(self, redirect, filename)
self.frame = wx.Frame(None, title='Photo Control')
self.panel = wx.Panel(self.frame)
self.PhotoMaxSize = 240
def createWidgets(self):
imageFile = LOCATION
data = open(imageFile, "rb").read()
stream = cStringIO.StringIO(data)
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.BitmapFromImage( wx.ImageFromStream( stream )))
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.frame)
self.panel.Layout()
self.panel.Center()
self.frame.Show()
class User(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'MiniViewer2017', size=(500, 500))
panel = wx.Panel(self)
button_scan = wx.Button(panel, label='start scanning!')
button_exit = wx.Button(panel, label='exit', pos=(400, 300))
self.Bind(wx.EVT_BUTTON, self.Scan, button_scan)
self.Bind(wx.EVT_BUTTON, self.closebutton, button_exit)
self.Bind(wx.EVT_CLOSE, self.closewindow)
def Scan(self, event):
client_socket = self.connetet_socket('127.0.0.1', PORT)
app = PhotoCtrl()
t1 = threading.Thread(target=self.ScreenThread(client_socket, app))
t1.start()
app.MainLoop()
def recieve_all(self, client_socket):
""" input:socket output: the data we recieved from the server"""
str_length = int(client_socket.recv(1024))
new_data = client_socket.recv(str_length)
return new_data
def connetet_socket(self, ip, port):
""" input : ip and port output : socket """
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, port))
except socket.error as msg:
print msg
client_socket = None
return client_socket
def ask_for_screen_shot(self, client_socket,app):
client_socket.send("Send me your screen")
time.sleep(0.0001)
screen_shot = self.recieve_all(client_socket)
print "i got it"
f = open(LOCATION, 'wb')
f.write(screen_shot)
f.close()
app.createWidgets()
def ScreenThread(self, client_socket,app):
fl=True
while fl:
self.ask_for_screen_shot(client_socket,app)
time.sleep(0.04)
def closebutton(self,event):
self.Close(True)
def closewindow(self, event):
self.Destroy()
def main():
app = wx.PySimpleApp()
frame = User(parent=None, id=-1)
frame.Show()
app.MainLoop()
if __name__ == '__main__':
main()
服务器端:
import ImageGrab, socket, threading
PORT = 1729
def print_screen():
im = ImageGrab.grab()
im.save('C:\stam\stam.jpg') #!!!before starting, make sure you have a folder in C drive named "stam"!!!
with open('C:\stam\stam.jpg', 'rb') as f:
return f.read()
def create_server_socket(ip, PORT):
""" input : ip and port output : server_socket """
try:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((ip, PORT))
server_socket.listen(1)
except socket.error as msg:
server_socket.close()
server_socket = None
print msg
return server_socket
def send_message(client_socket, msg):
#the function sends the client the length of the message(screen shot), and then send the screen shot while the client already set the amount of bits he is about to get.
try:
str_msg = str(msg)
str_msg_length = len(str_msg)
client_socket.send(str(str_msg_length))
client_socket.send(msg)
except socket.error as msg:
client_socket.close()
print msg
def ScreenThread(client_socket):
while True:
r = client_socket.recv(50)
print r
if r == "Send me your screen":
send_message(client_socket, print_screen())
print "The image has been sent successfully!"
else:
pass
def main():
while True:
server_socket_screen = create_server_socket('0.0.0.0', PORT)
if server_socket_screen is not None:
client_socket, address = server_socket_screen.accept()
t1 = threading.Thread(target=ScreenThread(client_socket))
t1.start()
if __name__ == '__main__':
main()
我建议从 wxpython 教程开始,这样您就可以了解它的基本概念。 See Here
我将图片控件更改为继承帧而不是 wx.App。我在整个代码中添加了一些注释来解释一些更改。
有2个框架,'User'框架和图片控制框架。用户框运行线程,然后更新图片控制框上的图片。
import cStringIO
import wx
import os
import threading
import socket
import time
PORT = 1729
IP = '127.0.0.1'
LOCATION = 'C:\stam\stam1.jpg'
class PhotoCtrl(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=wx.DefaultPosition,
size=wx.Size(500, 300), style=wx.DEFAULT_FRAME_STYLE)
self.panel = wx.Panel(self.frame)
self.PhotoMaxSize = 240
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.EmptyBitmap())
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY), 0, wx.ALL | wx.EXPAND, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.frame)
self.panel.Layout()
self.panel.Center()
self.frame.Show()
def update_image(self):
imageFile = LOCATION
if not os.path.exists(imageFile):
return
with open(imageFile, "rb") as fileobj:
data = fileobj.read()
stream = cStringIO.StringIO(data)
bmp = wx.BitmapFromImage(wx.ImageFromStream(stream))
self.imageCtrl.SetBitmap(bmp)
class User(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'MiniViewer2017', size=(500, 500))
panel = wx.Panel(self)
button_scan = wx.Button(panel, label='start scanning!')
button_exit = wx.Button(panel, label='exit', pos=(400, 300))
self.Bind(wx.EVT_BUTTON, self.Scan, button_scan)
self.Bind(wx.EVT_BUTTON, self.closebutton, button_exit)
self.Bind(wx.EVT_CLOSE, self.closewindow)
# create the photo ctrl as a child frame
self.photo_ctrl = PhotoCtrl(self)
def Scan(self, event):
client_socket = self.connetet_socket('127.0.0.1', PORT)
# app = PhotoCtrl()
t1 = threading.Thread(target=self.ScreenThread(client_socket, app))
t1.start()
app.MainLoop()
def recieve_all(self, client_socket):
""" input:socket output: the data we recieved from the server"""
str_length = int(client_socket.recv(1024))
new_data = client_socket.recv(str_length)
return new_data
def connetet_socket(self, ip, port):
""" input : ip and port output : socket """
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((ip, port))
except socket.error as msg:
print msg
client_socket = None
return client_socket
def ask_for_screen_shot(self, client_socket, app):
client_socket.send("Send me your screen")
time.sleep(0.0001)
screen_shot = self.recieve_all(client_socket)
print "i got it"
with open(LOCATION, "wb") as fileobj:
fileobj.write(screen_shot) # you could probably just pass the data directly to update_image instead of writing to a file
self.photo_ctrl.update_image()
def ScreenThread(self, client_socket, app):
fl = True
while fl:
self.ask_for_screen_shot(client_socket, app)
time.sleep(0.04)
def closebutton(self, event):
self.Close(True)
def closewindow(self, event):
self.Destroy() # when Frames are deleted they automatically call destroy
app = wx.App()
user = User(None, -1)
user.Show()
app.MainLoop()