I developed a script for pcba testing and it works fine.
Now I want to implement a very simple flow like this:
Window popup just to let the user start the test
Run the test without any window (the terminal is just fine)
Window popup to show pass/fail result of the test
I already developed the two windows in two other .py files, which run without any problems when "standalone".
If I implement these two within the script, the first appears normally, but the second opens and closes istantly.
Without being too complicated, the test function is defined in serial.py, the first window in infoBox.py and the final window in getResult.py.
Inside the serial.py I tried:
import infoBox
import getResult
[...]
def work():
[...]
if __name__ == '__main__':
app1 = QApplication([])
win1 = infoBox.infoBox("""Turn on 24V alim and press OK.""")
win1.show()
app.exec()
[...]
work()
[...]
app2 = QApplication([])
generateWindow(esiti=lst_esiti, info=lst_info) # <------- this calls getResult.getResult class and .show() the widget
win2 = getResult.getResult(lst_esito=lst_esiti, lst_info=lst_info)
win2.show()
app.exec()
So, when serial.py is lounched by terminal, the infoBox instance appears, the work() function does what it has to, and the getResult instance (which has a OK button to be closed) is instantly closed.
Maybe the error is the definition of two QApplication? I tried a lot but I'm not able to manage it.
Thank you very much.
Finally I came up with this.
It was easier than expected...
Solved opening a unique QApplication and call app.exec() after each subclass calling.
Related
I have a code that works well for bulk data analysis and plotting. But now i'm trying to incorporate it into a larger data analysis GUI. I find that when i run my code on its own, all goes well. But when i call it from the main code and run it from a tkinter button, it's not the same. Everything looks the same and it runs smoothly, the only difference is that no files are saved.
i think maybe it's a problem with which window is defined with "____init____"? or something with how i create and destroy Tk() windows within the subcode?
**the stackoverflow text editor uses underscores to make text bold/itallic, so for all cases that double underscores are used to wrap "init" or "main" in python, i had to use four on each side here
my code (saved as SubCode.py):
def AnalysisFunction():
*does things*
main = Tk()
os.chdir(OutputFolder)
plt.savefig('image.png')
main.destroy()
if __name__ == '__main__':
AnalysisFuntion()
the code i want to add mine into:
import SubCode
class TopLevel(Frame):
def __init__(self, master):
Frame.__init__(self,master)
*Creates main GUI window*
MyButton = Button(root, command = self.CallSubCode)
def CallSubCode(self):
SubCode.AnalysisFunction()
root = Tk()
main_window = TopLevel(root)
root.mainloop()
Any ideas why the subcode alone can save figures but it cannot when called by the larger GUI? FYI, it still creates all variables correctly when running through the larger GUI.
I think you should just save the image in SubCode.py without creating a tkinter window. i.e
def AnalysisFunction():
*does things*
os.chdir(OutputFolder)
plt.savefig('image.png')
if __name__ == '__main__':
AnalysisFuntion()
i figured it out, I had to put the whole SubCode within a class structure, then call it as its own Toplevel app. I think otherwise the plt.savefig command doesn't know which Tkinter window it is working with, and tries to find data in the "host" window, not the one which is handling the data.
I have made a UI window for Autodesk Maya 2015. Every time I run the script within Maya's script editor, it works fine, the UI gets launched and it docks properly on the main Maya window.
However, after closing the UI window and rerunning the script, the window doesn't dock anymore. It gets stuck on the main screen and I have to close the whole software. It seems that the UI can't find the main Maya Window anymore after I close it the first time round. I'm not sure how to fix this. Can anyone give me some advice on how to fix this problem?
Here is my code:
def getMayaWindow():
ptr = apiUI.MQtUtil.mainWindow()
if ptr is not None:
return shiboken.wrapInstance(long(ptr), QtGui.QMainWindow)
class pipeWindow(formClass,baseClass):
def __init__(self, parent=getMayaWindow()):
super(pipeWindow,self).__init__(parent)
self.setupUi(self)
self.setObjectName('pipe_window')
try:
cmds.deleteUI('dockPane')
except:
pass
self.pane = cmds.paneLayout('dockPane', cn='single')
if 'pipeDock' not in cmds.lsUI(ctl=1) :
cmds.dockControl('pipeDock', con=self.pane, area='right',
allowedArea = ['right','left'], label =
"ANMD_Pipeline", w=365)
else:
pass
cmds.control( 'pipe_window', e=True, p=self.pane)
After trying out multiple things, I have managed to resolve this issue. I have used
if cmds.dockControl('pipeDock', q=1, ex=1):
cmds.deleteUI('pipeDock')
Then I have a super(className, self).closeEvent(event) inside a closeEvent function. This did the trick for me. This did the trick for me. Previously I had the cmds.deleteUI within my closeEvent function which did not work, I suspect it was because I did not close the Event itself, so the UI just hides itself whenever I press the cross button instead of deleting it.
I'm trying to create a python program that pulls up a simple window that displays the text "Hello World?" I've imported tkinter and have created a class called MyGUI that should create a simple window. Then I create an instance of the MyGUI class. When I hit "F5" or run the programming after saving it, I get an error:
RESTART: C:....my filepath.....
>>>
Here is the code:
import tkinter
class MyGUI:
def init (self):
# Create the main window widget.
self.main_window = tkinter.tk()
# Create a Label widget containing the
# text 'Hello World!'
self.label = tkinter.Label(self.main_window, text="Hello World!")
# Call the Label widget's pack method.
self.label.pack()
# Enter the tkinter main loop.
tkinter.mainloop()
# Create an instance of the MyGUI class
my_gui = MyGUI()
What causes the "RESTART" error? Does where I save my .py file matter for this program?
Any help would be greatly appreciated. Thanks
The good news:
Your code works (in that it doesn't crash in python3, as is)!
The bad news:
Your code doesn't do anything :( Your only function would raise an exception if called
You have a code-unrelated problem
To resolve problem #1, change init to __init__ and tkinter.tk to tkinter.Tk()
__init__ is the function called by default on instance construction. The underscores are important if you want to override it. The other issue is just a typo.
You're broader problem is... broader. yes it matters where you save your file. If you don't save it in the place you are running python from, you need to supply an absolute path to it, or a relative path from the place you are running from. This is a broad topic, but pretty important and not too challenging. Maybe try here, or any python tutorial.
I don't know what type F5 does on your computer. I would not in general expect it to run python code. Are you in an IDE, then maybe it does run python code? Are you playing call of duty, because then it's more likely to lob a virtual grenade? F5 is app-dependent, probably not a universal binding on your machine
I would develop some functional tests for a pyqt application that uses PyQt (or PySide) as GUI library. The tests use Unittest and Qttest library, as reported in many resources, for example this stackoverflow question: Unit and functional testing a PySide-based application?
For the main window all works fine, and the code simulate perfectly Keyboard Types and Mouse Clicks and Movements, but the "devil is in the details"... and this method does not work for a QMessageBox.
In the class of the Main Window, for manage a IOError on opening a file, I initialize a QMessageBox:
self.IOErrMsgBox = QtGui.QMessageBox()
self.IOErrMsgBox.setText("<b>Error</b>")
self.IOErrMsgBox.setInformativeText("""
<p>There was an error opening
the project file:
%s.</p>"""%(path,))
self.IOErrMsgBox.setStandardButtons(QtGui.QMessageBox.Ok)
self.IOErrMsgBox.setDefaultButton(QtGui.QMessageBox.Ok)
self.IOErrMsgBox.exec_()
To test how it works, in functional test I have:
def test__open_project(self):
self.MainWin._project_open(wrong_path, flag='c')
# the function that handles the exception
# and initializes the QMessageBox.
IOErrMsgBox = self.MainWin.IOErrMsgBox
# Reference to the initialized QMessageBox.
self.assertIsInstance(IOErrMsgBox, QMessageBox)
okWidget = self.MainWin.IOErrMsgBox.button(IOErrMsgBox.Ok)
QTest.mouseClick(okWidget, Qt.LeftButton)
or, in altenative:
def test__open_project(self):
#... some code, exactly like previous example except for last row...
QTest.keyClick(okWidget, 'o', Qt.AltModifier)
but No one works... and the Ok button is not clicked and I can do it with my mouse pointer :(
Any suggestions?
The question is in general about how to test modal dialogs.
Any modal dialog including QMessageBox will not return from exec_() until it is closed, so the test code in your second code box probably never gets executed.
You could just show() it (making it non-modal) and then follow your code but don't forget to close and delete the dialog afterwards.
Or you use a Timer and schedule a click on the OK button (similar to Test modal dialog with Qt Test). Here is an example:
from PySide import QtGui, QtCore
app = QtGui.QApplication([])
box = QtGui.QMessageBox()
box.setStandardButtons(QtGui.QMessageBox.Ok)
button = box.button(QtGui.QMessageBox.Ok)
QtCore.QTimer.singleShot(0, button.clicked)
box.exec_()
I have a deque type list (a queue) which I'd like to show and update in QTextEdit.
There is a function uuenda_kama in class MyForm which should do this (and some other s*** too). First pass of this function when textEdit is empty, it works like a charm, all necessary fields are updated. But on second pass as there has some text added to it, it crashes throwing me a Visual Studio debugger in face.
Tried commenting different parts out and came out that line "self.ui.textEdit.clear()" is causing this. What is wrong with it and why is it working on first pass? What can I do to fix it?
Code I have right now:
class MyForm(QtGui.QMainWindow):
...
def uuenda_kama(self):
while True:
...
if vana_que != list(que):
self.ui.textEdit.clear()
for i in que:
self.ui.textEdit.append(i)
vana_que = list(que)
sleep(1)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
uuendamine = Thread(target=myapp.uuenda_kama)
uuendamine.start()
myapp.show()
sys.exit(app.exec_())
You should not be creating a standard python thread outside of the entire app that runs methods on your qwidgets. Instead you should have a QThread that runs non-gui related logic and then emits a signal when it wants the main thread to affect the GUI
Refer to this other question for a good example: Howto change progress by worker thread
You should never call gui methods directly outside of the main thread.