I'm working on numercial simulations in Abaqus 2020 and coded a GUI with Tkinter.
My problem is, that while running the Tkinter code everything works well unitl the start of the mainloop. Then both windows of Tkinter and Abaqus freeze. When I first close the Abaqus window, the Tkinter Window works correctly. I tried sth with threads but wihtout success..
Setup: Windows 10, Abaqus 2020, Python 2.7
here you find a minimal example:
import Tkinter as tk
from Tkinter import *
# Creating master Tkinter window
window = tk.Tk()
window.title('TKINTER-mini')
# window.attributes("-fullscreen", True)
width=1200
window.geometry("1800x1000")
# Frames
frame0 = Frame(window, width=width)
label_Titel = tk.Label(master=frame0, text ='Test', font=('Aerial 15 bold'))
label_Titel.grid(row=0, column = 0)
frame0.grid(row=0, column=2, padx=20, pady=20, ipadx = 20, ipady=20)
window.mainloop()
# window.update()
I'm looking forward to get some help. Thank you in advance!
Greets JBKingPile
I tried
#1
def __init__(self):
import threading
threading.Thread.__init__(self)
def shutdown_ttk_repeat(self):
self.mainroot.eval('::ttk::CancelRepeat')
self.mainroot.destroy()
def __init__(self, parent):
self.mainroot = parent
# self.mainroot.protocol("WM_DELETE_WINDOW", self.shutdown_ttk_repeat)
# self.tabpage()
self.root.after(1000, self.refresh())
self.root.mainloop()
#2
try:
# Tk will crash if pythonw.exe has an XP .manifest
# file and the root has is not destroyed explicitly.
# If the problem is ever fixed in Tk, the explicit
# destroy can go.
try:
gui = gui(window)
window.mainloop()
finally:
window.destroy()
except KeyboardInterrupt:
pass
#3
if __name__ == "__main__":
app = simpleapp_tk(window)
window.mainloop()
Related
How can I do in tkinter something similar to a messagebox, but that doesn't have any buttons, including the close, minimize and maximize buttons on top?
I want it to be in a different window (like a message box), and to be able to update the text and close it only within the code.
Is there a way to do something like that?
Make your own. For example:
try: #python3 imports
import tkinter as tk
except ImportError: #python3 failed, try python2 imports
import Tkinter as tk
class Popup(tk.Toplevel):
"""modal window requires a master"""
def __init__(self, master, **kwargs):
tk.Toplevel.__init__(self, master, **kwargs)
self.overrideredirect(True)
self.geometry('300x200+500+500') # set the position and size of the popup
lbl = tk.Label(self, text="Please wait for other players to join ... ")
lbl.place(relx=.5, rely=.5, anchor='c')
# The following commands keep the popup on top.
# Remove these if you want a program with 2 responding windows.
# These commands must be at the end of __init__
self.transient(master) # set to be on top of the main window
self.grab_set() # hijack all commands from the master (clicks on the main window are ignored)
### demo usage:
def open_popup():
root.popup = Popup(root)
# close the popup in 2 seconds
root.after(2000, close_popup)
def close_popup():
root.popup.destroy()
root = tk.Tk()
btn = tk.Button(root, text='Open Modal Window', command=open_popup)
btn.pack()
root.mainloop()
PyQt :Parent Window not waiting until child window closes. with reference to code shared below ,My welcome class object should wait till first_time class object completely finishes executing , but instead goes ahead and closes it self before first_time object finishes executing .
code :
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PySide.QtCore import QSettings
import sys
from PyQt4 import uic
#importing first configuration class
import configure as config_first
#loading initial settings
settings=QSettings('settings.ini',QSettings.IniFormat)
#loading the ui screens
form_class=uic.loadUiType("screens/firstscreen.ui")[0]
class welcome(QDialog,form_class):
#this signal is emitted when first configuration is done and ready to go
done_and_go_to_use = pyqtSignal()
def __init__(self):
super(welcome, self).__init__()
self.setupUi(self)
self.done_and_go_to_use.connect(self.close)
self.ready_btn.clicked.connect(self.ready)
def ready(self):
if_configured = settings.value('isConfigured', False)
if not if_configured :
first_time=config_first.configureFirst(self)
first_time.show()
self.close()
app = QApplication(sys.argv)
p = welcome()
p.show()
app.exec_()
below is the code for configure.py
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sqlite3
import csv
from PySide.QtCore import QSettings
from PyQt4 import uic
#loading initial settings
settings=QSettings('settings.ini',QSettings.IniFormat)
#loading ui screens
form_class=uic.loadUiType("screens/config_first.ui")[0]
#database connecting
con = sqlite3.connect("local.db")
cur = con.cursor()
cur.execute("CREATE TABLE if not exists marks (student_id int,student_name varchar(200));")
class configureFirst(QDialog,form_class):
done_configuring=pyqtSignal()
try_again=pyqtSignal()
def __init__(self,parent=None):
super(configureFirst, self).__init__(parent)
self.setupUi(self)
self.ok_btn.clicked.connect(self.ok_clicked)
self.cancel_btn.clicked.connect(self.cancel_clicked)
self.try_again.connect(self.ok_clicked)
self.done_configuring.connect(self.cancel_clicked)
self.show()
def ok_clicked(self):
file_select=QFileDialog.getOpenFileName(self,"open file","/")
if file_select:
with open(file_select, 'rb') as f:
reader = csv.reader(f)
ed = list(reader)
for row in ed:
if "name" not in row or "id" not in row:
cur.execute("Insert into marks Values (?,?);",(row[0],row[1]))
con.commit()
settings.setValue("isConfigured",True)
self.done_configuring.emit()
else:
#if recurssion is used the no of time it has to close increases and leads to integration problems
self.try_again.emit()
def cancel_clicked(self):
if_configured=settings.value("isConfigured")
if if_configured:
self.close()
else:
QMessageBox.critical(self,"PerfAnalyser","You Need to Configure For PerfAnalyser To Work")
def closeEvent(self,event):
#this method is triggered when 'X' is clicked i.e close button is clicked at the upper right corner
if_configured = settings.value("isConfigured")
if if_configured:
event.accept()
else:
QMessageBox.critical(self, "PerfAnalyser", "You Need to Configure For PerfAnalyser To Work")
event.ignore()
Thanks for the help in advance ...
I will try to help out since I notice few people have seen your post. I have had this happen a long time ago so I need a reminder, but I was unable to get your code running, I also tried to recreate your ui files and the screens directory but I was not successful. However, maybe the following is still useful.
In my working code, any time I needed to create a subwindow, I executed subwindows as follows from the main window's module:
dlg = SubWindowModuleName.StartSub()
dlg.exec_()
This will execute the subwindow and waits for it to close. Then, on the subwindow module (SubWindowModuleName in the above code, "configure" for you), I did this:
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
Dialog.resize(982, 521)
... # here I build the window (I noticed that you import UI files which is a much better way of doing this)
...
class StartSub(QtGui.QDialog, Ui_Dialog):
def __init__(self,parent=None):
QtGui.QDialog.__init__(self,parent)
self.setupUi(self)
I'm learning about GUI python using pyQt4. I have function A in another file python. and I want to run in GUI file python that I extracted from file .ui (output of designer pyQt4). How to create activity indicator which is active when the function A is running? can I use progress bar (in pyQt4 designer) without know how many time for my function A running?
Thank you.
this is the function to call A in GUI .py:
def RunFunction():
import Kdtree
_dir = kdTreeOk.getNeighbor(float(radius)) #function 'A'
file = file_open('Summary.txt',_dir) # ignore, just file to save result of `A`
with file:
textOutput=file.read()
ui.result.setPlainText(textOutput)
#### button to run RunFunction in file GUI .py
ui._run.clicked.connect(RunFunction)
QProgressDialog is made for this purpose and generally called via QThread. Here's a (messy) basic example to show how this can work (without any threading). If you are calling this dialog from another window, just set parent as the calling window and you can read attributes in this dialog by calling self.parent.some_variable.
EDITED to work properly ;).
from PyQt4 import QtCore, QtGui
from time import sleep
import sys
class ProgressBarWidget(QtGui.QProgressDialog):
def __init__(self, parent=None, app=None):
super(ProgressBarWidget, self).__init__(parent)
self.app=app
self._allow_close = True
layout = QtGui.QVBoxLayout(self)
# Create a progress bar and a button and add them to the main layout
self.progressBar = QtGui.QProgressBar(self)
self.progressBar.setRange(0,100)
layout.addWidget(self.progressBar)
self.button = QtGui.QPushButton("Start", self)
layout.addWidget(self.button)
self.button.clicked.connect(self.onStart)
self.upload_count = 10
def onStart(self):
self.progressBar.setValue(0)
self.button.setText("Uploading...")
self.run()
def makeProgress(self, current_num, total_num, message = ''):
if total_num == current_num:
self.onFinished()
elif current_num == 0:
self.progressBar.setValue(0)
else:
multiplier = int(float(float(100) / float(total_num)))
c_times_m = current_num * multiplier
for i in xrange(c_times_m - int(self.progressBar.value())):
new_val = int(self.progressBar.value()) + 1
self.progressBar.setValue(new_val)
sleep(.01)
def onFinished(self):
# progress complete
self.progressBar.setRange(0,100)
for i in xrange(int(self.progressBar.value()),101):
self.progressBar.setValue(i)
self.button.setEnabled(True)
self.button.setText('Exit')
self.button.clicked.disconnect(self.onStart)
self.button.clicked.connect(self.close)
def run(self):
self._allow_close = False
self.button.setDisabled(True)
total = self.upload_count * 2
progress_meter = 0
downloaded = []
tests_to_upload = 10
for each in xrange(tests_to_upload):
sleep(0.15)
progress_meter += 1
self.makeProgress(progress_meter,total)
sleep(0.2)
progress_meter += 1
self.makeProgress(progress_meter, total)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = ProgressBarWidget(app=app)
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
I'm trying to redirect the stdout from a subprogram to the QTextBrowser widget. (Python 2.7, Window 7, pyQT4)
This is the sub program, it will be in an executable file:
#test.py
import time
print ("ABC")
time.sleep(1)
print ("DEF")
time.sleep(1)
print ("GHI")
time.sleep(1)
print ("JKL")
My pyQT4 program:
from PyQt4 import QtGui
import subprocess, time, os, sys
from subprocess import Popen, PIPE
class GUI (QtGui.QWidget):
def __init__(self):
...
self.initUI()
def initUI(self):
...
self.edit = QtGui.QTextBrowser()
grid.addWidget (self.edit, 7, 0, 5, 7)
def run(self):
p = Popen (['C:\\...\\test.exe'], stdout=PIPE, stderr=subprocess.STDOUT)
while True:
line = p.stdout.readline()
if not line:
break
self.append_edit('>>>' + line)
def append_edit(self, string):
self.edit.append(string)
def main():
app = QtGui.QApplication(sys.argv)
upgrade = GUI()
sys.exit (app.exec_())
The program I have above will wait until the subprogram finish running then print everything into the widget. What I want is for the program to output ABC then DEF so on with one second in between into the widget WHILE the subprogram is running.
Edit: I can have the subprocess output to cmd just fine, however, if I were print it into the QTextBrowser, it will not work.
I have seen many questions about this issue, but none of them seems to answer my question.
Thanks in advance.
Edit: I'm still new to python. I think this is maybe the problem: Fixed by adding QtGui.QApplication.processEvents()
def initUI(self):
...
running = QtGui.QPushButton('Run')
running.clicked.connect(self.run)
def run(self):
time.sleep(1)
append_edit('Before')
time.sleep(2)
append_edit('After')
So when I hit run in my program, instead of printing out Before first then wait 1 sec, it wait 3 seconds in total then print both Before and After. What cause this problem?
Edit: Even with QtGui.QApplication.processEvents() in my code, I'm still having the same issue. it will run the whole subprogram before showing the output to QTextBrowser.
Please help me !
I'm creating GUI by Python can run on the 3Ds Max, i heard someone said i have to use Pyside to make it. And everthing be fine until now.
This is my code :
import sys
from PySide import QtGui
from PySide.QtGui import *
from PySide.QtCore import *
class Window(QDialog):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setMinimumHeight(660)
self.setMinimumWidth(700)
self.setMaximumHeight(660)
self.setMaximumWidth(700)
grid = QtGui.QGridLayout()
grid.addWidget(self.First(), 0,0,2,0)
self.setLayout(grid)
self.setWindowTitle("Library")
self.resize(700, 660)
def First(self):
groupBox = QtGui.QFrame()
groupBox.setMaximumWidth(230)
groupBox.setMaximumHeight(700)
lbRenderer = QtGui.QLabel("Renderer :",self)
lbFolders = QtGui.QLabel("Folders :",self)
cbRenderer = QtGui.QComboBox(self)
cbRenderer.addItem("Vray")
cbRenderer.addItem("Octane")
lvFolders = QtGui.QListView(self)
lvFolders.setMaximumWidth(220)
lvFolders.setMaximumHeight(500)
btnAddNewObject = QtGui.QPushButton('Add New Objects',self)
btnNewSet = QtGui.QPushButton('New Set',self)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbRenderer,0,0)
vbox.addWidget(cbRenderer,0,1,1,3)
vbox.addWidget(lbFolders,2,0,1,4)
vbox.addWidget(lvFolders,3,0,1,4)
vbox.setColumnStretch(1, 1)
vbox.addWidget(btnAddNewObject,4,0,1,2)
vbox.addWidget(btnNewSet,4,3)
groupBox.setLayout(vbox)
return groupBox
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
clock = Window()
clock.show()
app.exec_()
I try another code same like my code , it run fine by "MAXScript Listener". But I dont know why when i try to run this, it dont appear anything(my GUI, or Alert is my code is not good).
First of all - you are initializing your script wrong, you call the 'initialize' function which returns #Success (meaning python initialized properly),
however you then just send in a string (which is the path to the file) and this does nothing.
What you have to use is:
python.ExecuteFile "C:\\Program Files\\Autodesk\\3ds Max 2015\\scripts\\Python\\yourPythonScript.py"
in maxscript listener\editor.
Autodesk documentation says:
Autodesk 3ds Max ships with a pre-built version of PySide 1.2
compatible with Python 2.7.3. This version includes the following
sub-set of modules:
QtCore
QtGui
QtNetwork
QtOpenGL
QtSql
QtSvg
QtTest
QtWebKit
QtXml
They have provided a simple sample script that you can run, save this in a python file, then execute it properly with the command mentioned in the beginning.
The code is here:
from PySide import QtGui
import MaxPlus
class _GCProtector(object):
widgets = []
def make_cylinder():
obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Cylinder)
obj.ParameterBlock.Radius.Value = 10.0
obj.ParameterBlock.Height.Value = 30.0
node = MaxPlus.Factory.CreateNode(obj)
time = MaxPlus.Core.GetCurrentTime()
MaxPlus.ViewportManager.RedrawViews(time)
return
app = QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication([])
def main():
MaxPlus.FileManager.Reset(True)
w = QtGui.QWidget()
w.resize(250, 100)
w.setWindowTitle('Window')
_GCProtector.widgets.append(w)
w.show()
main_layout = QtGui.QVBoxLayout()
label = QtGui.QLabel("Click button to create a cylinder in the scene")
main_layout.addWidget(label)
cylinder_btn = QtGui.QPushButton("Cylinder")
main_layout.addWidget(cylinder_btn)
w.setLayout(main_layout)
cylinder_btn.clicked.connect(make_cylinder)
if __name__ == '__main__':
main()
They also mention this which is important:
Normally one creates a PySide application object in a script using
QtGui.QApplication(). However, in 3ds Max, there is already a PySide
application running, so you get a handle for that object like this:
QtGui.QApplication.instance()
Use that as a start script, and port your GUI items into that and it should get you up and running.
I tried to fix your code but anything happen, i dont know why.
First thing , i opened your code and run it in Pycharm but it can not run. But it totally run in Maxscript Listener, could you explain to me ?
Second i tried to fix your code. It's all the same, i can run it on Maxscript, but the content and function inside is disappear.
This is my code
from PySide import QtGui
import MaxPlus
class _GCProtector(object):
widgets = []
app = QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication([])
def main():
MaxPlus.FileManager.Reset(True)
w = QtGui.QWidget()
w.setWindowTitle('Window')
_GCProtector.widgets.append(w)
w.show()
main_layout = QtGui.QGridLayout()
main_layout.addWidget(First(),0,0)
main_layout.addWidget(Second(),0,1)
w.setLayout(main_layout)
def First():
groupBox = QtGui.QFrame()
lbRenderer = QtGui.QLabel("Renderer :",self)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbRenderer,0,0)
groupBox.setLayout(vbox)
return groupBox
def Second():
groupBox = QtGui.QFrame()
lbRenderer = QtGui.QLabel("Renderer :",self)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbRenderer,0,0)
groupBox.setLayout(vbox)
return groupBox
if __name__ == '__main__':
main()
And this is the alert from Maxcript