Well I'm trying to use a outliner in maya with Pyqt4 and python, My outliner is in a Qsplitter with other two panels, it seems the code is ok, but when I run the code sometimes the Outliner appears, sometimes doesn't appear
this is the code where I create the Outliner:
self.outliner = QWidget()
self.outliner.setObjectName("outliner")
self.outLayout = QGridLayout()
self.outLayout.setContentsMargins(0, 0, 0, 0)
self.outLayout.setObjectName("outLayout")
self.outliner.setLayout(self.outLayout)
outL = cmds.outlinerPanel(mbv=False, p="outLayout")
cmds.control(out, edit=True, visible=True, parent="outLayout")
And this is how I display it:
self.splitter1 = QSplitter()
self.splitter1.addWidget(self.list)
self.splitter1.addWidget(self.outliner)
What I need to modify to make it work every time
EDIT:
I Upgraded my code, deleting inecesaring lines, but still doesn't work the way i need
Switching to answer format:
The current code would be better if you were not dependent on the hard coded names:
self.outliner.setLayout(self.outLayout)
#snip#
# in ordinary maya / python usage you'd do this....
panelLayout = cmds.formLayout("panelLayout", parent=self.outLayout)
# but in your original sample self.Outlayout is not a maya widget but a QT one
# so it doesn't resolve down to a string...
# the line below is the usual idiom
outliner = cmds.outlinerPanel("out", mbv=False, p=panelLayout)
that way the real names of the controls will be used and you're less vulnerable to strays with the same name. It's still good practice to delete strays - but it's hard to be sure without making the code very cumbersome.
Also, the line:
cmds.control(out, edit=True, visible=True, parent="panelLayout")
looks redundant - is it intentional? Is it a lefttover of an attempt to parent the outline? because the p= keyword ought to be doing your parenting for you.
Lurker update
As OP pointed out, code above wont' work - i've updated the sample to indicate the problem for the benefit of future readers.
well this is what i finished doing:
The first part is the same
self.outliner = QWidget()
self.outliner.setObjectName("outliner")
self.outLayout = QGridLayout()
self.outLayout.setContentsMargins(0, 0, 0, 0)
self.outLayout.setObjectName("outLayout")
self.outliner.setLayout(self.outLayout)
then I "translate" Pyqt to maya to be able to assign the layout with any extra code
panel = mui.MQtUtil.fullName(long(sip.unwrapinstance(self.outLayout)))
cmds.setParent(panel)
if cmds.modelPanel("outL", exists=True):
cmds.deleteUI("outL")
outL = cmds.outlinerPanel(mbv=False)
cmds.control(outL, edit=True, visible=True, p=panel)
ptr = mui.MQtUtil.findControl(outL)
Transform a Maya widget to a QWidget
self.outPanel = sip.wrapinstance(long(ptr), QObject)
And Finally add the Widget to my Layout
self.outLayout.addWidget(self.outPanel)
Related
I'm starting experimenting with Maya python, and I'm trying to do some UI.
I came across to a really strange problem, I can't get a button to stay in the center of the windows.
I've tried different things but nothing seems to work, here is the code:
import maya.cmds as cmds
cmds.window( width=200 )
WS = mc.workspaceControl("dockName", retain = False, floating = True,mw=80)
submit_widget = cmds.rowLayout(numberOfColumns=1, p=WS)
cmds.button( label='Submit Job',width=130,align='center', p=submit_widget)
cmds.showWindow()
this is a simple version but still, I can't get it to work.
can someone help me?
I honestly don't know the answer as anytime I have to dig into Maya's native UI stuff it makes me question my own life.
So I know it's not exactly what you're asking for, but I'll opt with this: Use PySide instead. At first glance it might make you go "woah, that's way too hard", but it's also a million times better (and actually easier). It's much more powerful, flexible, has great documentation, and also used outside of Maya (so actually useful to learn). Maya's own interface uses the same framework, so you can even edit it with PySide once you're more comfortable with it.
Here's a bare-bones example to create a centered button in a window:
# Import PySide libraries.
from PySide2 import QtCore
from PySide2 import QtWidgets
class MyWindow(QtWidgets.QWidget): # Create a class for our window, which inherits from `QWidget`
def __init__(self, parent=None): # The class's constructor.
super(MyWindow, self).__init__(parent) # Initialize its `QWidget` constructor method.
self.my_button = QtWidgets.QPushButton("My button!") # Create a button!
self.my_layout = QtWidgets.QVBoxLayout() # Create a vertical layout!
self.my_layout.setAlignment(QtCore.Qt.AlignCenter) # Center the horizontal alignment.
self.my_layout.addWidget(self.my_button) # Add the button to the layout.
self.setLayout(self.my_layout) # Make the window use this layout.
self.resize(300, 300) # Resize the window so it's not tiny.
my_window_instance = MyWindow() # Create an instance of our window class.
my_window_instance.show() # Show it!
Not too bad, right?
I'm making a GUI using Qt and pyqtgraph. It's got several PlotWidgets in it - here's a section of it:
I'd like to include the mouse cursor position (in scaled units) as a label within the plot, a bit like the pyqtgraph crosshair example:
The example works by adding a LabelItem to a GraphicsWindow like this:
win = pg.GraphicsWindow()
label = pg.LabelItem(justify='right')
p1 = win.addPlot(row=1, col=0)
But I don't have a GraphicsWindow, just a normal Qt window (built using the Designer) with PlotWidgets in it. I can't seem to add a LabelItem or a TextItem to a PlotWidget. I'm sure there must be a 'standard' way of doing this, but I can't figure it out and Google doesn't seem to know. Any ideas?
Edit: here's a snippet of my code from the window's __init__ function:
self.B_field_plot.setLabels(title='Magnetic field', left='B [T]', bottom='z [m]')
self.label = pg.LabelItem(justify="right")
self.B_field_plot.addItem(self.label)
self.label.setText('Hello')
The label does not appear.
Although it is a bit late now to answer this question, but I will put my answer in case someone else needed it.
You have to change the source file generated by the QTdesigner.
find the line that creates the plotwidget and embedded the title in it.
self.plot = PlotWidget(title= "something")
I'm currently looking for a smart way to start a game made in PyCharm by using the PyQt library and I wanted to try and hide several widgets, or complete Layouts but the function .hide() doesn't work on complete layouts.
Is there a code to hide layouts completely or is hiding all the widget in that box the way to go?
If the answer is the latter, how can I make it easier for me than to go through every single widget and add the .hide() extension to them. Can I collect all those widgets in some sort of parent and then just parent.hide() as well as parent.show() ?
The code looks like this atm:
playerbox = QGridLayout()
playerbox.addWidget(self.player1, 0, 0)
playerbox.addWidget(self.player2, 0, 1)
playerbox.addWidget(self.stake, 1, 0)
playerbox.addWidget(self.money, 1, 1)
playerbox.addWidget(betButton, 2, 0)
playerbox.addWidget(foldButton, 2, 1)
playerbox.addWidget(bettingtext,3,0)
And the playerbox is supposed to be a box in a game that displays several items. I just want this box not to show anything before the game has started (this is done when the user press start but this has already been dealt with).
Thanks in advance!
I like this one:
[playerbox.itemAt(i).widget().hide() for i in
range(playerbox.rowCount()*playerbox.columnCount()) if
playerbox.itemAt(i)]
the if clause is required since you could have empty spots in your grid, and then itemAt() returns None.
I want both view below are blue, how to set it? please help me! when i forcus to the second line i want it highlight both of object are blue, not one blue and one grey as below.
Code like this:
ui = twin_gtk_builder('twin.ui', ['dia_support', 'liststore7'])
win = ui.get_object('dia_support')
##### Begin function tree view
liststore = gtk.ListStore(int, int, int)
liststore.append([1,2,3])
liststore.append([2,2,2])
liststore.append([4,4,4])
win.sw = gtk.ScrolledWindow()
win.sm = gtk.TreeModelSort(liststore)
##### Set sort column
n = 1
win.sm.set_sort_column_id(n, gtk.SORT_ASCENDING)
win.tv = gtk.TreeView(win.sm)
win.vbox.pack_start(win.sw)
win.sw.add(win.tv)
win.tv.column = [None] * 3
win.tv.column[0] = gtk.TreeViewColumn('0-1000')
win.tv.column[1] = gtk.TreeViewColumn('0-1000000')
win.tv.column[2] = gtk.TreeViewColumn('-10000-10000')
win.tv.cell = [None] * 3
for i in range(3):
win.tv.cell[i] = gtk.CellRendererText()
win.tv.append_column(win.tv.column[i])
win.tv.column[i].set_sort_column_id(i)
win.tv.column[i].pack_start(win.tv.cell[i], True)
win.tv.column[i].set_attributes(win.tv.cell[i], text=i)
##### End function tree view
win.show_all()
and how it work
Tried one more time with #PM 2Ring help, Thanks so much for your help!
Somebody did it like this, but i can't find his contact...
I had to do a bit of work to get that code to run, Sunshine jp. In future, please try to post code that others can run & test, especially if it's GUI code. Otherwise it can be very hard to work out what the problem is and how to fix it.
I'm not familiar with twin_gtk1_builder(). Is it a GTK1 function?
Anyway, I've modified your code to run on GTK2+. I'm not quite sure what you want your code to do. So I've given row 2 a background color of cyan. Also, I've added the ability to make multiple selections, either using Ctrl or Shift on the keyboard when you select with the mouse; you can also do multiple selection with the keyboard with shift up and down arrows.
When the window loses focus the selected row(s) stays blue on my system. Maybe that's a feature of GTK2 that GTK1 doesn't have. (Or maybe it's due to my window manager - I'm using KDE 4.5.3 on Mepis Linux).
#!/usr/bin/env python
'''
TreeView test
From http://stackoverflow.com/questions/25840091/how-to-make-forcus-highlight-for-2-objects-at-the-same-time
'''
import pygtk
#pygtk.require('2.0')
import gtk
def TreeViewTest():
def delete_event(widget, event, data=None):
gtk.main_quit()
return False
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.set_title("TreeView Test")
win.set_size_request(320, 160)
win.connect("delete_event", delete_event)
win.vbox = gtk.VBox()
win.add(win.vbox)
win.sw = gtk.ScrolledWindow()
win.vbox.pack_start(win.sw)
##### Begin function tree view
#Set up liststore data. Column 3 controls whether
# background color of the TreeView is default or special.
liststore = gtk.ListStore(int, int, int, bool)
liststore.append([1, 2, 3, False])
#Tell row 2 to use the special color
liststore.append([2, 2, 2, True])
liststore.append([4, 4, 4, False])
win.sm = gtk.TreeModelSort(liststore)
##### Set initial sort column
n = 1
win.sm.set_sort_column_id(n, gtk.SORT_ASCENDING)
win.tv = gtk.TreeView(win.sm)
win.sw.add(win.tv)
win.tv.column = [None] * 3
win.tv.column[0] = gtk.TreeViewColumn('0-1000')
win.tv.column[1] = gtk.TreeViewColumn('0-1000000')
win.tv.column[2] = gtk.TreeViewColumn('-10000-10000')
#Set up cell renderers
win.tv.cell = [None] * 3
for i in range(3):
win.tv.cell[i] = gtk.CellRendererText()
win.tv.cell[i].set_property('cell-background', 'cyan')
win.tv.append_column(win.tv.column[i])
win.tv.column[i].set_sort_column_id(i)
win.tv.column[i].pack_start(win.tv.cell[i], True)
#win.tv.column[i].set_attributes(win.tv.cell[i], text=i)
win.tv.column[i].set_attributes(win.tv.cell[i], text=i,
cell_background_set=3)
#Allow multiple selection
treeselection = win.tv.get_selection()
treeselection.set_mode(gtk.SELECTION_MULTIPLE)
##### End function tree view
win.show_all()
def main():
TreeViewTest()
gtk.main()
if __name__ == "__main__":
main()
Note that this is NOT a good way to make a GUI. You should be creating a proper class, not adding everything as an attribute to win. Please see the PyGTK 2.0 Tutorial for plenty of code examples.
Edit
Ok. Sorry about my earlier confusion over what your problem is. At least we've now got a nice simple example of a PyGTK program that creates a TreeView. :)
Anyway, it turns out that I was right when I guessed that the blue color of the selection turning to grey when the window loses focus on your computer is due to the behaviour of the window manager. I suppose there may be a way to block that in the application, by playing with Widget attributes, but I'm not sure how to do that. And besides, it's considered rude for programs to ignore the settings in the users' window theme.
So the most appropriate solution to your problem is to make the appropriate change in your window manager's appearance settings.
In KDE the relevant property is called "Inactive selection changes color", as described in Color Scheme Options:
Inactive selection changes color — If checked, the current selection in elements which do not have input focus will be drawn using a different color. This can assist visual identification of the element with input focus in some applications, especially those which simultaneously display several lists.
To change this, open up system settings (ALT+F2 → "systemsettings", or the [K] menu → system settings), then go to "Application appearance" and select "Colors". In the "Options" tab, uncheck the "Inactive selection changes color" setting, and click apply.
... ... ...
If you're not using KDE you'll have to figure out for yourself how to change it; hopefully, other window manager settings interfaces and documentation refer to this property with the same name or a similar name.
Because of their high customizability I've been relying on using multiple GroupBoxes while building app GUIs. But it appears QGroupBoxes make a certain impact on how fast an interface builds.
Now with layout's .insertLayout() method I can build an entire graphics interface placing the widgets any where I want. The dialogs feel very lightweight and extremely fast to re-draw. Unfortunately I can't find a way to control their appearance. I would appreciate if you would give me some clue on how to control the layout visual properties. I am particularly interested in knowing:
How to draw layout border, how to control a border line width,
How to place a layout title (similar to what QGroupBox's .setTitle() does)
How to control the layout outside and inside margins.
How to make layout minimizable/size-restorable (So the user could click some minus/arrow icon to fold/unfold layout when they need or don't need certain widgets belonging to the same layout.
The example with three nested layouts is posted below. As it is seen on dialog screenshot there is no way to visually differentiate one layout from another since there are no border, no titles, no dividers and etc.
from PyQt4 import QtGui, QtCore
class Dialog_01(QtGui.QMainWindow):
def __init__(self):
super(QtGui.QMainWindow,self).__init__()
tabWidget = QtGui.QTabWidget()
tabGroupBox = QtGui.QGroupBox()
tabLayout = QtGui.QVBoxLayout()
tabLayout.setContentsMargins(0, 0, 0, 0)
tabLayout.setSpacing(0)
subLayoutA=QtGui.QVBoxLayout()
tabLayout.insertLayout(0, subLayoutA)
tabGroupBox.setLayout(tabLayout)
tabWidget.addTab(tabGroupBox,' Tab A ')
listWidgetA = QtGui.QListWidget()
for i in range(3):
QtGui.QListWidgetItem( 'Item '+str(i), listWidgetA )
subLayoutA.addWidget(listWidgetA)
subLayoutB=QtGui.QHBoxLayout()
tabLayout.insertLayout(1, subLayoutB)
subLayoutB.addWidget(QtGui.QLineEdit('LineEdit 1'))
subLayoutB.addWidget(QtGui.QLineEdit('LineEdit 2'))
subLayoutC=QtGui.QVBoxLayout()
tabLayout.insertLayout(2, subLayoutC)
subLayoutC.addWidget(QtGui.QPushButton('PushButton 1'))
subLayoutC.addWidget(QtGui.QPushButton('PushButton 2'))
self.setCentralWidget(tabWidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480,320)
sys.exit(app.exec_())
EDITED LATER
I inserted two lines into an example code to implement one of the suggestions made by sebastian. A Spacing-Margins method combos can be effectively used to get some additional tweaks done. Here is a screenshot (still could not get rid of the spacing around pushButtons):
QLayout sublcasses don't have a visual representation, which becomes clear by the fact that QLayout classes do not inherit QWidget. They only calculate the positions of the widgets they are responsible for in the context of their "parent" widget.
So the answer to questions 1,2 and 4 is basically: You can't.
You'll always have to have a QWidget in combination with a QLayout.
E.g. to group your two buttons into a frame with a box use a QFrame:
subLayoutC=QtGui.QVBoxLayout()
buttonFrame = QtGui.QFrame()
buttonFrame.setFrameStyle(QtGui.QFrame.Plain |QtGui.QFrame.Box)
buttonFrame.setLayout(subLayoutC)
subLayoutC.addWidget(QtGui.QPushButton('PushButton 1'))
subLayoutC.addWidget(QtGui.QPushButton('PushButton 2'))
# now we add the QFrame widget - not subLayoutC to the tabLayout
tabLayout.addWidget(buttonFrame) # I think your suggested edit was correct here
self.setCentralWidget(tabWidget)
Concerning question 3, check the docs:
http://qt-project.org/doc/qt-4.8/qlayout.html#setContentsMargins
http://qt-project.org/doc/qt-4.8/qboxlayout.html#setSpacing