2017-09-16 54 views
0

前段时间,我用Python(2.7)编写了一个简单的井字游戏游戏,多人游戏版本与服务器脚本(每个连接线程)和客户端脚本。现在我想用gtk扩展客户端。我希望这是一个使用装饰器的例子。客户端脚本以通过提示检索数据的方式工作。我想写一个脚本,就像客户端的补丁(只是装饰客户端功能,调用新的gtk客户端脚本和wallah)。我认为这样做的:扩展井字游戏(gtk + decorators + raw_input)的功能

  • GTK的客户端从客户端脚本中的线程开始run_game()函数负责用户输入
  • 功能有装饰,执行代码,并在年底,他们把数据提示(这是可能的吗?)

这是我的想法被GTK界面来控制客户端脚本,但我碰到一些问题就来了:

  • 是有可能把数据提示像keybo输入?
  • 如果它不在主线程中,是否可以从raw_input()获取数据?

编辑: 好吧,我找到了解决办法。我将创建将覆盖raw_input()函数(猴子路径)的装饰器。它应该看起来像这样:

  • gtk-client使用run_game()函数创建线程。从客户端
  • run_game()被(前函数调用的raw_input覆盖())饰
  • 的raw_input现在()等待由队列从GTK的客户端的输入数据(queue.get())

它看起来是一个很好的解决方案,但这是我的另一个问题。我的gtk-client调用线程(run_game())。如果我不使用thread.join(),我的线程在执行时被阻塞,或者打印功能无法将整个数据打印到控制台。如果我使用创建冲突的thread.join(),因为线程等待队列中的数据。例如测试代码:

gtk-client.py

import gtk 
import client as cliApp 
from threading import Thread 
from Queue import Queue 

# gtk stuff etc... 

# lets say it is called on y_button_click, part of GameGtk class 
def y_button_click(self, widget): 
    cliApp.q.put('test msg') 


# lets say that it is called in x_button_click 
@run_game_decorator(func): 
    def wrapper(*args): 
     # some connecting/logging stuff 
     cliApp.q = Queue() 
     t = Thread(target = cliApp.test) 
     t.start() 
     # t.join() - worked until I added q.get() to new raw_input() 
    return wrapper 
# gtk still working after this function 

client.py

def new_raw_input(label): 
    print label 
    return q.get() 

def test(): 
    print 'Thread start' 
    raw_input = new_raw_input 
    a = raw_input("Type something: ") 
    print a 
    print 'Thread finished' 

在这种情况下,我的线程仅打印 '主题开始'。如何处理这个问题?

+0

如果我理解您的问题的权利,您的请求是可能的。但它带有一个价格。从您自己的GUI循环控制所有Gtk小部件的代价。 Linux Mint为他们的一些对话框做了这些工作,并且代码很快变得复杂。 – theGtknerd

回答

0

好吧,最后我找到了解决所有我的问题。要模拟用户对raw_input()的输入,只需修改函数funcionality(monkey patching),如问题编辑部分所示。

关于在控制台打印错误 - 我加入sys.stdout.flush()刷新缓冲区(解释here),并把数据排队后等待线程resolvet它。

gtk-client。py

import gtk 
import client as cliApp 
from threading import Thread 
from Queue import Queue 
from time import sleep 
import sys 


# gtk stuff etc... 

# lets say it is called on y_button_click, part of GameGtk class 
def y_button_click(self, widget): 
    cliApp.q.put('test msg') 
    self.t.join() 


# lets say that it is called in x_button_click 
@run_game_decorator(func): 
    def wrapper(*args): 
     # some connecting/logging stuff 
     cliApp.q = Queue() 
     gtkWindow.t = Thread(target = cliApp.test) 
     gtkWindow.t.start() 
     sleep(0.1) 
     sys.stdout.flusch() 
    return wrapper 
# gtk still working after this function