I want to launch a warning using tkMessageBox in Python3. This warning is supposed to launch when a user doesn't select an element from a listbox. Unfortunately whenever I try to implement message box it does not launch like it is supposed to. I have code for a script called pietalkgui.py which contains the code where I want to implement the message box:
from tkinter import messagebox
# Gives warning if no user is selected for whisper
def whisperwarning(self):
# show warning to user
showwarning("Select User","Select a user to whisper to!")
# Handles whisper
def whispermessage(self):
# stores element selected in temp variable
temp = self.userslist.get(self.userslist.curselection())
# if no item is selected from userslist (listbox)
if temp == "":
# launch warning to user if no item is selected
self.whisperwarning()
else:
# retrieves usernames from userslist
username = temp
# storing whisper
outwhisper = ' /w "' + username +'" ' + self.messagebox.get("0.0",END)
# handling whisper
self.handler(outwhisper)
# erase message in message box
self.messagebox.delete("0.0",END)
Am I doing something wrong in the implementation of tkMessageBox? Or am I not properly checking if not item is selected from the listbox?
It appears that you are calling the method showwarning, but haven't defined it or imported it. That is the name of a function the messagebox module, so perhaps you need to change this:
showwarning("Select User","Select a user to whisper to!")
... to this:
messagebox.showwarning("Select User","Select a user to whisper to!")
Also, FWIW, this code is slightly incorrect: self.messagebox.delete("0.0",END) -- text indices start at "1.0", not "0.0".
Related
I'm trying to automatize Outlook with python with win32com.client in python.
I have already a Macro that creates me a email, with all the subject and attached files.
The problem is that when I try to automatize it with Python, i don't know how to select the window that the macro open with all the info, and put the address to whom i want to send.
Example:
I want to send it to "Albert" all the emails that has number "1234" in attach files.
Also, i get error " AttributeError: 'NoneType' object has no attribute 'To' "
outlook = win32.dynamic.Dispatch('Outlook.Application')
namespace = outlook.GetNameSpace('MAPI')
mail = outlook.ActiveWindow().Display()
print(type(mail))
mail. To = "Albert#gmail.com"
mail. Send()
Code from VBA is : (i deleted some details that are not important)
'Generate MailID
strMailID = GenerateMailID
'Generate xls file
strFileName =Environ$("temp") & "/file directory"
'Create mail and attach xls file
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.Subject = "DETAILS FROM EXCEL "
.HTMLBody = "DETAIILS "
.Attachments.Add strFileName
.UserProperties.Add "MailID", 1, False, 1
.UserProperties("MailID") = strMailID
.Display
Firstly, Application.ActiveWindow will return either Explorer or Inspector object, and you only want the latter. The current inspector is returned by Application.ActiveInspector.
And once you have an Inspector object, use Inspector.CurrentItem to retrieve the message being composed.
Thirdly, if you alreay have code that creates the message, why not simply call MailItem.Display to show it to the user? And if the message is shown in an inspector, why do you need to call MailItem.Send instead of letting the user click the Send button when they are ready? You really need to post your code that creates the message.
I have the following code to enable the file browser using blender:
import bpy
import os
from bpy.props import StringProperty
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator
sel = ''
class OpenBrowser(bpy.types.Operator):
bl_idname = "open.file"
bl_label = "Select Excel File"
bli_description = "Simulation output excel file"
filter_glob: StringProperty(default = '*.xls;*.xlsx',options = {'HIDDEN'})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
#somewhere to remember the address of the file
def execute(self, context):
global sel
sel = self.filepath
#self.selected_file = self.filepath
#display = "filepath= "+self.filepath
#print(display) #Prints to console
#Window>>>Toggle systen console
return {'FINISHED'}
def invoke(self, context, event): # See comments at end [1]
context.window_manager.fileselect_add(self)
global sel
sel = self.filepath
#Open browser, take reference to 'self'
#read the path to selected file,
#put path in declared string type data structure self.filepath
return {'RUNNING_MODAL'}
# Tells Blender to hang on for the slow user input
bpy.utils.register_class(OpenBrowser)
#Tell Blender this exists and should be used
# [1] In this invoke(self, context, event) is being triggered by the below command
#but in your script you create a button or menu item. When it is clicked
# Blender runs invoke() automatically.
#execute(self,context) prints self.filepath as proof it works.. I hope.
bpy.ops.open.file('INVOKE_DEFAULT')
print(sel)
The issue I am facing is that I have declared a global variable sel to which I want to save the filepath selected from the user when running the code. However, when I run the script I see that sel has not changed and it is as it was initialized. Could someone please help me on how to access from the class the self.filepath variable? What am I doing wrong here?
If I understand correctly, you want to store that value for later.
I'm not sure why 'sel' doesn't even update in your case, but I think the more correct way would be to use a property like so:
import bpy
# Assign a custom property to an existing type.
bpy.types.Scene.my_sel_value = bpy.props.StringProperty(name="Sel")
# Set property value.
bpy.context.scene.my_sel_value = "Foo"
# Get property value.
print(bpy.context.scene.my_sel_value)
Properties can be added to all ID types, but for "global" values, bpy.types.scene us ussualy used. Though there can be multiple scenes in one project and they will have separate values. Property values are stored when Blender closes.
If you are making an addon, you can also store your value in Addon Preferences. This value will be the same for all blender projects.
I have written a Python Telegram program but I need a bit of help on navigating the inline keyboard. When user clicks on one of the custom keyboard button [Feedback], an inline keyboard appears:
"Message: Do you find this app useful"
[No], [Yes], [Leave Comments].
When pressing [No], only a text message appears "Thank you and we hope you can leave some comments how to improve the app", goes back to main menu.
When pressing [Yes], a second inline button message appears with wording "Please vote for this app!" which hyperlinks to external website.
When pressing [Leave Comments], user needs to type in comments which is saved into a database.
My problem is upon pressing any of the 3 inline button, it leads to the same function "insert_UserFeedback".
Part of my codes as follows.
keyboard03 = [[InlineKeyboardButton("No", callback_data='no'),
InlineKeyboardButton("Yes", callback_data='yes')],
[InlineKeyboardButton("Leave Comments", callback_data='comments')]]
reply_markup03 = InlineKeyboardMarkup(keyboard03)
update.message.reply_text('Do you find the app useful?',
reply_markup=reply_markup03)
user = update.message.from_user
return FEEDBACK
At conv_handler states={
FEEDBACK: [MessageHandler(Filters.text,
insert_UserFeedback,
pass_user_data=True),
def insert_UserFeedback(bot, update, user_data):
user = update.message.from_user
#some codes..
sql10 = "UPDATE `subscribers` SET `feedback`='" + userFeedbackTxt + "',
`feedbackDate`='" + todaydatestamp + "' WHERE `id`=" + str(user.id) + ";"
cc.execute(sql10)
copp.commit()
copp.close()
update.message.reply_text(user.first_name + ', thank you for your feedback!')
return KEYBOARDVAL
So regardless if I choose which inline button I chose, "insert_UserFeedback" is called which then requires user to write a comment, because the program did not know in advance which inline button was selected.
The response object InlineQuery has a field query where the result of the user action is returned. Check the structure at Telegram API Inline Query
I need some hints to find a simple solution for inserting a popup window inside a python console app.
This app runs normally unattended, because it's done to be launched from crontab.
It uses everywhere logging to display messages and save them to logfiles.
However, in some cases, the app needs user intervention to choose some options when it is not able to find a suitable one.
That's why I inserted a --interactive option in argparse, and when the app needs user intervention, a popup window in console should appear, allowing the user to choose between some items in a list.
Here's an extract of the output to give you an example :
INFO : Try to fuzzy-match 'Orange Itbn'
INFO : Fuzzy-matched alternative entries : ['Orange Is The New Black']
INFO : Fuzzy matched 'Orange Itbn' as seriesname 'Orange Is The New Black'
INFO : MOVE /Users/spadazz/testing/orange itbn.s03e10.hdtv.720p.mkv TO:
/Volumes/NAS/TV Shows/Orange Is The New Black/S03/Orange Is The New Black.S03E10.hdtv.720p.mkv
INFO : Try to fuzzy-match 'Sur'
INFO : Fuzzy-matched alternative entries : ['Survivors 2008', 'Survivors']
WARNING :
Series 'Sur' not uniquely matched in titles
Choose between these titles :
['Survivors 2008', 'Survivors']
WARNING :
******************************************
**** INSERT HERE THE CALL TO THE POPUP ***
******************************************
Now, I've read some documentation about tkinter, curses and npyscreen but I wasn't able to come up with something simple for this purpose.
I don't wanna mess with the app structure or put the log messages in a main window..
I just wanna a popup that allows me to choose between some options, even with a simple keypress like '1' and '2' etc...
This should be a python solution too, possibly without calling external commands from os.
Any ideas ??
Thanks
With a little help from Nicholas Cole, who wrote npyscreen, I was able to fix this :
import npyscreen as np
class myPop(np.NPSApp):
def setopt(self, title, oList, multi):
self.title = title
self.options = oList
self.multi = multi
self.height = len(self.options)+1
def main(self):
F = np.Popup(name="Choose an option")
if self.multi:
opt = F.add(np.TitleMultiSelect, name=self.title, max_height=self.height, values=self.options, scroll_exit=True)
else:
opt = F.add(np.TitleSelectOne, name=self.title, max_height=self.height, values=self.options, scroll_exit=True)
F.edit()
self._values = opt.get_selected_objects()
self.result = ( self._values if self.multi and len(self._values) > 1 else self._values[0] )
def ChooseOption(title, oList, multi=False):
pop = myPop()
pop.setopt(title, oList, multi)
pop.run()
return pop.result
# Show a popup with radiobuttons to select 1 item from a list
print ChooseOption('choose a single element', ['a','b','c','d'])
# Show a popup with radiobuttons to multi-select items from a list
print ChooseOption('choose multi-elements', ['a','b','c','d'], True)
Hope this helps.
Enrico
Since npyscreen was written to make that kind of thing really simple, I'd use npyscreen. :)
The example code here is almost exactly what you are asking for.
I've to build a form in QGIS to customize data input for each polygon in the shapefile.
I use QtDesigner to create a form (.ui), with some textboxes and comboboxes pointing to the fields of my shapefile.
Then I use the python file from Nathan QGIS Blog to add some logic.
Python code:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
nameField = None
myDialog = None
def formOpen(dialog,layerid,featureid):
global myDialog
myDialog = dialog
global nameField
nameField = dialog.findChild(QTextEdit,"PART")
buttonBox = dialog.findChild(QDialogButtonBox,"buttonBox")
nameField.textChanged.connect(Name_onTextChanged)
# Disconnect the signal that QGIS has wired up for the dialog to the button box.
buttonBox.accepted.disconnect(myDialog.accept)
# Wire up our own signals.
buttonBox.accepted.connect(validate)
buttonBox.rejected.connect(myDialog.reject)
def validate():
# Make sure that the name field isn't empty.
if not nameField.text().length() > 0:
nameField.setStyleSheet("background-color: rgba(255, 107, 107, 150);")
msgBox = QMessageBox()
msgBox.setText("Field PART must not be NULL.")
msgBox.exec_()
else:
# Return the form as accpeted to QGIS.
myDialog.accept()
def Name_onTextChanged(text):
if not nameField.text().length() > 0:
nameField.setStyleSheet("background-color: rgba(255, 107, 107, 150);")
else:
nameField.setStyleSheet("")
So I open an edit session in QGIS and I click on a polygon with Identify tool, but when I clik on OK button on my customized form, regardless field PART is NULL or not, the following error occurs:
ERROR CODE LINE >>>> if not nameField.text().length() > 0:
ERROR MESSAGE >>>> AttributeError: 'str' object has no attribute 'text'
I'm running QGIS 1.7.4, Python 2.7.2, Windows 7 64-bit.
I miss something... Please, anybody can help me?
It looks like you have a Python error more than a problem with QGIS.
You have two instances of if not nameField.text().length() > 0:
def validate():
if not nameField.text().length() > 0:
and
def Name_onTextChanged(text):
if not nameField.text().length() > 0:
Initially, it looks like nameField is not an input for either of these functions. So I guess these are assigned somewhere else and you've reduced the code example. Also, you have text as a variable input for 'Name_onTextChanged' but you also try and use it as a function 'nameField.text().length()'. This might be a problem.
Generally, Python is complaining because it cannot perform the operation 'text()' on the variable nameField, which it believes is a string. There is no text() function available for strings. And it looks like nameField is actually supposed to be a QTextEdit object.
If nameField is a QTextEdit object, then you can use toPlainText() instead which should do what you need it to do. So something like
if not nameField.toPlainText().strip().length() > 0:
In this instance, I have included .strip() as well so that you do not get a positive result if there are white spaces in text field.
Does that help at all?