J'essaie d'écrire un client non basé sur le web pour un service de chat sur un site web, il se connecte bien via le socket et peut communiquer avec lui et tout. Je vous écris une interface graphique pour (j'essayé d'écrire dans tkinter mais je frappé des murs, je vraiment wantd de se passer, donc je suis passé à wxPython)Besoin d'aide avec wxPython, NotebookCtrl en particulier
Ce que je vais avoir un problème avec:
Cette L'application utilise un widget Notebook étendu appelé NotebookCtrl. Cependant, le même problème apparaît avec un ordinateur portable ordinaire. D'abord, il crée une page dans laquelle les choses sont enregistrées, ce qui est réussi, puis il se connecte, et il est censé ajouter des pages avec chaque salle de chat qu'il rejoint sur le service. Cependant, quand il ajoute un onglet après le démarrage de mainloop (je communique avec l'interface graphique et les sockets via les files d'attente et le thread), l'onglet apparaît complètement vide. J'ai été bloqué sur cela pendant des heures et des heures et suis absolument nulle part
L'exemple fourni avec le téléchargement NotebookCtrl ajoute et supprime parfaitement les pages par lui-même. Je suis sur le point d'abandonner complètement ce projet. Voici ce que le code ressemble (noter que ceci est une très petite partie de l'application, mais cela couvre les choses wxPython)
class Chatroom(Panel):
''' Frame for the notebook widget to tabulate a chatroom'''
def __init__(self, ns, parent):
Panel.__init__(self, parent, -1)
self.msgs, self.typed, self.pcbuff = [], [], {}
self.members, self._topic, self._title, self.pc = None, None, None, None
self.name, self.tabsign, = ns, 0
self.hSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.vSizer = wx.BoxSizer(wx.VERTICAL)
self.Grid = wx.GridBagSizer(5, 2)
self.Title = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Topic = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Privclasses = TreeCtrl(self, size=(150, -1))
self.Buffer = wx.html.HtmlWindow(self)
self.Buffer.SetStandardFonts(8)
self.templbl = StaticText(self, -1, 'This is where the formatting buttons will go!')
# note to remember: self.templbl.SetLabel('string') sets the label
self.Typer = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE)
self.Grid.Add(self.Title, (0,0), (1,2), wx.EXPAND, 2)
self.Grid.Add(self.Topic, (1,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.Privclasses, (1,1), (2,1), wx.EXPAND, 2)
self.Grid.Add(self.Buffer, (2,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.templbl, (3,0), (1,1), wx.EXPAND | wx.ALIGN_LEFT, 2)
self.Grid.Add(self.Typer, (4,0), (1,1), wx.EXPAND, 2)
self.Grid.AddGrowableCol(0)
self.Grid.AddGrowableRow(2)
self.SetSizerAndFit(self.Grid)
self.Show(True)
self.Typer.Bind(EVT_CHAR, self.Typer_OnKeyDown)
def Typer_OnKeyDown(self, event):
keycode = event.GetKeyCode()
if event.ShiftDown():
if keycode == WXK_RETURN:
pass
elif keycode == WXK_BACK:
pass
elif keycode == WXK_UP:
pass
elif keycode == WXK_DOWN:
pass
else:
if keycode == WXK_RETURN:
pass
event.Skip()
def Write(self, msg, K):
self.msgs.append(msg)
if len(self.msgs) > 300:
self.msgs = self.msgs[50:]
self.Buffer.SetPage('<br>'.join(self.msgs))
class Application(App):
def __init__(self, K):
self.Queue = Queue.Queue()
self.current = ''
self.chatorder = []
self.Window = App(0)
self.frame = MainFrame(None, 0, "Komodo Dragon")
self.Pages = NC.NotebookCtrl(self.frame, 9000)
self.Channels = {}
self.AddChatroom('~Komodo', K)
self.frame.Show(True)
self.Window.SetTopWindow(self.frame)
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
self.Pages.Bind(NC.EVT_NOTEBOOKCTRL_PAGE_CHANGED, self.onPageChanged)
self.Pages.Bind(NC.EVT_NOTEBOOKCTRL_PAGE_CHANGING, self.onPageChanging)
self.Pages.Bind(EVT_PAINT, self.onPaint)
self.Pages.Bind(EVT_SIZE, self.onSize)
def onPaint(self, event):
event.Skip()
def onSize(self, event):
event.Skip()
def Run(self):
self.Window.MainLoop()
def onPageChanged(self, event):
event.Skip()
def onPageChanging(self, event):
event.Skip()
# Timer and Queue functions
def OnTimer(self):
self.CheckQueue()
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
def CheckQueue(self): # the Application needs to use a queue to do things in order to prevent
try: # overlaps from happening, such as runtime errors and widgets changing
while not self.Queue.empty(): # suddenly. The most common error seems to be size
func = self.Queue.get_nowait() # changes during iterations. Everything from
func() # packet processing to adding widgets needs to wait in line this way
except Queue.Empty:
pass
def AddQueue(self, func):
self.Queue.put(func)
# Channel controls
def AddChatroom(self, ns, K):
if ns in self.Channels: return
#self.typedindex = 0
c = K.format_ns(ns)
self.chatorder.append(ns)
self.current = ns
self.Channels[ns] = Chatroom(ns, self.Pages)
self.Pages.AddPage(self.Channels[ns], ns, True)
def DeleteChatroom(self, ns, bot): # Delete a channel, it's properties, and buttons
ind = self.chatorder.index(ns)
del self.chatorder[ind]
for each in self.chatorder[ind:]:
x = self.channels[each].tab.grid_info()
if x['column'] == '0': r, c = int(x['row'])-1, 9
else: r, c = int(x['row']), int(x['column'])-1
self.channels[each].tab.grid_configure(row=r, column=c)
x = self.channels[each].tab.grid_info()
self.channels[ns].Tab.destroy()
self.channels[ns].tab.destroy()
self.channels[self.chatorder[-1]].tab.select()
self.switchtab(bot, self.chatorder[-1])
x = self.tabids_reverse[ns]
del self.tabids_reverse[ns], self.tabids[x], self.channels[ns]
La classe Chatroom couvre ce que chaque onglet doit avoir en elle. le premier onglet ajouté dans la classe init de l'application fonctionne parfaitement et imprime même les messages qu'il reçoit du service de discussion lorsqu'il tente de se connecter. Une fois que le service m'envoie un paquet de jointure, il appelle la même fonction que celle utilisée pour ajouter cet onglet, AddChatroom(), et devrait créer exactement la même chose, en n'imprimant que des messages spécifiques pour ce chat. Il crée l'onglet, mais la page Chatroom est complètement vide et grise. Je suis très triste: C
Merci d'avance si vous pouvez m'aider.
EDIT
J'ai écrit un exemple concret de ce script, vous pouvez vous lancer (si vous avez wxPython). Il utilise Notebook au lieu de NotebookCtrl, donc vous n'avez pas besoin de télécharger ce widget, mais le bug survient pour les deux. L'exemple configure la fenêtre et configure l'onglet principal de débogage, puis un onglet de salon de discussion avant d'entrer dans la boucle principale. Après mainloop, tout chatrooms ajouté postfaces sont complètement vide
from wx import *
import Queue, time
from threading import Timer as _Timer
from threading import Thread
# import System._NotebookCtrl.NotebookCtrl as NC ## Using regular notebook for this example
class MainFrame(Frame):
def __init__(self, parent, ID, title):
ID_FILE_LOGIN = 100
ID_FILE_RESTART = 101
ID_FILE_EXIT = 102
ID_HELP_ABOUT = 200
Frame.__init__(self, parent, ID, title,
DefaultPosition, Size(1000, 600))
self.CreateStatusBar()
self.SetStatusText("This is the statusbar")
menu_File = Menu()
menu_Help = Menu()
menu_Edit = Menu()
menu_Config = Menu()
menu_File.Append(ID_FILE_LOGIN, "&Login Info",
"Enter your deviantArt Login information")
menu_File.AppendSeparator()
menu_File.Append(ID_FILE_RESTART, "&Restart",
"Restart the program")
menu_File.Append(ID_FILE_EXIT, "E&xit",
"Terminate the program")
menu_Help.Append(ID_HELP_ABOUT, "&About",
"More information about this program")
menuBar = MenuBar()
menuBar.Append(menu_File, "&File");
menuBar.Append(menu_Edit, "&Edit");
menuBar.Append(menu_Config, "&Config");
menuBar.Append(menu_Help, "&Help");
self.SetMenuBar(menuBar)
EVT_MENU(self, ID_FILE_LOGIN, self.OnLogin)
EVT_MENU(self, ID_FILE_RESTART, self.OnRestart)
EVT_MENU(self, ID_FILE_EXIT, self.OnQuit)
EVT_MENU(self, ID_HELP_ABOUT, self.OnAbout)
def OnAbout(self, event):
dlg = MessageDialog(self, "Hi! I am Komodo Dragon! I am an application\n"
"that communicates with deviantArt's Messaging Network (dAmn)",
"Komodo", OK | ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def OnQuit(self, event):
self.Close(True)
def OnRestart(self, event):
pass
def OnLogin(self, event):
dlg = MessageDialog(self, "Enter your Login information here:\n"
"Work in progress, LOL",
"Login", OK | ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
class Chatroom(Panel):
''' Frame for the notebook widget to tabulate a chatroom'''
def __init__(self, parent, ns):
Panel.__init__(self, parent, -1)
self.msgs, self.typed, self.pcbuff = [], [], {}
self.members, self._topic, self._title, self.pc = None, None, None, None
self.name, self.tabsign, = ns, 0
self.hSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.vSizer = wx.BoxSizer(wx.VERTICAL)
self.Grid = wx.GridBagSizer(5, 2)
self.Title = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Topic = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE | wx.TE_READONLY)
self.Privclasses = TreeCtrl(self, size=(150, -1))
self.Buffer = wx.html.HtmlWindow(self)
self.Buffer.SetStandardFonts(8)
self.templbl = StaticText(self, -1, 'This is where the formatting buttons will go!')
self.Typer = TextCtrl(self, size=(-1, 50), style=wx.TE_MULTILINE)
self.Grid.Add(self.Title, (0,0), (1,2), wx.EXPAND, 2)
self.Grid.Add(self.Topic, (1,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.Privclasses, (1,1), (2,1), wx.EXPAND, 2)
self.Grid.Add(self.Buffer, (2,0), (1,1), wx.EXPAND, 2)
self.Grid.Add(self.templbl, (3,0), (1,1), wx.EXPAND | wx.ALIGN_LEFT, 2)
self.Grid.Add(self.Typer, (4,0), (1,1), wx.EXPAND, 2)
self.Grid.AddGrowableCol(0)
self.Grid.AddGrowableRow(2)
self.SetSizerAndFit(self.Grid)
self.Show(True)
self.Typer.Bind(EVT_CHAR, self.Typer_OnKeyDown)
def Typer_OnKeyDown(self, event):
keycode = event.GetKeyCode()
if event.ShiftDown():
if keycode == WXK_RETURN:
pass
elif keycode == WXK_BACK:
pass
elif keycode == WXK_UP:
pass
elif keycode == WXK_DOWN:
pass
else:
if keycode == WXK_RETURN:
pass
event.Skip()
def Write(self, msg):
self.msgs.append(msg)
if len(self.msgs) > 300:
self.msgs = self.msgs[50:]
self.Buffer.SetPage('<br>'.join(self.msgs))
class Application(App):
def __init__(self, K):
self.Queue = Queue.Queue()
self.current = ''
self.chatorder = []
self.Window = App(0)
self.frame = MainFrame(None, 0, "Komodo Dragon")
self.Pages = Notebook(self.frame, 9000)
self.Channels = {}
self.AddChatroom('~Komodo', K)
self.frame.Show(True)
self.Window.SetTopWindow(self.frame)
self.Timer = _Timer(0.050, self.OnTimer)
self.Pages.Bind(EVT_NOTEBOOK_PAGE_CHANGED, self.onPageChanged)
self.Pages.Bind(EVT_NOTEBOOK_PAGE_CHANGING, self.onPageChanging)
self.Pages.Bind(EVT_PAINT, self.onPaint)
self.Pages.Bind(EVT_SIZE, self.onSize)
def onPaint(self, event):
event.Skip()
def onSize(self, event):
event.Skip()
def onPageChanged(self, event):
event.Skip()
def onPageChanging(self, event):
event.Skip()
def Run(self):
self.Window.MainLoop()
# Timer and Queue functions
def OnTimer(self):
self.CheckQueue()
self.Timer = _Timer(0.050, self.OnTimer)
self.Timer.start()
def CheckQueue(self): # the Application needs to use a queue to do things in order to prevent
try: # overlaps from happening, such as runtime errors and widgets changing
while not self.Queue.empty(): # suddenly. The most common error seems to be size
func = self.Queue.get_nowait() # changes during iterations. Everything from
if func is not None:
func() # packet processing to adding widgets needs to wait in line this way
except Queue.Empty:
pass
def AddQueue(self, func):
self.Queue.put(func)
# Channel controls
def AddChatroom(self, ns, K):
if ns in self.Channels: return
self.chatorder.append(ns)
self.current = ns
self.Channels[ns] = Chatroom(self.Pages, ns)
self.Pages.AddPage(self.Channels[ns], ns, True)
class _Thread(Thread):
def __init__(self, K):
Thread.__init__(self)
self.K = K
def run(self):
self.K.Mainloop()
class K:
def __init__(self):
self.App = Application(self)
self.App.AddQueue(self.App.Channels['~Komodo'].Write('>> Welcome!'))
self.App.AddQueue(self.App.Channels['~Komodo'].Write('>> Entering mainloop...'))
self.App.AddChatroom('#TestChatroom1', self)
self.roomcount = 1
self.timer = time.time() + 3
self.thread = _Thread(self)
self.thread.start()
self.App.Timer.start()
self.App.Run()
def Mainloop(self):
while True:
if time.time() > self.timer:
self.App.AddQueue(
lambda: self.App.Channels['~Komodo'].Write('>> Testing'))
if self.roomcount < 5:
self.roomcount += 1
self.App.AddQueue(
lambda: self.App.AddChatroom('#TestChatroom{0}'.format(self.roomcount), self))
self.timer = time.time() + 3
if __name__ == '__main__':
test = K()
Balise 'notebook' supprimée dans le cadre du [nettoyage de 2012] (http: // méta.stackexchange.com/questions/128315/the-great-stack-overflow-tag-question-cleanup-of-2012). –