Class-calling function not working - python

I am trying to modify this piece of code by calling out a import window then follow by this code.
As I am also going to use the current piece of code (which is not written by me), the way it works is that when user selects one of the 3 prefixes ['a','b','c'], it will change the naming of the items in Maya accordingly.
Part of the former Coding (prefix window):
import maya.cmds as cmds
import maya.mel as mel
import pymel.core as pm
from PyQt4 import QtGui, QtCore
import sys, os
class createUI(QtGui.QFrame):
def __init__(self, parent=None):
QtGui.QFrame.__init__(self, parent)
self.shot = SHOT
self.initUI()
self.connections()
class MainWindow(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.resize(400,100)
self.move(300,300)
self.setWindowTitle('Select the prefix of rexPass')
self.pubDock = createUI()
vLayout = QtGui.QVBoxLayout()
vLayout.addWidget(self.pubDock)
self.setLayout(vLayout)
self.createConnection()
def createConnection(self):
self.connect( self.pubDock.cancelButton, QtCore.SIGNAL( "clicked()" ), self.close )
self.connect( self.pubDock.OKButton, QtCore.SIGNAL( "clicked()" ), self.close )
def setupRenderGlobals():
cmds.setAttr ('StartRange.multiFrame', 1)
cmds.setAttr ('EndRange.endFrame', 200)
cmds.setAttr ('WidthRes.xres', 1920)
cmds.setAttr ('HeightRes.yres', 1080)
def main():
setupRenderGlobals()
global app
app=QtGui.qApp
global form
form = MainWindow()
form.show()
Currently I would like to add on a function where it calls a selection window to import something, and once the selection is done, it will then calls out the above code.
The problem I have is where when user hits the import button in the import window, it automatically closes, and the perfix window is not showing up, or I would have the 2 windows showing up or just the prefix window and not the import window
My Coding:
class Processing():
'In-house code to call out the import window and they will have the name of 'prItems_a01''
importItems = procureItems.api.importItem()
allItems = pm.ls(type="prItems")
if allItem < 2 :
test = MainWindow()
else:
print ('testing')
Any advices?

The problem is here:
if allItem < 2 :
test = MainWindow()
else:
print ('testing')
allItems = pm.ls(type="prItems")
if allItem < 2 :
test = MainWindow()
pymel.core.ls returns a list, while 2 is an int. Python may not do what you expect here. From the docs:
Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.
So, "list" > "int"
What you probably meant to do is check the len of allItem, like this:
def processing():
# ~~ your code ~~ #
if len(allItem) < 2:
test = MainWindow()
else:
print ('testing')

Related

Why is this basic PyQt5 program not working?

This is a pyqt5 program that is suppossed to set the content of one lineedit to the content of the other lineedit. It is not working in that it you can't edit the line edits. Can someone tell me why and how I can fix it?
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
firstenter = QLineEdit(self)
firstenter.move(140,276)
firstenter.setFixedWidth(240)
secondenter = QLineEdit(self)
secondenter.move(420,276)
secondenter.setFixedWidth(240)
equalsighn = QLabel(self)
equalsighn.setText("=")
equalsighn.move(395,270)
def conversion():
try:
a = firstenter.displayText()
b = secondenter.displayText()
if firstenter.isModified() == True:
firstenter.setText(str(b))
elif secondenter.isModified() == True:
secondenter.setText(str(a))
except:
if firstenter.isModified() == True:
secondenter.setText("")
if secondenter.isModified() == True:
firstenter.setText("")
firstenter.textEdited.connect(conversion)
secondenter.textEdited.connect(conversion)
self.setGeometry(500, 300, 800, 500)
self.setWindowTitle('Test')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('Fusion')
ex = Example()
sys.exit(app.exec_())
It's not working because the logic in the first if statement is wrong:
if firstenter.isModified() == True:
firstenter.setText(str(b))
You're resetting the contents of the first line edit to the second, but since the secondenter text is empty to begin with, it sets the firstenter text accordingly, thus resetting its contents no matter what you type. Because of that, the second if won't work for the same reason.
The solution is much simpler, and uses [sender()] to know which object emitted the signal:
def conversion():
if self.sender() == firstenter:
secondenter.setText(firstenter.text())
else:
firstenter.setText(secondenter.text())
Note that you should use text() and not displayText(), since the latter might return a different result if the echoMode() is not set to Normal (the default).
Also, the try/exception is useless, and you shouldn't check against isModified, since textEdited is always and only emitted when the user changes the text, and not when the text is changed programmatically using setText().
A suggestion: avoid fixed sizes and positions, using them will probably result in an unusable interface on systems different from yours (because of various reasons, including screen size, DPI and default fonts). You should prefer layout managers instead.

Complex context-menu submenu

I have a Qt5 application mainly driven by context menu.
Right now I have the standard structure with menu(s), submenu(s) and actions.
I would like to add, in place of a submenu, a small dialog with a few input widgets, something like this:
Is there any (possibly simple) way to get this?
I know I can open a normal dialog from popup, but that is not what I mean.
I would like to have normal submenu behavior, with chance to go back to parent menu... if possible.
Note: I'm actually using PyQt5, but I think this is a more general Qt question.
Following #G.M. advice I was able to partially solve my problem.
My code current code looks like:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class ActionFont(QWidgetAction):
def __init__(self, parent: QWidget, target: QPlainTextEdit):
super(ActionFont, self).__init__(parent)
self.setIcon(QIcon("font-face.svg"))
self.setText("Face")
w = QFontComboBox()
w.currentFontChanged.connect(self.doit)
self.setDefaultWidget(w)
self.cursor = target.textCursor()
self.char_format = self.cursor.charFormat()
font = self.char_format.font()
w.setCurrentFont(font)
# self.triggered.connect(self.doit)
def doit(self, font):
self.char_format.setFont(font)
self.cursor.setCharFormat(self.char_format)
class ActionSize(QWidgetAction):
def __init__(self, parent: QWidget, target: QPlainTextEdit):
super(ActionSize, self).__init__(parent)
self.setIcon(QIcon("font-size.svg"))
self.setText("Size")
self.has_changed = False
w = QSpinBox()
self.setDefaultWidget(w)
self.cursor = target.textCursor()
self.char_format = self.cursor.charFormat()
font = self.char_format.font()
size = font.pointSize()
w.setRange(6, 100)
w.setValue(size)
w.valueChanged.connect(self.doit)
w.editingFinished.connect(self.quit)
def doit(self, size):
print(f'ActionSize.doit({size})')
self.char_format.setFontPointSize(size)
self.cursor.setCharFormat(self.char_format)
self.has_changed = True
def quit(self):
print(f'ActionSize.quit()')
if self.has_changed:
print(f'ActionSize.quit(quitting)')
class Window(QMainWindow):
def __init__(self, parent=None):
from lorem import text
super().__init__(parent)
self.text = QPlainTextEdit(self)
self.setCentralWidget(self.text)
self.text.setContextMenuPolicy(Qt.CustomContextMenu)
self.text.customContextMenuRequested.connect(self.context)
self.text.appendPlainText(text())
self.setGeometry(100, 100, 1030, 800)
self.setWindowTitle("Writer")
def context(self, pos):
m = QMenu(self)
w = QComboBox()
w.addItems(list('ABCDE'))
wa = QWidgetAction(self)
wa.setDefaultWidget(w)
m.addAction('Some action')
m.addAction(wa)
m.addAction('Some other action')
sub = QMenu(m)
sub.setTitle('Font')
sub.addAction(ActionFont(self, self.text))
sub.addAction(ActionSize(self, self.text))
m.addMenu(sub)
pos = self.mapToGlobal(pos)
m.move(pos)
m.show()
app = QApplication([])
w = Window()
w.show()
app.exec()
This works with a few limitations:
I have been able to add just a single widget using setDefaultWidget(), if I try to
add a fill QWidget or a container (e.g.: QFrame) nothing appears in menu.
I have therefore not been able to prepend an icon (or a QLabel) to the widget.
Widget does not behave like a menu item (it does not close when activated); I tried to overcome that as implemented in ActionSize, but looks rather kludgy and I'm unsure if it's the right way to go.
I will therefore not accept my own answer in hope someone can refine it enough to be generally useful.

Pyqt Pass Variable to QDialog Class

I have developed a QGIS plugin using Pyqt. I now have a need within this plugin to have a QDialog popup have its fields populated with data from our database.
My problem is how to pass a variable (in this case it might be a table and row reference) into a class and have it used by the static method.
If I print a passed in variable from within the class it will return the variable in addition to None?? If I take the same variable and try and populate a qplaintextedit it won't work because its complaining of being type 'None'.
Here is some test code I'm trying out just to get the concept down...
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import pdb
class mydi(QDialog):
def __init__(self, pass_var, parent=None):
super(mydi, self).__init__(parent)
layout = QVBoxLayout(self)
self.pass_var = pass_var
print pass_var
self.txt_comments = QPlainTextEdit(self)
self.txt_comments.appendPlainText(pass_var)
layout.addWidget(self.txt_comments)
self.buttons = QDialogButtonBox(
QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
Qt.Horizontal, self)
layout.addWidget(self.buttons)
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
def something(self):
return self.somevar
def comments(self):
return self.txt_comments.toPlainText()
#staticmethod
def getData(parent=None):
dialog = mydi(None)
dialog.exec_()
return (dialog.comments())
def main():
app = QApplication([])
pass_in_var = "test"
dia = mydi(pass_in_var)
data = dia.getData()
print data

How to get a value of QTimeEdit,QCheckBox and QDateTimeEdit into a variable. (Python)

I'm starting with PyQt4 and I'm making a program for practice. In that program I have QDateTimeEdit, QTimeEdit and QCheckBox.
How would I pull values from them into a string using signals and slots.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class main_frame(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.initUI()
def initUI(self):
# A push buttnon
btn_get = QPushButton("Get Time", self)
btn_get.move(100, 250)
#
time = QTime()
# Find what is the local/system time
curent_t = time.currentTime()
# Convert it to a str
# The output shoud be HH:MM:SS , eg 10:45:28
curent_t_str = curent_t.toString()
# Create a timeEdit widget
time_widget = QTimeEdit(time, self)
time_widget.setTime(curent_t)
def get_time():
print(curent_t_str)
btn_get.clicked.connect(get_time)
### At the end of the day you got curent_t_str variable
### which you can use it in your code down the road
### so I belive that`s helpful for your needs
### implement this may vary, depending your needs ...
# Set a costom size for the mainWindow
self.setFixedSize(300, 300)
def main():
app = QApplication(sys.argv)
myapp = main_frame()
myapp.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Does that help you out ? Note that for QDateTimeEdit the procedure is the same, after you got your value into format like 10:45:28 is up to you how you gonna format the string or for what you gonna use

Why is this implementation of a QGraphicsScene causing the app to crash on exit?

I'm using Qt's Graphics View Framework to display a large number of images, and implementing it using PyQt4 and Python 2.7. I instantiate a number of QPixmapItem objects and add them to my QGraphicsScene. It all works as I'd expect it to until I exit the application, and the program crashes instead of exiting normally.
class ImgDisplay(QtGui.QWidget):
NUM_ITEMS = 5000
VIEW_WIDTH,VIEW_HEIGHT = 400, 400
def __init__(self):
super(ImgDisplay, self).__init__()
self.scene = QtGui.QGraphicsScene(QtCore.QRectF(0,0,ImgDisplay.VIEW_WIDTH,ImgDisplay.VIEW_HEIGHT))
self.view = QtGui.QGraphicsView(self.scene)
self.view.setParent(self)
#Load the texture
self.texture = QtGui.QPixmap('image.png')
self.populateScene()
def populateScene(self):
for i in range(0, ImgDisplay.NUM_ITEMS-1):
item = QtGui.QGraphicsPixmapItem(self.texture)
self.scene.addItem(item)
I'm thinking that all those PixMapItems I'm creating aren't being cleaned up properly, or maybe I need to free the texture that I load (there doesn't seem to be a method to free it, so I assumed it happened in the background).
I've tried calling self.scene.clear in a destructor to delete the PixmapItems, but it didn't help.
Any suggestions on how I can fix this problem?
*I'm aware that the posted code just puts the images all on top of each other, my actual program assigns them random positions and rotations, but I wanted to reduce this to the minimal problem.
OK, understood. Problem is QtGui.QGraphicsPixmapItem can't clear itself your have to manual just like you says, but not destructor. I recommend doing after have signal close program by using closeEvent, like this;
def closeEvent (self, eventQCloseEvent):
self.scene.clear() # Clear QGraphicsPixmapItem
eventQCloseEvent.accept() # Accept to close program
and this implemented you code;
import sys
from PyQt4 import QtCore, QtGui
class ImgDisplay (QtGui.QWidget):
NUM_ITEMS = 5000
VIEW_WIDTH,VIEW_HEIGHT = 400, 400
def __init__ (self):
super(ImgDisplay, self).__init__()
self.scene = QtGui.QGraphicsScene(QtCore.QRectF(0,0,ImgDisplay.VIEW_WIDTH,ImgDisplay.VIEW_HEIGHT))
self.view = QtGui.QGraphicsView(self.scene)
self.view.setParent(self)
#Load the texture
self.texture = QtGui.QPixmap('image.png')
self.populateScene()
def populateScene (self):
for i in range(0, ImgDisplay.NUM_ITEMS-1):
item = QtGui.QGraphicsPixmapItem(self.texture)
self.scene.addItem(item)
def closeEvent (self, eventQCloseEvent):
self.scene.clear()
eventQCloseEvent.accept()
app = QtGui.QApplication([])
window = ImgDisplay()
window.show()
sys.exit(app.exec_())
I use PyQt4 (Windows 7).
And this useful to implement close event, Hope is helps;
QWidget Close Event Reference : http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#closeEvent
LAST EDITED : 8 / 11 / 2014 01:51
If your want to control your parent & child widget to delete together, I have to implement destructor method (As your say). By use safe delete method QObject.deleteLater (self), Like this;
import sys
from PyQt4 import QtCore, QtGui
class ImgDisplay (QtGui.QWidget):
NUM_ITEMS = 5000
VIEW_WIDTH, VIEW_HEIGHT = 400, 400
def __init__ (self, parent = None):
super(ImgDisplay, self).__init__(parent)
self.scene = QtGui.QGraphicsScene(QtCore.QRectF(0,0,ImgDisplay.VIEW_WIDTH,ImgDisplay.VIEW_HEIGHT), parent = self)
self.view = QtGui.QGraphicsView(self.scene, parent = self)
#Load the texture
self.texture = QtGui.QPixmap('image.png')
self.populateScene()
def populateScene (self):
for i in range(0, ImgDisplay.NUM_ITEMS-1):
item = QtGui.QGraphicsPixmapItem(self.texture)
self.scene.addItem(item)
def __del__ (self):
self.deleteLater() # Schedules this object for deletion
app = QtGui.QApplication([])
window = ImgDisplay()
window.show()
sys.exit(app.exec_())
Warning : Don't forget set parent in your widget ! (Because some time It can't be delete itself.)
deleteLater Reference : http://pyqt.sourceforge.net/Docs/PyQt4/qobject.html#deleteLater
Regards,
I would like to highlight Josh's answer in the comments.
If you create the scene by setting the QGraphicsView as parent the crash will automatically go away.
self.view = QtGui.QGraphicsView(parent = self)
self.scene = QtGui.QGraphicsScene(QtCore.QRectF(0,0,ImgDisplay.VIEW_WIDTH,ImgDisplay.VIEW_HEIGHT), parent = self.view)
self.view.setScene(self.scene)

Categories