I have made a python script which creates a MacOS Status bar item which displays youtube statistics.
I want to add dividers to the drop down menu when you click the text but I am unable to do this. (Image of what I mean under the text). I have found many examples but all of them only work with an __init__ function in the class. If I try adding an __init__ function to the class I get an error saying AttributeError: 'Sub_Counter' object has no attribute '_menu'. Why is this happening and how can it be fixed?
Code I added to the __init_ function
self.menu = [
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
Normal Code without the __init__ function
import rumps
import time
import sys
import os
from sty import fg
from googleapiclient.discovery import build
key = open(os.path.join(sys.path[0], './key.txt')).read().strip()
service = build('youtube', 'v3', developerKey=key)
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
timers = ["1 secs","5 secs","10 secs","15 secs","20 secs","25 secs","30 secs","35 secs","45 secs","50 secs","1 Min"]
EXEC_TIMER = 60
class Sub_Counter(rumps.App):
#rumps.timer(EXEC_TIMER)
def pull_data(self, _):
self.sub_menu = timers
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
a = (str(subs))
self.icon = "logo.png"
self.title = "Subscribers: " + str(a)
self.notification = str(a) + " Subscribers"
#rumps.clicked("About")
def about(self, _=):
rumps.notification("Youtube Subscriber Count", "Made by Roxiun using Python & rumps", "Shows Youtube Subscriber counts")
#rumps.clicked("No Icon")
def noicon(self, sender):
sender.state = not sender.state
self.icon = None
#rumps.clicked("Detailed Statistics")
def Detailed_Statistics(self, _):
rumps.notification("You have:", self.notification , "Veiws Comming Soon")
if __name__ == "__main__":
Sub_Counter("Loading...").run() #debug=True
Image of what I want to do [circled in red - (Yes it is the line)]
Thanks in advance!
Fixed by doing
app = Sub_Counter("Loading...")
app.menu[
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
app.run()
You can add a separator by doing:
self.menu.add(rumps.separator)
Link to source code.
Related
I'm trying to create a chatbot program with CHATTERBOT MODULE and TKINTER.
It's almost ok, in fact my problem is that every button-click, the program creates me new labels, with command risposta.pack().
My intent is creating just one label and update it every other button-click.
How can I do it?
MY CODING:
from chatterbot import ChatBot
from tkinter import *
import time
from chatterbot.trainers import ListTrainer
bot = ChatBot(
"GUI Bot",
storage_adapter="chatterbot.storage.SQLStorageAdapter",
input_adapter='chatterbot.input.VariableInputTypeAdapter',
output_adapter='chatterbot.output.OutputAdapter',
database='../database,db',
logic_adapters=[
{
"import_path": "chatterbot.logic.BestMatch",
"statement_comparison_function": "chatterbot.comparisons.levenshtein_distance",
"response_selection_method": "chatterbot.response_selection.get_first_response"
}
]
)
with open('/home/griguols/Scrivania/chatterbot/istruzioni.txt') as istruzioni:
conversation = istruzioni.readlines()
bot.set_trainer(ListTrainer)
bot.train(conversation)
def command():
global risposta
user_input = input.get()
response = bot.get_response(user_input)
risposta = Label(schermata, text=str(response.text))
risposta.pack()
schermata = Tk()
ment = StringVar()
schermata.geometry('1000x500')
schermata.title('OMERO')
titolo = Label(schermata,text='OMERO')
titolo.pack()
input = Entry(schermata,textvariable=ment)
input.pack()
bottone = Button(schermata,text='PARLA CON OMERO',command=command)
bottone.pack()
schermata.mainloop()
To solve this issue, you can pack the label (only one time) after the button, so the last part of the code would look as follows:
bottone = Button(schermata,text='PARLA CON OMERO',command=command)
bottone.pack()
risposta = Label(schermata, text="")
risposta.pack()
schermata.mainloop()
Then, change the command function so that it only updates the text of the already packed label:
def command():
global risposta
user_input = input.get()
response = bot.get_response(user_input)
risposta['text']=str(response.text)
PS: I could not execute the with scope since you have not provided the .txt file. For you next post, please consider providing an MCVE.
I'm trying read and parse a CSV file in LibreOffice Calc. I need to show text in order to debug my logic, and the first thing I found was this. Annoyingly, it duplicates functionality that's built into OOo Basic. The first implementation tries to use a non-existent function; the second one works if I invoke it directly (using TestMessageBox from the Tools menu), but when I include it from my pythonpath directory I get an error:
com.sun.star.uno.RuntimeExceptionError during invoking function main
in module
file:///C:/path/to/test.py
(: 'module' object has no attribute
'MessageBox' C:\path\to\test.py:34
in function main() [msgbox.MessageBox(parentwin, message, 'Title')]
C:\Program Files (x86)\LibreOffice 5\program\pythonscript.py:870 in
function invoke() [ret = self.func( *args )] )
Why is there no attribute MessageBox?
I'm invoking it like this:
import msgbox
def main():
doc = XSCRIPTCONTEXT.getDocument()
parentwin = doc.CurrentController.Frame.ContainerWindow
message = "Message"
msgbox.MessageBox(parentwin, message, 'Title')
return
And here's pythonpath/msgbox.py:
import uno
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE
from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
def TestMessageBox():
doc = XSCRIPTCONTEXT.getDocument()
parentwin = doc.CurrentController.Frame.ContainerWindow
s = "This a message"
t = "Title of the box"
res = MessageBox(parentwin, s, t, QUERYBOX, BUTTONS_YES_NO_CANCEL + DEFAULT_BUTTON_NO)
s = res
MessageBox(parentwin, s, t, "infobox")
# Show a message box with the UNO based toolkit
def MessageBox(ParentWin, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK):
ctx = uno.getComponentContext()
sm = ctx.ServiceManager
sv = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
myBox = sv.createMessageBox(ParentWin, MsgType, MsgButtons, MsgTitle, MsgText)
return myBox.execute()
g_exportedScripts = TestMessageBox,
The package name msgbox is already used in UNO. See msgbox.MsgBox. Choose a different name for your module instead, such as mymsgbox.py. Even better, move it to a package (subdirectory) inside pythonpath, such as mystuff.msgbox.MessageBox.
As a matter of fact, I tried msgbox.MsgBox just now and it seemed like it could be useful:
import msgbox
def main():
message = "Message"
myBox = msgbox.MsgBox(XSCRIPTCONTEXT.getComponentContext())
myBox.addButton("oK")
myBox.renderFromButtonSize()
myBox.numberOflines = 2
myBox.show(message,0,"Title")
I was wondering if there is any way to find the name of the last window created in Maya, knowing that I can't add any information to the window itself before that... I checked in both the cmds and API but couldn't find anything. Maybe in PyQt but I don't know much about it.
I'm looking for any solution. Thanks
you can work with something like a close callback, save the needed information and restore it again
def restoreLayout(self):
"""
Restore the layout of each widget
"""
settings=self.settings
try:
self.restoreGeometry(settings.value("geometry").toByteArray())
self.restoreState(settings.value("windowState").toByteArray())
size=settings.value('fontSize').toFloat()[0]
self.setFontSize(size)
except:
pass
def saveLayout(self):
"""
Save the layout of each widget
Save the main window id to your data base
"""
settings=self.settings
settings.setValue("geometry", self.saveGeometry())
settings.setValue("windowState", self.saveState())
settings.setValue("fontSize", app.font().pointSize())
def closeEvent(self, event):
QtGui.QMainWindow.closeEvent(self, event)
self.saveLayout()
a simple case/idea to save tha main win_id and a child button_id:
from functools import partial
import json
def close_ui(*args):
win_id = args[0]
if cmds.window(win_id, exists=True):
cmds.deleteUI(win_id, window=True)
with open('dataBase/ui/uidata.json', 'w') as outfile:
json.dump(args, outfile)
win = {}
win["main_win"] = cmds.window()
cmds.columnLayout()
cmds.text( label='closing it' )
win["btn"] = cmds.button( label='Close')
cmds.button(win["btn"],e=True, command=partial(close_ui, win["main_win"], win["btn"]))
cmds.showWindow(win["main_win"])
Here is what I came up with, it's surely not the "cleanest" solution but it works!
# List all the currently opened windows
uisBefore = cmds.lsUI (wnd = True)
# Execute the function which may or may not create a window
func(*args, **kwargs)
# List all the opened windows again
uisAfter = cmds.lsUI (wnd = True)
# Find all the windows that were opened after executing func()
newUIs = [ui for ui in uisAfter if ui not in uisBefore]
If you create a window with the window command, you'll get back the name of the window you just created:
import maya.cmds as cmds
w = cmds.window()
c= cmds.columnLayout()
def who_am_i(*_):
print "window is", w
b = cmds.button('push', c=who_am_i)
cmds.showWindow(w)
If for some reason you don't own the code that creates the window:
existing_windows = set(cmds.lsUI(type = 'window'))
// make your window here
new_windows = list(set(cmds.lsUI(type = 'window') - existing_windows))
I'm trying to make an program for twitch, where the twitch chat can vote by typing a command ("!voteA") for example, and the chatbot-code will count the votes, and show them in a GUI window, I've already gotten pretty far, but my GUI window is not opening and I think it has something to do with the self.after(10, self.get_votes) line, could anyone help me out?
Here's the code: (it has some more tabs like Read, Socket, Initialize, Settings, but I don't think they're relevant for now, if they are I can also post them)
import Tkinter as tk
from Read import getUser, getMessage
from Socket import openSocket, sendMessage
from Initialize import joinRoom
from collections import OrderedDict
class App(tk.Frame): #Toplevel is a frame with a specific use. Unless there is another window, you want a Frame.
def __init__(self):
options = [
"voteA",
"voteB",
"voteC"]
self.s = openSocket()
joinRoom(self.s)
self.readbuffer = ""
tk.Frame.__init__(self)
self['background']='black'
self.pack()
self.master.geometry("+200+200")
# self.master.attributes("-alpha", 0.7)
self.labels = OrderedDict()
for option in options:
label = tk.Label(
self,
bg="black",
fg="white",
font="HouseSlant-Regular 30",
anchor="w")
label.pack()
self.labels[option] = [0, label]
self.update_text()
self.after(10, self.get_votes)
def update_text(self):
for name, data in self.labels.items():
count, label = data
label['text'] = "{} has {} votes".format(name, count)
def get_votes(self):
self.after(10, self.get_votes)
self.readbuffer = self.readbuffer + self.s.recv(1024)
temp = self.readbuffer.split('\n')
self.readbuffer = temp.pop() #save the last (possibly incomplete) line for later
if self.readbuffer == "":
pass #no further messages in the queue
#you should add a sleep time here for the sake of your hot NIC
for line in temp:
print(line)
if "PING" in line:
s.send("PONG :tmi.twitch.tv\r\n".encode())
break
user = getUser(line)
message = getMessage(line)
print "{} typed: {}".format(user, message)
if "!commands" in message:
sendMessage(self.s, " ".join(["!"+option for option in self.labels]))
break
for option in self.labels:
if "!"+option in message:
self.labels[option][0] += 1
print self.labels[option][0]
self.update_text()
app=App()
app.mainloop()
What happens when I run the code, is that the chatbot works; if I type "!commands" or "!voteA" it will respond to that nicely, however, the GUI window isn't opening. I can see in my dock (I'm a mac user) that it's trying to open a window, but it freezes and then I have to force quit it. It's not giving an error in the compiler though. Does anyone have any idea what I've messed up?
Getting this error when pressing the "Close Window" button in my UI. This button should delete the UI window but isn't. Full traceback:
Error: deleteUI: Object 'Animation_Copy_Tool' not found.
Traceback (most recent call last):
File "", line 36, in closeBtnCmd
RuntimeError: deleteUI: Object 'Animation_Copy_Tool' not found. #
# Animation Copy Tool
# Bakari Holmes 5/7/2015
# This is designed to copy and existing animation
# from one rig to another and make the process easier
# with a simple UI
import maya.cmds as mc
import functools
import maya.mel as mm
import pprint
class AnimCopyWindow(object):
##classmethod
def showUI(cls):
win = cls()
win.create()
return win
def __init__(self):
self.window = "Animation Copy Tool"
self.title = "Animation Copier"
self.size = (546,350)
def pasteTheseKeys(self, *args):
self.offsetVal = mc.intFieldGrp(self.int_offset, q=True, value1=True)
self.selObj_pasteKeys = mc.ls(sl=True)
for objectQuant in self.selObj_pasteKeys:
print objectQuant
self.ct = mc.currentTime(query = True)
self.t = self.ct + self.offsetVal
mc.currentTime(self.t)
# mc.selectKey(selObj_pasteKeys[objectQuant])
mc.pasteKey(time=(self.t,self.t), f=(1.0,1.0), option="merge", copies=1, to=0, fo=0, vo=0)
def closeBtnCmd(self,*args):
mc.deleteUI(self.window,window=True)
def create(self):
# check to see if window exists already
if mc.window(self.window,exists=True):
mc.deleteUI(self.window,window=True)
self.window = mc.window(self.window, title=self.title,widthHeight=self.size,menuBar=True)
self.copyAnim = mc.window(title="Transfer Animation Tool", backgroundColor=[0.3,0.3,0.3],sizeable=False,resizeToFitChildren=True)
#set the layout for UI
mc.columnLayout(adjustableColumn=True)
self.tx_src = mc.textFieldGrp(label="Source Object", editable=False, text=sel[0])
self.int_offset = mc.intFieldGrp(label="Frame Offset Amount", value1=0)
#add paste animation button
self.btn1 = mc.button(label="PASTE ANIMATION", command=self.pasteTheseKeys, bgc=[0.1,0.1,0.5])
#add close button window
self.btn2 = mc.button(label="CLOSE WINDOW", command=self.closeBtnCmd, bgc=[0.2,0.2,0.2])
mc.showWindow()
#################################
#####end of class definition#####
#################################
def keys_as_dictionary(channel):
"""return a dictionay of times:values for <channel>"""
keys = mc.keyframe(channel, q=True, tc=True) or []
values = mc.keyframe(channel, q=True, vc=True) or []
return dict(zip(keys, values))
def channels():
"""return a dictionary of <plug>:<channel_dict> for each animated plug selected"""
keys = mc.keyframe(sl=True, n=True, q=True)
result = {}
for k in keys:
plugs = mc.listConnections(k, p=True)[0]
result[plugs]= keys_as_dictionary(k)
return result
#store selected object info
sel = mc.ls(selection=True)
if (len(sel) != 1):
mm.eval("warning Must select one animated object;")
else:
mc.copyKey()
win = AnimCopyWindow()
win.create()
pprint.pprint(channels())
This error almost always means your UI element is not named what you think it is: Maya will automatically rename the items to make sure that no two siblings have the same name -- you can ask for "my_window" and get back "my_window123" . So you need to capture the actual name that is returned from cmds.window() or whatever ui command you use and delete that. Hard coded names are never reliable