display output in Text from module - python

I am working on a tool to log on a motorolla modem, i get it working and display the output on the python console, this tool have 2 part one part with the gui and the button, label and text frame.
i would like to get the output displayed on the Gui and not to the console.
how can i get that done
here is the files :
from Tkinter import *
import motorola
class Application(object):
def init(self):
self.fen = Tk()
self.fen.title("Motorola tool V 0.1")
self.fen.geometry("720x480")
Label(self.fen,
text = "IP address").grid(row=0)
#self.entree = MaxLengthEntry(self.fen, maxlength=5)
self.entree1 = Entry(self.fen)
self.entree1.grid(row=0, column=1)
Label(self.fen,
text = "Password").grid(row=2)
#self.entree = MaxLengthEntry(self.fen, maxlength=5)
self.entree2 = Entry(self.fen)
self.entree2.grid(row=2, column=1)
Button(self.fen, text = 'Connect',
command = self.launch).grid(row = 3, column=2)
Button(self.fen, text = 'Disconect',
command = self.exits).grid(row = 3, column=3)
Button(self.fen, text = 'Quit',
command = self.fen.quit).grid(row = 5, sticky = E)
self.output = Text(self.fen)
self.output.grid(row = 7, column = 1)
self.fen.mainloop()
def launch(self):
self.ip = self.entree1.get()
self.passw = self.entree2.get()
print self.ip, self.passw
if self.passw == "":
self.entree2.config(bg = 'red')
self.fen.after(1000, self.empty)
else:
self.f = motorola.Motorola(self.ip, self.passw)
self.f.sh_dsl()
def empty(self):
self.entree2.configure(bg='white')
def exits(self):
try:
self.f.disconnect()
except AttributeError:
print "You are not connected"
a = Application()
motorola file :
class Motorola(object):
def init(self, ip, passw):
self.ip = ip
self.passw = passw
print "connect on the modem"
self.tn = telnetlib.Telnet(self.ip, '2323' , timeout =5)
self. tn.read_until("login: ")
self.tn.write('radadmin\r\n')
self.tn.read_until("Password:")
self.tn.write(self.passw+"\r\n")
data = self.tn.read_until(">")
print "you are connected"
print data,
def disconnect(self):
self.tn.close()
print "disconnect from the modem"
import telnetlib
once i connect on the modem with the button which launch motorola module, how can the data could be displayed on the frame text of the gui module ?
Thank you

The basic idea is that you have to replace each print with some code that adds the string to the GUI.
The trick is that a Motorola instance probably doesn't know how to do that. So, what you want to do is pass it something—self, or self.output, or best of all, a function (closure) that appends to self.output. Then the Motorola code doesn't have to know anything about Tk (and doesn't have to change if you later write a wx GUI); it just has a function it can call to output a string. For example:
def outputter(msg):
self.output.insert(END, msg + "\n")
self.f = motorola.Motorola(self.ip, self.passw, outputter)
Then, inside the Motorola object, just store that parameter and call it everywhere you were using print:
def __init__(self, ip, passw, outputter):
self.outputter = outputter
# ...
self.outputter("connect on the modem")
That almost does it, but how you do handle the magic trailing comma of the print function, or even simple things like multiple arguments or printing out numbers? Well, you just need to make outputter a little smarter. You could look at the interface of the Python 3 print function for inspiration:
def outputter(*msgs, **kwargs):
sep = kwargs.get("sep", " ")
end = kwargs.get("end", "\n")
self.output.insert(END, sep.join(msgs) + end)
You could go farther—converting non-strings to strings (but not breaking Unicode), etc.—but really, why? If you're trying to get too fancy with print or with your outputter function, you probably want to let str.format do the heavy lifting instead…
Anyway, now, instead of:
print data,
You do:
self.outputter(data, end='')
And all of your other print statements are trivial.

Related

Multiple listboxs bound to same function

Honestly, I do not feel like this should be happening, but it is.
self.marketList.bind('<<ListboxSelect>>', self.market_selected)
self.jobsList.bind('<<ListboxSelect>>', self.job_selected)
There really isn't any more interaction between these two functions. When you click on an item in the marketList box, it's supposed to bring up the jobs in the jobsList box. Currently, it is applying the binding two both boxes. When I click on a job entry in the jobsBox, it clears the jobs and my troubleshooting is showing that it's calling market_selected. I'm not sure why this is happening, but it's really messing with what I'm trying to do with it.
How can I ensure that my binding is on only one widget, and won't be applied to multiple widgets?
edit:
I'm told that this isn't enough code to reproduce the error.
This is all the relevant code.
As I said previously, self.market_selected is called when I click on anything in the jobsList
edit #2
I uploaded the entire script.
import MarketWizard
import JobWizard
import SpanWalkerDocuments as swd
import tkinter as tk
from tkinter import *
from tkinter import ttk
import SpanWalkerDocuments as SpanWalker
class SpanWalker:
def __init__(self):
self.root = tk.Tk()
self.root.title('Luke Spanwalker')
self.root.resizable(True, True)
self.MainFrame = Frame(self.root, bg='red')
self.sidebarFrame = Frame(self.root, bg='blue')
self.tabControl = ttk.Notebook(self.sidebarFrame)
self.marketFrame = Frame(self.tabControl)
self.clientFrame = Frame(self.tabControl)
self.jobsFrame = Frame(self.tabControl)
self.polesFrame = Frame(self.MainFrame, height=100, width=50)
self.tabControl.add(self.marketFrame, text="Markets")
self.tabControl.add(self.jobsFrame, text="Jobs")
self.tabControl.add(self.clientFrame, text="Clients")
#self.tabControl.add(self.polesFrame, text="Poles")
self.tabControl.pack(expand=1, fill="both")
self.MainFrame.grid(row=0, column=1)
self.sidebarFrame.grid(row=0, column=0)
#Awesome, our tabbed control is ready.
#Now, we need to make the listBox widgets that will actually display our data.
self.marketList = Listbox(self.marketFrame)
self.jobsList = Listbox(self.jobsFrame)
self.polesList = Listbox(self.polesFrame)
#Binding functions! Yay for binding functions!
self.marketList.bind('<<ListboxSelect>>', self.market_selected)
self.jobsList.bind('<<ListboxSelect>>', self.job_selected)
self.curMarket = ""
self.markets = []
self.jobs = []
self.poles = []
def UpdateMarkets (self):
if len(self.markets) > 0:
self.markets.clear()
self.marketList.delete(0, END)
for mark in swd.Market.objects:
self.markets.append(mark)
for m in range(0, len(self.markets)):
self.marketList.insert(m, self.markets[m].title)
def OpenMarketWizard(self):
mw = MarketWizard.MarketWizard()
mw.RunMarketWizard(self.root)
def market_selected(self, event):
print("Market Selected")
selection = self.marketList.curselection()
selectedMarket = ",".join([self.marketList.get(i) for i in selection])
self.PopulateJobs(selectedMarket)
def PopulateJobs(self, market):
self.jobs.clear()
self.jobsList.delete(0, END)
self.GetJobs(market)
for j in range(0, len(self.jobs)):
self.jobsList.insert(j, self.jobs[j].jobName)
def GetJobs(self, market):
marketJobs = []
jobs = []
if market =="":
return
for j in swd.Job.objects:
jobs.append(j)
print("Market = {0}".format(market))
for i in jobs:
if i.market == market:
self.jobs.append(i)
def job_selected(self, event):
print("Job Selected")
selection = self.jobsList.curselection()
selectedJob = ",".join([self.jobsList.get(i) for i in selection])
print("The selected job is: {0}".format(selectedJob))
def PopulateMarkets(self):
self.marketList.destroy()
for m in range(0, len(self.markets)):
marketList.insert(m, self.markets[m].title)
def OpenJobWizard(self):
jw = JobWizard.JobWizard()
jw.RunJobWizard(self.root)
#We need to pack everything that belongs in our tabbed function.
def marketListDisplay(self, show):
if show == True:
self.marketList.pack(fill="both")
self.UpdateMarkets()
self.newButton=Button(self.marketFrame, text="Open Market Wizard", command=lambda:self.OpenMarketWizard())
self.newButton.pack()
self.refreshButton=Button(self.marketFrame, text="Refresh Markets", command=lambda:self.UpdateMarkets())
self.refreshButton.pack()
else:
self.marketList.forget_pack()
def jobsListDisplay(self, show):
if show==True:
self.jobsList.pack()
self.newButton = Button(self.jobsFrame, text="Create New Job / Open Job Wizard", command=lambda:self.OpenJobWizard())
self.newButton.pack()
else:
self.jobsList.forget_pack()
def polesListDisplay(self, show):
if show==True:
self.polesList.pack()
else:
self.polesList.forget_pack()
#Query, why not put them all in a function?
sp = SpanWalker()
sp.marketListDisplay(True)
sp.polesListDisplay(True)
sp.jobsListDisplay(True)
The answer was given by acw1668. I just added exportselection=0 during the creation process for the listboxes, and it worked perfectly.
Sorry for the confusion, y'all, I've never really asked for help on here before.
Thanks for the help!

Tkinter app behaves differently when imported than when directly executed [duplicate]

This question already has answers here:
Why is Python running my module when I import it, and how do I stop it?
(12 answers)
Closed 4 years ago.
I am trying to build a GUI.
When I execute the application directly (i.e. double click the python file), I get a different result (console output) to importing it (mainloop).
I would like it to give the following console output:
c
d
e
f
g - from app
as I would like the main loop to be accessible after it has been imported as a module.
I am attempting to make the input and output controllable from an external file importing it as a module.
I get the expected output when I run the file, but when I import it as a module, it appears to run the main loop, as I get a Tkinter mainloop window output.
Here is the code:
class Application(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.text = Lines()
self.text.insert("\n\n\n\n\n")
self.waitingForInput = False
self.inText = ""
self.pack()
self.widgets()
def widgets(self):
self.L1 = Label(self)
self.L1["text"] = self.text.bottomLines
self.L1.pack(side = "top")
self.E1 = Entry(self)
self.E1["width"] = 40
self.E1.pack(side = "top")
self.B1 = Button(self)
self.B1["text"] = "Enter",
self.B1["command"] = self.giveInput
self.B1.pack(side = "top")
def giveInput(self):
if self.waitingForInput:
self.inText = self.B1.get()
self.waitingForInput = False
def getInput(self, output):
giveOutput(output)
self.waitingForInput = True
while True:
time.sleep(0.1)
if not self.waitingForInput:
break
return self.inText
def giveOutput(self, output):
self.text.insert(output)
self.L1["text"] = self.text.bottomLines
print self.text.bottomLines + " - from app"
root = Tk()
app = Application(master = root)
app.giveOutput("a \n b \n c \n d \n e \n f \n g")
The Lines class is essentially a stack of lines of text in a string, stacking more with insert(x) and accessing the final five lines of the stack with bottomLines.
Back on topic, when imported as a module, it runs the main loop, with a label containing what I assume to be 5 empty lines, an entry box and the "Enter" button. I do not want this. I want the same result as when I run the file directly, as I showed before.
I only want the box to appear when the app.mainloop method is called.
What have I done wrong, how is it wrong, and how can I correct it?
This will only run when the module is run directly, not when imported:
if __name__ == "__main__":
root = Tk()
app = Application(master = root)
app.giveOutput("a \n b \n c \n d \n e \n f \n g")

Trouble starting Python Threading loop

I am attempting to make a simple "chat" client in python. I have the basics and everything but I cannot get my threading to work at all. This is a still a work in progress so not all the code is there yet and I know that but if you do have any suggestion as a whole that would be greatly appreciated.
from Tkinter import *
import time
import socket
import thread
import threading
HOST = 'localhost'
PORT = 5454
fromserver = ''
data = ''
#Declares socket information
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind((HOST,PORT))
#Loop for receiving
def receivingloop():
global fromserver
while 1:
fromserver = s.recv(30)
time.sleep(.5)
class ChatClient:
def __init__(self, master):
#Use Global fromserver
global fromserver
global data
#Create both frames
top_frame = Frame(master)
bot_frame = Frame(master)
#Create and pack the Buttons
self.send_but = Button(bot_frame, \
text='Send',\
command=self.sending)
self.quit_but = Button(bot_frame, \
text='Quit', \
command=client_window.destroy)
self.send_but.pack(side=LEFT)
self.quit_but.pack(side=LEFT)
#Create and pack label
self.received_lab = Label(top_frame,\
text=(fromserver))
self.received_lab.pack()
self.sent_lab = Label(top_frame,\
text='Message Sent: ' +data)
self.sent_lab.pack()
self.sending_entry = Entry(top_frame, \
width=10)
self.sending_entry.pack()
#Pack Frames
top_frame.pack()
bot_frame.pack()
#Function to send stuff
def sending(self):
global data
s.sendto(data,(HOST,PORT))
data = str(self.sending_entry.get())
print data
#Start the thread
l1 = threading.Thread(target=receivingloop)
l1.start()
client_window = Tk()
chat_client = ChatClient(client_window)
client_window.mainloop()
If I'm not mistaken I would say the receivingloop method takes the self element but the self argument you need only by classes and this method is not in a class
Try this:
#Loop for receiving
def receivingloop():
global fromserver
while 1:
fromserver = s.recv(30)
time.sleep(.5)
Your function is defined with a variable called 'self', it looks like you previously had this function in a class, but decided to extract it from the class later on.
Anyway, to fix your problem, it should just be:
def receivingloop():
Note that the 'self' part from the function arguments has been removed.
Also, you might want to add global data to your send function.

First letters of a Tkinter input

My program should check if the first three letters of the input word are similar to a predefined word.
I've made a GUI with Tkinter and want to get the letters of the input field.
Somehow I can't implement it in like I would do without Tkinter.
That's how I do it just for the shell:
text = raw_input('Enter a word: ')
if (text[0] + text[1] + text[2] == 'sag'):
print "sagen"
else:
print "error"
So, when I input the word "sagst" it checks the first three letters and should put out "sagen". Works fine.
I learned that e.g. inputfield.get() gets the input of the entry "inputfield".
But how can I check the first letters of that "inputfield"?
A small selection:
from Tkinter import*
root = Tk()
def check():
if (text[0] + text[1] + text[2] == 'sag'):
print "True"
else:
print "False"
inputfield = Entry(root)
inputfield.pack()
but = Button(root,text='Check!', command = check)
but.pack()
text = inputfield.get()
root.mainloop()
Does not work...
I hope you can understand my question and will answer soon. (Sorry for my bad english and my bad Python skills) ;-)
Thanks!
Your check function will have to retrieve the textfield after the button has been pressed:
def check():
text = inputfield.get()
print text.startswith('sag')
I've changed your test a little, using .startswith(), and directly printing the result of that test (print will turn boolean True or False into the matching string).
What happens in your code is that you define inputfield, retrieve it's contents (obviously empty), and only then show the TKInter GUI window by running the mainloop. The user never gets a chance to enter any text that way.
You can also check this without the need for a button (Now it will check whenever the user presses "Enter"):
from Tkinter import *
root = Tk()
def check(*event):
text = inputfield.get()
print text.startswith('sag')
inputfield = Entry(root)
inputfield.bind('<Return>',check)
inputfield.pack()
root.mainloop()
You can also do other things to have your widget validate the entry as you type. (The link is old, but it also points to newer features that allow you to do this without subclassing).
You're not actually putting the value in the input field into the text variable.
I renamed the value from text to input_text because it was confusing to me. I also changed from using text[0] + text[1] + text[2] to using startswith(). This will keep you from getting IndexErrors on short strings, and is much more pythonic.
from Tkinter import*
root = Tk()
def check():
input_text = inputfield.get()
if input_text.startswith('sag'):
print "True"
else:
print "False"
inputfield = Entry(root)
inputfield.pack()
input_text = inputfield.get()
print input_text # Note that this never prints a string, because it only prints once when the input is empty.
but = Button(root, text='Check!', command=check)
but.pack()
root.mainloop()
The key change is that the check function needs to actually get the value in the inputfield.
Here is a version which uses an Entry widget which validates its contents as the user types (so the user does not have to click a button or even press Return).
import Tkinter as tk
class MyApp(object):
'''
http://effbot.org/zone/tkinter-entry-validate.htm
http://effbot.org/tkinterbook/entry.htm
http://www.tcl.tk/man/tcl8.5/TkCmd/entry.htm#M-validate
'''
def __init__(self, master):
vcmd = (master.register(self.validate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(master, validate = 'key',
validatecommand = vcmd)
self.entry.pack()
self.entry.focus()
def validate(self, action, index, value_if_allowed,
prior_value, text, validation_type, trigger_type, widget_name):
dtype = {'0':'delete', '1':'insert', '-1':'other'}[action]
n = min(3, len(value_if_allowed))
valid = False
if dtype == 'insert':
if value_if_allowed[:n] == 'sag'[:n]: valid = True
else: valid = False
else: valid = True
print(valid)
return True
root = tk.Tk()
app = MyApp(root)
root.mainloop()

classmethod for Tkinter-Monitor-Window

I would like to realise a monitor window that reports the user about ongoing computations. To do so I wrote a little class. But as I would like to use it accross different modules in an easy fashion I thought to implement it with classmethods. This allows to use it in the following way without instances:
from MonitorModule import Monitor
Monitor.write("xyz")
Also, if I use it in an other module, the output of Monitor.write() within other_module.py will be displayed in the same window.
This I can import in each module to redirect specific outputs to the same monitor. I got it to work except one little thing that I don't understand. I can't close the Monitor-window with the specific handler that I wrote. I could do it with the non-classmethod-way but not with the handler as a classmethod.
Look at the code:
import Tkinter
class Monitor_non_classmothod_way(object):
def __init__(self):
self.mw = Tkinter.Tk()
self.mw.title("Messages by NeuronSimulation")
self.text = Tkinter.Text(self.mw, width = 80, height = 30)
self.text.pack()
self.mw.protocol(name="WM_DELETE_WINDOW", func=self.handler)
self.is_mw = True
def write(self, s):
if self.is_mw:
self.text.insert(Tkinter.END, str(s) + "\n")
else:
print str(s)
def handler(self):
self.is_mw = False
self.mw.quit()
self.mw.destroy()
class Monitor(object):
#classmethod
def write(cls, s):
if cls.is_mw:
cls.text.insert(Tkinter.END, str(s) + "\n")
else:
print str(s)
#classmethod
def handler(cls):
cls.is_mw = False
cls.mw.quit()
cls.mw.destroy()
mw = Tkinter.Tk()
mw.title("Messages by NeuronSimulation")
text = Tkinter.Text(mw, width = 80, height = 30)
text.pack()
mw.protocol(name="WM_DELETE_WINDOW", func=handler)
close = handler
is_mw = True
a = Monitor_non_classmothod_way()
a.write("Hello Monitor one!")
# click the close button: it works
b = Monitor()
Monitor.write("Hello Monitor two!")
# click the close button: it DOESN'T work, BUT:
# >>> Monitor.close()
# works...
So, the classmethod seems to work and also seems to be accessible in the right way! Any idea, what went wrong, that it doesn't work with the button?
Cheers, Philipp
You don't need lots of classmethods just to make it easy to use an object across multiple modules.
Instead consider making an instance at module import time as shown here:
import Tkinter
class Monitor(object):
def __init__(self):
self.mw = Tkinter.Tk()
self.mw.title("Messages by NeuronSimulation")
self.text = Tkinter.Text(self.mw, width = 80, height = 30)
self.text.pack()
self.mw.protocol(name="WM_DELETE_WINDOW", func=self.handler)
self.is_mw = True
def write(self, s):
if self.is_mw:
self.text.insert(Tkinter.END, str(s) + "\n")
else:
print str(s)
def handler(self):
self.is_mw = False
self.mw.quit()
self.mw.destroy()
monitor = Monitor()
other_module.py
from monitor import monitor
monitor.write("Foo")

Categories

Resources