【问题标题】:Extending the functionality of the Tic-tac-toe game (gtk + decorators + raw_input)扩展井字游戏的功能(gtk + decorators + raw_input)
【发布时间】:2018-02-25 18:18:52
【问题描述】:

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

  • gtk-client 从线程中的客户端脚本启动 run_game() 函数
  • 负责用户输入的函数具有装饰器,它们执行代码并在最后将数据放入提示中(有可能吗?)

这是我通过gtk接口控制客户端脚本的想法,但遇到了一些问题:

  • 是否可以像键盘输入一样将数据输入提示?
  • 如果 raw_input() 不在主线程中,是否可以从它获取数据?

编辑: 好的,我找到了解决方案。我将创建将覆盖 raw_input() 函数(猴子路径)的装饰器。它应该是这样的:

  • gtk-client 使用 run_game() 函数创建线程。来自客户
  • run_game() 被修饰(在函数调用之前覆盖 raw_input())
  • 现在 raw_input() 通过队列 (queue.get()) 等待来自 gtk-client 的输入数据

这看起来是一个很好的解决方案,但这是我的另一个问题。我的 gtk 客户端调用线程 (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'

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

【问题讨论】:

  • 如果我理解你的问题是正确的,你的要求是可能的。然而,它是有代价的。从您自己的 GUI 循环中控制所有 Gtk 小部件的价格。 Linux Mint 为他们的一些对话框执行此操作,代码很快变得复杂。

标签: python multithreading python-2.7 gtk python-decorators


【解决方案1】:

好的,我终于找到了解决我所有问题的方法。要模拟用户对 raw_input() 的输入,只需更改函数功能(猴子修补),如问题中所示,已编辑部分。

关于在控制台中打印错误 - 我通过将 sys.stdout.flush() 添加到刷新缓冲区(解释为 here)并在将数据放入队列后等待线程来解决它。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 2015-01-08
    相关资源
    最近更新 更多