I am trying to open a new window inside a mdiArea and I achieved it with the following code.
class Window(QMainWindow, MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_tool)
def open_tool(self):
# Create Sub Window
new_win = new_Window()
self.mdiArea.addSubWindow(new_win)
new_win.show()
self.mdiArea.cascadeSubWindows()
Now, since each new window that I open, has multiple long tasks, I wanted to run each new window in a new thread in order to prevent freezing of the entire gui.
I tried using the following code:
class Tool_Thread(QtCore.QThread):
def __init__(self, mdiArea):
# Get Widget Area
super().__init__()
self.mdiArea = mdiArea
# Create Sub Window
self.new_win = new_Window()
self.mdiArea.addSubWindow(self.new_win)
def run(self):
self.new_win.show()
and running it in the main gui with
class Window(QMainWindow, MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.open_tool)
def open_tool(self):
new_tool = TMTC_Thread(self.mdiArea)
new_tool .start()
but the main gui continues to freeze. Is there any way to handle cases like this?
Related
Guys!
I'm working with QTDesigner and PyQT5, I've created two screens using QTDesi. A Login form and a Main form. I'm trying to call the main screen after the login screen. But it didn't work. I've looked up to many tutorials, but non of them, worked for me.
Here's some code:
To call the Login Screen, I've used this class (On Controller):
class LoginController(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent=parent)
super().__init__(parent)
self.setupUi(self)
self.txtLogo.setPixmap(QtGui.QPixmap('../gui/img/icons/aperam.png'))
self.action_performed()
def action_performed(self):
self.pushButton.clicked.connect(self.valid_login)
def valid_login(self):
user = self.txtUser.text()
password = self.txtPassword.text()
if model.validate_login(user, password):
self.close()
main = HomeScreen()
Then, to call the Main Screen, I'm using this:
class HomeScreen(Ui_Model):
def __init__(self):
super(HomeScreen, self).__init__()
self.ui = Ui_Model()
self.main = QtWidgets.QMainWindow()
self.login_home_screen()
def login_home_screen(self):
self.ui.setupUi(self.main)
self.main.show()
self.ui.actionNovo.triggered.connect(self.user_screen_show)
self.main.close()
But It didn't work for me. It only shows up a black screen then closes.
The "Start" from the system is this code (Where I call the LoginScreen):
cd = LoginController()
if __name__ == "__main__":
import sys
ui = LoginController()
cd.show()
sys.exit(app.exec_())
Can you help me? I've tried to many tutorials and articles, but both them didn't work. I want to call another form after the login is sucessufuly.
Thanks
There are various problems with your code.
HomeScreen should inherit from QMainWindow too, not only from Ui_Model;
you should avoid mixing QWidget/uic creation styles;
you should not call the base class __init__ if you're also calling super().__init__ afterwards;
you create a HomeScreen instance (main), but then the function returns, which means that that instance will be instantly garbage collected;
two instances of LoginController are being created, but you only need one;
the home screen is shown and closed afterwards, which doesn't make much sense;
there is usually no need to create other functions if you just run them once (I'm referring to action_performed and login_home_screen), especially if they only do small tasks that can be included in the __init__;
The simplest solution for your case is to create a custom signal for the login screen, and connect it to the show function of the home screen window.
Note that I don't know what user_screen_show does; if it's used to show again the login, you should use a similar system to show the dialog again.
class LoginController(QtWidgets.QDialog, Ui_Dialog):
loginSuccessful = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(LoginController, self).__init__(parent)
self.setupUi(self)
self.txtLogo.setPixmap(QtGui.QPixmap('../gui/img/icons/aperam.png'))
self.pushButton.clicked.connect(self.valid_login)
def valid_login(self):
user = self.txtUser.text()
password = self.txtPassword.text()
if model.validate_login(user, password):
# login is valid, emit the signal
self.loginSuccessful.emit()
self.hide()
class HomeScreen(QtWidgets.QMainWindow, Ui_Model):
newLogin = QtCore.pyqtSignal()
def __init__(self):
super(HomeScreen, self).__init__()
self.setupUi(self)
self.actionNovo.triggered.connect(self.user_screen_show)
def user_screen_show(self):
self.newLogin.emit()
self.hide()
if __name__ == "__main__":
import sys
cd = LoginController()
cd.show()
home = HomeScreen()
cd.loginSuccessful.connect(home.show)
home.newLogin.connect(cd.show)
sys.exit(app.exec_())
It's weird that a function to create a new window works when I use a button to call it and didn't work when something satisfy some condition to call it.
from PyQt5 import QtWidgets, QtCore
from interface import Ui_Form as uiInterface
from chooseLauncherFile import Ui_Form as uiChooseLauncherFile
class MyInterface(uiInterface):
def __init__(self):
self.window = QtWidgets.QWidget()
self.setupUi(self.window)
self.threads = QtCore.QThread()
self.threads.run = self.init
self.threads.start()
self.window.show()
def init(self):
self.util = Util(self)
self.util.detectLauncher()
self.syncToServer() #this function should run after main window show
def chooseLauncherFile(self):
self.chooseLauncherWindow = QtWidgets.QWidget()
self.chooseLauncherUi=MyChooseLauncherFile()
self.chooseLauncherUi.setupUi(self.chooseLauncherWindow)
self.chooseLauncherWindow.show()
class MyChooseLauncherFile(uiChooseLauncherFile):
def confirm(self, item):
EXEC_FILE = item.text()
class Util():
def __init__(self, interface):
self.interface = interface
def detectLauncher(self):
if True: #has been simplified here
self.interface.chooseLauncherFile()
these code will make the new child window non-response, but it will be ok when I change the code like following
def init(self):
self.syncToServer() #this function should run after main window show
self.pushButton.pressed.connect(self.chooseLauncherFile)
#this line come from another file
#to use a button to call function
It's highly appreciate if you could help me make code of top works, in another world, create a new window automatically not using button.
I have Qdialog with that I open from main window:
Dialog = myDialog(self)
Here is the code from new opened Dialog:
class myDialog(QtGui.QDialog, Ui_DialogCalibration):
def __init__(self, parent=None):
super(myDialog, self).__init__(parent)
self.setupUi(self)
How can pass parameter(lint) from main window to this new window, something like
Dialog = myDialog(self, listInformation)
and then in myDialog class use that list
class myDialog(QtGui.QDialog, Ui_DialogCalibration):
def __init__(self, parent=None, listInfo):
super(myDialog, self).__init__(parent)
self.listInfo = listInfo
self.setupUi(self)
Then, when you go to create the myDialog, you can add the list as a parameter. When you need to use it inside of your myDialog, you would access it as self.listInfo.
EDIT: To further expand on the comments:
If you have def __init__(self, parent=None, listInfo=None), you would call it as Dialog = myDialog(parent=self, listInfo=listInfo). If you had it as def __init__(self, parent, listInfo) you would do Dialog = myDialog(self, listInfo). Hopefully you see the pattern here.
I've got two classes; one for my window and one for my controlling object
class window(baseClass, testForm):
scanStarted = QtCore.pyqtSignal(str)
def __init__(self,parent=None):
super(window, self).__init__(parent)
self.setupUi(self)
#other window setup
self._scanner.pushScan.clicked.connect(self._scanClicked)
def _scanClicked(self):
self.scanStarted.emit( self._scanner.getTextData() )
and my controlling object
class vis(QtCore.QObject):
def __init__(self):
self._oreList = []
self._w = window()
self._w.scanStarted.connect(self._scanOre)
def _scanOre(self, rawText):
print "main ->", rawText
When using the QtCore.QObject as my reference, this signal won't connect to the _scanOre. When I switch the reference to python 'object' it'll work fine. I've been trying to figure out why it won't connect using the QtCore.QObject type.
The signal will also connect just fine in the window class regardless.
I tried giving the _scanOre the #QtCore.pyqtSlot(str, name='scanGo') and adding the name parameter into the signal creation as well. I'm not sure what I'm missing here.
You forgot to initialize the QObject:
class vis(QtCore.QObject):
def __init__(self, parent=None):
super(vis, self).__init__(parent) # you are missing this line
# also the `parent` arg
self._oreList = []
self._w = window.window()
self._w.scanStarted.connect(self._scanOre)
def _scanOre(self, rawText):
print "main ->", rawText
I'm creating an app using Eric4 and PyQt4.
I have two dialog boxes, one runs as a thread and the other is a standard dialog box with a label inside, which I want to change to an image.
Every time the main window thread runs I want it to change the current image displayed in the dialog box to a new image. Everything works fine except every time the thread runs it creates a new dialog box with the new image inside - I want it to change the image in the dialog box that's currently open.
Dialog box with image inside:
class SubWindow(QDialog, Ui_subWindow):
def __init__(self, parent = None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
def main(self, img):
pic = self.imgView
pic.setPixmap(QtGui.QPixmap(os.getcwd() + img))
Thread which changes the image:
class MainWindow(QDialog, Ui_MainWindow, threading.Thread):
def __init__(self, parent = None):
threading.Thread.__init__(self)
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
#some code here which does some stuff then calls changeImg()
def changeImg(self):
img = SubWindow()
img.main(img)
I've not included all my code, only the relevant bits.
It looks like the problem is that you are creating a new SubWindow every time you wish to change the image. I would recommend creating the SubWindow as an attribute to MainWindow in the MainWindiw.__init__ function:
class MainWindow(QDialog, Ui_MainWindow, threading.Thread):
def __init__(self, parent = None):
threading.Thread.__init__(self)
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
self.img = SubWindow() # Create SubWindow once here
def changeImg(self):
self.img.main(self.img) # Only change the image, no new SubWindow