python3 线程同步_GTK3和Python中的线程同步

我目前正在学习Python和GTK 3,并且在同步线程时遇到问题.我将尝试快速而清晰:

我必须创建一个社交网络客户端.因为目的是学习如何创建GUI,所以将模拟“对社交网络API的访问”,但我必须“等待” time.sleep()的网络响应.在主线程中调用time.sleep()会冻结GUI(它停止执行Gtk.Main()),因此我必须在单独的线程中进行所有连接.

这就是我的问题.在验证用户身份(verifying_credentials)时,我需要从该线程中等待完成以继续执行主程序.如果尝试Thread.join,GUI会冻结.我试过使用队列,但是queue.get也阻止了Gtk.main().

我尝试在线程完成时发出信号,但是处理程序在同一线程中启动,因此,当我尝试修改GUI(我需要)时,程序崩溃(您不应该从任何地方触摸GUI)除了主线程).

我的解决方案?我做忙等待/活动等待,这在定义上是一种反模式.我一直在问线程是否已经完成并强迫Gtk.main()

必须有另一种方法,比我的方法更优雅/更有效.

我不知道我是否可以发信号通知另一个线程,或者有一种使用队列而不阻塞主线程的方法.任何帮助将不胜感激.

python代码:

from os.path import abspath, dirname, join

import gettext

import threading

import math

import time

import random

import locale

from gi.repository import Gtk, Gdk, GLib, GObject

import list

APP = "UDC_Social_API"

user_list = {

"user": "password",

"admin": "admin",

"carnotan": "1234"

}

class UDC_Social_API:

def on_applicationwindow1_key_press_event(self, widget, event):

# keyname = Gdk.keyval_name(event.keyval)

# print (_("Key %(name)s (%(val)d) was pressed" )%{"name":keyname, "val":event.keyval})

if event.keyval == 65293:

self.on_login_button_clicked()

def delay(self):

if self.delay_option.get_active():

time.sleep(math.exp(random.random()*5))

else:

pass

def active_waiting(self):

while self.finished is False:

Gtk.main_iteration_do(False)

self.finished = False

self.z_handler(None)

def verify_credentials(self, user, password):

GLib.idle_add(self.active_waiting)

self.delay()

if user in user_list:

if password == user_list.get(user):

self.authentication = True

self.finished = True

else:

self.authentication = False

self.finished = True

else:

self.authentication = False

self.finished = True

def on_login_button_clicked(self, data=None):

user = self.user_entry.get_text()

password = self.password_entry.get_text()

thread = threading.Thread(target=self.verify_credentials, args=(user, password))

thread.daemon = True

thread.start()

def z_handler(self, data=None):

if self.authentication is False:

self.message_dialog.set_markup(_("User/Password incorrect

Please, verify login information"))

self.message_dialog.run()

self.message_dialog.hide()

return False

else:

self.window.hide()

print ("Success!")

def on_applicationwindow1_destroy(self, data=None):

Gtk.main_quit()

def on_gtk_about_activate(self, menuitem, data=None):

self.aboutdialog.run()

self.aboutdialog.hide()

def on_gtk_cut_activate(self, widget):

# Get the bounds of the selected text

bounds = self.focus.get_selection_bounds()

# if the bounds of the selection are not an empty tuple,

# put the selection in the variable chars

# and copy it to the clipboard

# (get_selection_bounds returns an empty tuple if there is no selection)

# then delete the selection

if bounds:

chars = self.focus.get_chars(*bounds)

self.clipboard.set_text(chars, -1)

self.focus.delete_text(bounds[0], bounds[1])

else:

pass

def on_gtk_copy_activate(self, widget):

# Get the bounds of the selected text

bounds = self.focus.get_selection_bounds()

# if the bounds of the selection are not an empty tuple,

# put the selection in the variable chars

# and copy it to the clipboard

# (get_selection_bounds returns an empty tuple if there is no selection)

if bounds:

chars = self.focus.get_chars(*bounds)

self.clipboard.set_text(chars, -1)

else:

pass

def on_gtk_paste_activate(self, widget):

# Get the text from the clipboard

text = self.clipboard.wait_for_text()

if text is not None:

# If there's text selected in the target

# delete it and paste the contents of the clipboard

bounds = self.focus.get_selection_bounds()

if bounds:

self.focus.delete_text(bounds[0], bounds[1])

self.focus.insert_text(text, bounds[0])

# else insert the text in the current position of the cursor in the target

else:

pos = self.focus.get_position()

self.focus.insert_text(text, pos)

else:

pass

def on_entry_focus(self, widget, event):

self.focus = widget

def create_menubar(self):

self.file_menu=self.builder.get_object("menuitem1")

self.edit_menu=self.builder.get_object("menuitem2")

self.options_menu=self.builder.get_object("option")

self.help_menu=self.builder.get_object("menuitem4")

self.languages_menu=self.builder.get_object("menuitem3")

self.delay_option = self.builder.get_object("delay_option")

self.gtk_quit_menu=self.builder.get_object("gtk_quit_menu")

self.gtk_cut_menu=self.builder.get_object("gtk_cut_menu")

self.gtk_copy_menu=self.builder.get_object("gtk_copy_menu")

self.gtk_paste_menu=self.builder.get_object("gtk_paste_menu")

self.gtk_about_menu=self.builder.get_object("gtk_about_menu")

self.galician_option=self.builder.get_object("radiomenuitem1")

self.spanish_option=self.builder.get_object("radiomenuitem2")

self.english_option=self.builder.get_object("radiomenuitem3")

def set_menubar_names(self):

self.file_menu.set_label(_("_File"))

self.edit_menu.set_label(_("_Edit"))

self.options_menu.set_label(_("_Options"))

self.help_menu.set_label(_("_Help"))

self.languages_menu.set_label(_("_Languages"))

self.delay_option.set_label(_("_Delay"))

self.gtk_quit_menu.set_label(_("Quit"))

self.gtk_copy_menu.set_label(_("Copy"))

self.gtk_cut_menu.set_label(_("Cut"))

self.gtk_paste_menu.set_label(_("Paste"))

self.gtk_about_menu.set_label(_("About"))

self.galician_option.set_label(_("_Galician"))

self.spanish_option.set_label(_("_Spanish"))

self.english_option.set_label(_("_English"))

def create_login_box(self):

self.user_entry = self.builder.get_object("user_entry")

self.password_entry = self.builder.get_object("password_entry")

self.user_label=self.builder.get_object("user_label")

self.password_label=self.builder.get_object("password_label")

self.login_button=self.builder.get_object("login_button")

def set_login_box_names(self):

self.user_entry.set_placeholder_text(_("user"))

self.password_entry.set_placeholder_text(_("password"))

self.user_label.set_label(_("User"))

self.password_label.set_label(_("Password"))

self.login_button.set_label(_("Login"))

def create_about_dialog(self):

self.aboutdialog = self.builder.get_object("aboutdialog1")

self.aboutdialog.set_transient_for(self.window)

def set_about_dialog(self):

self.aboutdialog.set_comments(_("Developed for GTK 3+ and Python 3.4"))

def reset_names(self):

self.set_menubar_names()

self.set_login_box_names()

def on_radiomenuitem1_toggled(self, widget):

if widget.get_active():

self.lang_gl_ES.install()

self.reset_names()

self.window.queue_draw()

else:

pass

def on_radiomenuitem2_toggled(self, widget):

if widget.get_active():

self.lang_es_ES.install()

self.reset_names()

self.window.queue_draw()

else:

pass

def on_radiomenuitem3_toggled(self,widget):

if widget.get_active():

self.lang_en_US.install()

self.set_menubar_names()

self.window.queue_draw()

else:

pass

def set_languages(self):

WHERE_AM_I = abspath(dirname(__file__))

locale.setlocale(locale.LC_ALL, '')

locale.bindtextdomain(APP, WHERE_AM_I)

locale_path = WHERE_AM_I +'/'

self.builder.set_translation_domain(APP)

gettext.find(APP,localedir=locale_path,languages=['gl_ES'])

gettext.find(APP,localedir=locale_path,languages=['es_ES'])

gettext.find(APP,localedir=locale_path,languages=['en_US'])

gettext.install(APP,locale_path)

gettext.textdomain(APP)

gettext.bindtextdomain(APP,locale_path)

self.lang_gl_ES=gettext.translation(APP,localedir=locale_path, languages=['gl_ES'])

self.lang_es_ES=gettext.translation(APP,localedir=locale_path, languages=['es_ES'])

self.lang_en_US=gettext.translation(APP,localedir=locale_path, languages=['en_US'])

def set_signals(self):

handlers = {

"on_applicationwindow1_destroy": self.on_applicationwindow1_destroy,

"on_gtk_about_activate": self.on_gtk_about_activate,

"on_login_button_clicked": self.on_login_button_clicked,

"on_applicationwindow1_key_press_event": self.on_applicationwindow1_key_press_event,

"on_entry_focus": self.on_entry_focus,

"on_gtk_cut_activate": self.on_gtk_cut_activate,

"on_gtk_copy_activate": self.on_gtk_copy_activate,

"on_gtk_paste_activate": self.on_gtk_paste_activate,

"on_radiomenuitem1_toggled": self.on_radiomenuitem1_toggled,

"on_radiomenuitem2_toggled": self.on_radiomenuitem2_toggled,

"on_radiomenuitem3_toggled": self.on_radiomenuitem3_toggled

}

self.builder.connect_signals(handlers)

def __init__(self):

# GObject.signal_new("z_signal", Gtk.ApplicationWindow, GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ())

self.builder = Gtk.Builder()

self.builder.add_from_file("p1.glade")

self.window = self.builder.get_object("applicationwindow1")

self.set_languages()

self.create_menubar()

self.create_login_box()

self.create_about_dialog()

self.reset_names()

self.set_signals()

self.focus = None

self.finished = False

self.authentication = False

# self.statusbar = self.builder.get_object("statusbar1")

# self.context_id = self.statusbar.get_context_id("status")

# self.status_count = 0

self.message_dialog = self.builder.get_object("messagedialog1")

self.message_dialog.set_transient_for(self.window)

self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

self.window.show_all()

if __name__ == "__main__":

GObject.threads_init()

main = UDC_Social_API()

Gtk.main()

Glade文件位于pastebin中,因为它将超出发布大小限制.

预先感谢您可以提供的任何帮助.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值