right click a shelf button in Maya to launch a different script - python

I was wondering if it is possible to launch a different script in Maya when right clicking on a custom shelf button verses a left click. So a traditional left click of the button would launch one version of the script, but a right click ( or some other action ) would execute a different version of the script.

Yes it is possible. What you can do is add a shelf button with cmds.shelfButton, then attach a pop-up menu with cmds.popupMenu where you can put as many commands as you want. cmds.popupMenu has a parameter button where you can specify what mouse button triggers the pop-up to show up.
import maya.cmds as cmds
# Put in what shelf tab to add the new button to.
shelf = "Rigging"
# Throw an error if it can't find the shelf tab.
if not cmds.shelfLayout(shelf_name, q=True, exists=True):
raise RuntimeError("Not able to find a shelf named '{}'".format(shelf_name))
# Create a new shelf button and add it to the shelf tab.
# Include `noDefaultPopup` to support a custom menu for right-click.
new_shelf_button = cmds.shelfButton(label="My shelf button", parent=shelf, noDefaultPopup=True)
# Create a new pop-up menu and attach it to the new shelf button.
# Use `button` to specify which mouse button triggers the pop-up, in this case right-click.
popup_menu = cmds.popupMenu(parent=new_shelf_button, button=3)
# Create commands and attach it to the pop-up menu.
menu_command_1 = cmds.menuItem(label="Select meshes", sourceType="python", parent=popup_menu, command='cmds.select(cmds.ls(type="mesh"))')
menu_command_2 = cmds.menuItem(label="Select joints", sourceType="python", parent=popup_menu, command='cmds.select(cmds.ls(type="joint"))')
menu_command_3 = cmds.menuItem(label="Select all", sourceType="python", parent=popup_menu, command='cmds.select("*")')

Related

Create event clicking on context menu with python pyqt5

Am working with PyQt5, and I have a window app, I already have some functions and classes, and I implemented that when the user click Mouse Right-click it shows a context menu.
What I need is: I want to make a unit test for the code, so I want to test the right click which will open the context menu and after that I must test if the user click on it, it should do something like removing the points.
But my problem is I can't make an event that will click on that context menu and take action, because what I think is it is not in the widget so I can't make an event click on the point that the context menu are in, I tried it but it doesn't work.
So any ideas, how to make an event click on or pass or anything just made the action taken and run the code after context menu opened?
NOTE: I'm using QEvent for testing, Since am working with QWidget and QApllication PyQt5 python 3.7.
Here is the test event that opened the context menu:
point = QPointF(30, 30) #For example this will open the context menu at that point
e = QMouseEvent(QMouseEvent.MouseButtonPress, point, Qt.RightButton, Qt.NoButton, Qt.NoModifier) #Right Click
self.canvas.contextMenuEvent(e)
This is from canvas class:
def contextMenuEvent(self, ev):
"""
overrides the original contextMenuEvent function
:param ev: <QEvent>
:return: None
"""
self.current_tool.context_menu(ev)
And this is from the current tool function:
def context_menu(self, e):
menu = QMenu(self.canvas)
delete_whole_polygon_act = menu.addAction("Delete Area?")
action = menu.exec_(self.canvas.mapToGlobal(e.pos()))
if action == delete_whole_polygon_act:
self.delete_polygon(e.pos())

How to speed up browsing application via pywinauto?

From application that I want to automate I get pane with set of buttons. Clicking on the button adds new buttons set to Pane, and deletes other buttons from source set. Text in buttons are unique in one set, but aren't unique between them. Text on button is the only property I can use to handle it and click, so after clicking, the button is appended to list that contain already clicked buttons. Difference between children of pane and that array are buttons with unique text.
So my function is like:
def click_button(textOnButton, clickedButtons):
children = paneWindow.children() # get buttons currently present
handles = []
for item in children:
handles.append((item.handle, item.texts()[0]))
unique_buttons = list(set(handles) - set(clickedButtons)) # remove clicked buttons
button = [t for t in handles if t[1].startswith(textOnButton)]
paneWindow.childWindow(handle=button[0][0]).click_input()
clickedButtons.append((button[0][0], button.[0][1]))
clickedButtons = []
click_button("FOO", clickedButtons)
click_button("IPSUM", clickedButtons)
It works correctly, but just one function execution takes.. 2 to 3 seconds what is certainly unacceptable. Most timeconsuming is getting pane children and clicking on button. Anyone has an idea how to speed it up?
It's considerable for me to change tool from pywinauto to something else. Python isn't required.

GUI automation using pywinauto python. Attribute error , menu_select() missing error in uaicontrols.py

I'm tring to automate a windows gui mouse click of a check box in properties of a printer.
I get to this by starting print management mmc, right clicking on "G23XnQ2E (local)" from "Print Servers" drop down in the left pane and selecting properties, switching to "security tab" and i finally want to select the checkbox against manage printer option. This can also be achieved by directly clicking on the action menu and selecting properties, provided that i have selected "G23XnQ2E (local)" from the printer servers.
I have tried all the possible ways that I can thing of but always end up getting the many errors like "raise AttributeError", "menu_select", "select()", "click()" - "missing".
my code is like say:
from pywinauto import Application
Application().start(r'mmc printmanagement.msc')
app = Application(backend="uia").connect(path='mmc.exe')
app.PrintManagement.dump_tree()
app.dialog.pane1.pane5.pane6.menu.menu_select("Action -> Properties")
#app.dialog.menu_select("Action -> Properties")
#app.dialog.pane1.pane5.pane6.menu.ActionMentuitem.select()
#app.dialog.pane1.pane5.pane6.menu.ActionMentuitem.click()
How to fix the problem?
menu_select is good for main menu like "File->Open". It doesn't work for popup/context menus. This is my code working on my PC (name of print server has been changed to yours):
from pywinauto import Application
Application().start(r'mmc printmanagement.msc')
app = Application(backend="uia").connect(path='mmc.exe')
#app.PrintManagement.dump_tree()
print_servers = app.PrintManagement.child_window(title="Print Servers", control_type="TreeItem")
print_servers.select() # it expands the subtree
# call popup menu
print_servers.child_window(title="G23XZNQ2E (local)", control_type="TreeItem").right_click_input()
# alternative way to call popup menu
#print_servers.child_window(title_re=".*\(local\)$", control_type="TreeItem").right_click_input()
# select "Properties..." menu item
app.ContextMenu.child_window(title="Properties...", control_type="MenuItem").select()
#app.PrintManagement.Print_Server_Properties.dump_tree()
app.PrintManagement.Print_Server_Properties.TabControl.select('Security')
app.PrintManagement.Print_Server_Properties.child_window(title="Allow Manage Printers", control_type="CheckBox").toggle()
All child_window specifications have been copied from dump_tree() outputs. Some windows are children of main window, but context menu is a top level one. This is not a documented experience, but we're working on a recorder feature planned this year as Beta. So it will be much easier to generate a script without thinking about hierarchy structure so much.

Tkinter Initial Cursor position and Enter to press button

I am making a box that is similar to the tkMessageBox. There are two simple behaviors that I want to the box to have. First I want the button to be selected automatically when the window opens, and second I want to be able to press enter to push the button. Sounds simple and I realize that I could use the tkinterMessageBox to do this same thing, but this is a stepping stone, and I would like to know how to do this in the future for other things.
The current behavior of the window below is that it opens, and if I press tab it will select the button, but then i can only press the button with the mouse. Again the desired functionality is to have the button selected right away and be able to press the button with the enter key.
import Tkinter, tkMessageBox
from Tkinter import *
def closewindow():
Messagebox.destroy()
Messagebox=Tk()
l3=Label( Messagebox, text="This is your preview! Align camera then press ESC")
b3=Button(Messagebox, text="Okay", command=closewindow)
l3.grid(row=1,column=1)
b3.grid(row=2,column=1)
Messagebox.mainloop()
You can actually do this with just two lines of code:
b3.bind('<Return>', lambda _: closewindow())
b3.focus_set()
The first binds the button to the Enter key and the second sets the application's focus on the button.
Note that I had to use a lambda with the binding to handle the event object that will be sent to the callback. You could however change the definition of closewindow to handle this:
def closewindow(event=None):
Messagebox.destroy()
Now you can just do:
b3.bind('<Return>', closewindow)
For more information on bindings in Tkinter, see Events and Bindings over on Effbot.

How to prevent a double execution of a single-click event when actually trying to trigger a double click event?

I am creating a gtk (pygtk) based GUI file browser on python using IconView. It has two signals - selection-changed which is triggered when an image is selected by single click and item-activated which is triggered when a double-click is performed . I need both the signals in my program , selection-changed to select folders to cut/copy and item-activated to navigate child folders and files.
However, double-clicking generates two selection-changed signals and one item-activated signal. I only need the item-activated signal to be generated.
Hence the question.
The second single-click and the double-click event should arrive simultaniously.
You can use glib.timeout_add(interval, callback, ...) to execute all the single-clicks after a milli second (or increase it).
If within some time a double-click occurred then you do not execute the single-click event.
Implementation hints: use a variable so save when the last double-click occurred and a variable for the last click using time.time().
If the double-click and single-click are very close, do not execute the singe-click code.
Due to the use of the timeout, the single-click always executes after the double-click.
Why not keep track which item is selected? Ignore selection-changed on second click since selection won't have changed. Here is an example from pytk FAQs modified to handle this case...
import gtk
import gtk.gdk
current_path = []
current_path.append(None)
def on_selection_changed(iconview, current_path):
if iconview.get_selected_items():
if cmp(current_path[0], iconview.get_selected_items()[0]):
print "selection-changed"
current_path[0] = iconview.get_selected_items()[0]
def on_item_activated(iconview, path):
print "item-activated"
# First create an iconview
view = gtk.IconView()
view.connect("selection-changed", on_selection_changed, current_path)
view.connect("item-activated", on_item_activated)
# Create a store for our iconview and fill it with stock icons
store = gtk.ListStore(str, gtk.gdk.Pixbuf)
for attr in dir(gtk):
if attr.startswith('STOCK_'):
stock_id = getattr(gtk, attr)
pixbuf = view.render_icon(stock_id,
size=gtk.ICON_SIZE_BUTTON, detail=None)
if pixbuf:
store.append(['gtk.%s' % attr, pixbuf])
# Connect our iconview with our store
view.set_model(store)
# Map store text and pixbuf columns to iconview
view.set_text_column(0)
view.set_pixbuf_column(1)
# Pack our iconview into a scrolled window
swin = gtk.ScrolledWindow()
swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
swin.add_with_viewport(view)
swin.show_all()
# pack the scrolled window into a simple dialog and run it
dialog = gtk.Dialog('IconView Demo')
close = dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_NONE)
dialog.set_default_size(400,400)
dialog.vbox.pack_start(swin)
dialog.run()

Categories

Resources