I have 2 windows: MainWindow and a normal window, I have a button in MainWindow that open the second window and I have a button in the second window, I want when clicked the button in the second window close the MainWindow. The two windows are in separate class and files.
This is the MainWindow
from select_company_controller import SelectCompany
from views.main_window_view import MainWindowForm
from PySide2 import QtWidgets, QtCore, QtGui
import sys
class MainWindow(QtWidgets.QMainWindow, MainWindowForm):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
self.button.clicked.connect(self.open_select_company_window)
def open_select_company_window(self):
self.window = SelectCompany()
self.window.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.showMaximized()
sys.exit(app.exec_())
And this is the second window
from PySide2 import QtWidgets, QtCore, QtGui
from views.select_company_view import SelectCompanyForm
class SelectCompany(QtWidgets.QWidget, SelectCompanyForm):
def __init__(self):
super(SelectCompany, self).__init__()
self.setupUi(self)
self.button.clicked.connect(close_main_window)
def close_main_window(self):
pass
Try it:
main.py
import sys
#from PySide2 import QtWidgets, QtCore, QtGui
from PyQt5 import QtWidgets, QtCore, QtGui
from select_company_controller import SelectCompany
#from views.main_window_view import MainWindowForm
class MainWindow(QtWidgets.QMainWindow): #, MainWindowForm):
def __init__(self):
super(MainWindow, self).__init__()
# self.setupUi(self)
self.setWindowTitle('Main Window')
centralWidget = QtWidgets.QWidget()
self.setCentralWidget(centralWidget)
button = QtWidgets.QPushButton('Open SelectCompany')
button.clicked.connect(self.open_select_company_window)
grid = QtWidgets.QGridLayout(centralWidget)
grid.addWidget(button)
def open_select_company_window(self):
self.window = SelectCompany(self)
self.window.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show() #showMaximized()
sys.exit(app.exec_())
select_company_controller.py
#from PySide2 import QtWidgets, QtCore, QtGui
from PyQt5 import QtWidgets, QtCore, QtGui
#from views.select_company_view import SelectCompanyForm
class SelectCompany(QtWidgets.QMainWindow): #QWidget, SelectCompanyForm):
def __init__(self, parent=None):
super(SelectCompany, self).__init__(parent)
self.parent = parent
self.setWindowTitle('SelectCompany')
centralWidget = QtWidgets.QWidget()
self.setCentralWidget(centralWidget)
button = QtWidgets.QPushButton('Close MainWindow')
button.clicked.connect(self.close_main_window)
grid = QtWidgets.QGridLayout(centralWidget)
grid.addWidget(button)
def close_main_window(self):
self.parent.hide()
Update
#from PySide2 import QtWidgets, QtCore, QtGui
from PyQt5 import QtWidgets, QtCore, QtGui
#from views.select_company_view import SelectCompanyForm
class SelectCompany(QtWidgets.QWidget): #, SelectCompanyForm): # <--- QWidget
def __init__(self, parent=None):
super(SelectCompany, self).__init__(parent)
self.parent = parent
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowStaysOnTopHint) # <---
self.setWindowTitle('SelectCompany')
button = QtWidgets.QPushButton('Close MainWindow')
button.clicked.connect(self.close_main_window)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(button)
def close_main_window(self):
self.parent.hide()
Related
I am adding a gif to my QMainWindow. I want the size of my window to match exactly the size of QMovie but my QMovie is truncated at the first place and even if use resize on that, its still not showing fully.
Here is the code :
from typing import Text
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
import sys
class MainWindow(qtw.QDialog):
def __init__(self, *arg, **kwargs):
super().__init__(*arg, **kwargs)
self.centralwidget = qtw.QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.label = qtw.QLabel(self.centralwidget)
movie = qtg.QMovie('mic_listen2.gif')
movie.setScaledSize(qtc.QSize(50,50))
self.label.setMovie(movie)
movie.start()
self.show()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())
Here is the gif
https://media.giphy.com/media/QGMXK7Byy6MSXKVRlc/giphy.gif
Here is my output
You must set both the minimum size of the label and that of the widget.
#!/usr/bin/env python3
from typing import Text
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
import sys
class MainWindow(QtWidgets.QDialog):
def __init__(self, movsize=50, *arg, **kwargs):
super().__init__(*arg, **kwargs)
self.centralwidget = QtWidgets.QWidget(self)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.movie = QtGui.QMovie("giphy.gif")
self.movie.setScaledSize(QtCore.QSize(movsize, movsize))
self.movie.start()
self.label.setMovie(self.movie)
self.label.setMinimumSize(self.movie.scaledSize())
self.centralwidget.setMinimumSize(self.label.minimumSize())
# Uncomment to force the window to take the size of the movie.
# self.setMaximumSize(self.movie.scaledSize())
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w2 = MainWindow(movsize=160)
w3 = MainWindow(movsize=500)
sys.exit(app.exec_())
I want to create a QApplication which is then exited using a keyboard shortcut. Then the python script should call another QApplication.
My issues currently is that I get this error when the second QApplication is about to run:
app2 = QApplication()
RuntimeError: Please destroy the QApplication singleton before creating a new QApplication instance.
I have the following structure:
| main.py
| Q1.py
| Q2.py
This is main.py:
import Q1 as record
import Q2 as display
def main():
record.main()
display.main()
if __name__ == "__main__":
main()
This is Q1 which creates the problem:
import sys
from PySide2 import QtWidgets as qtw
from PySide2 import QtGui as qtg
from PySide2 import QtCore as qtc
from PySide2 import QtMultimedia as qtmm
class MainWindow(qtw.QMainWindow):
def __init__(self):
super().__init__()
#Create Window layout with a sound widget
soundboard = qtw.QWidget()
soundboard.setLayout(qtw.QGridLayout())
self.setCentralWidget(soundboard)
sw = SoundWidget()
soundboard.layout().addWidget(sw)
#Window Dimensions
self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
# Code ends here
self.show()
class SendOrderButton(qtw.QPushButton):
button_stylesheet = 'background-color: blue; color: white;'
def __init__(self):
super().__init__('Send Order')
self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
self.setStyleSheet(self.button_stylesheet)
#self.clicked.connect(qtc.QCoreApplication.instance().quit)
def press_button(self):
if self.isEnabled():
self.setEnabled(False)
self.setText('Send Order')
else:
self.setEnabled(True)
self.setText('Sent')
class SoundWidget(qtw.QWidget):
def __init__(self):
super().__init__()
self.setLayout(qtw.QGridLayout())
#Send Order Button
self.sendorder_button = SendOrderButton()
self.sendorder_button.setShortcut(qtg.QKeySequence('Tab'))
self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
self.sendorder_button.clicked.connect(qtc.QCoreApplication.instance().quit)
def main():
app = qtw.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
This is Q2.py which has the second QApplication:
import sys
from PySide2.QtCore import (QAbstractTableModel, Slot)
from PySide2.QtWidgets import (QAction, QApplication, QMainWindow,QWidget)
class MainWindow(QMainWindow):
def __init__(self, widget):
QMainWindow.__init__(self)
# Exit QAction
exit_action = QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.exit_app)
#Slot()
def exit_app(self, checked):
sys.exit()
class CustomTableModel(QAbstractTableModel):
def __init__(self, data=None):
QAbstractTableModel.__init__(self)
class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)
# Getting the Model
self.model = CustomTableModel()
def main():
app2 = QApplication()
widget = Widget()
window2 = MainWindow(widget)
window2.show()
sys.exit(app2.exec_())
if __name__ == "__main__":
app = QApplication()
widget = Widget()
window = MainWindow(widget)
window.show()
sys.exit(app.exec_())
As noted in the comments a Qt application can only and should have a QApplication (you might not follow this rule but nothing guarantees that it works correctly) so you will have to restructure your code.
Assuming that you want the Q1 window to be first and when that window is closed then the Q2 window opens that does not imply at any time that you have to use several QApplication. The idea is to know when a window is closed and to be notified of it, to know when a window is closed then you must override the closeEvent method of the window and to make the notification you must send a signal.
Considering the above, the solution is:
├── main.py
├── Q1.py
└── Q2.py
main.py
import sys
from PySide2 import QtWidgets as qtw
import Q1 as record
import Q2 as display
def main():
app = qtw.QApplication(sys.argv)
w1 = record.get_mainwindow()
w2 = display.get_mainwindow()
w1.closed.connect(w2.show)
w1.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Q1.py
from PySide2 import QtWidgets as qtw
from PySide2 import QtGui as qtg
from PySide2 import QtCore as qtc
class MainWindow(qtw.QMainWindow):
closed = qtc.Signal()
def __init__(self):
super().__init__()
# Create Window layout with a sound widget
soundboard = qtw.QWidget()
soundboard.setLayout(qtw.QGridLayout())
self.setCentralWidget(soundboard)
sw = SoundWidget()
soundboard.layout().addWidget(sw)
# Window Dimensions
self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.MinimumExpanding)
sw.sendorder_button.clicked.connect(self.close)
def closeEvent(self, event):
self.closed.emit()
super().closeEvent(event)
class SendOrderButton(qtw.QPushButton):
button_stylesheet = "background-color: blue; color: white;"
def __init__(self):
super().__init__("Send Order")
self.setSizePolicy(qtw.QSizePolicy.Expanding, qtw.QSizePolicy.Expanding)
self.setStyleSheet(self.button_stylesheet)
def press_button(self):
if self.isEnabled():
self.setEnabled(False)
self.setText("Send Order")
else:
self.setEnabled(True)
self.setText("Sent")
class SoundWidget(qtw.QWidget):
def __init__(self):
super().__init__()
self.setLayout(qtw.QGridLayout())
# Send Order Button
self.sendorder_button = SendOrderButton()
self.sendorder_button.setShortcut(qtg.QKeySequence("Tab"))
self.layout().addWidget(self.sendorder_button, 5, 0, 1, 2)
def get_mainwindow():
window = MainWindow()
return window
if __name__ == "__main__":
import sys
app = qtw.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Q2.py
from PySide2 import QtCore as qtc
from PySide2 import QtWidgets as qtw
class MainWindow(qtw.QMainWindow):
def __init__(self, widget):
super().__init__()
file_menu = self.menuBar().addMenu("&File")
# Exit QAction
exit_action = qtw.QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.close)
file_menu.addAction(exit_action)
class CustomTableModel(qtc.QAbstractTableModel):
pass
class Widget(qtw.QWidget):
def __init__(self):
super().__init__()
# Getting the Model
self.model = CustomTableModel()
def get_mainwindow():
widget = Widget()
window2 = MainWindow(widget)
return window2
if __name__ == "__main__":
import sys
app = qtw.QApplication()
widget = Widget()
window = MainWindow(widget)
window.show()
sys.exit(app.exec_())
This question already has an answer here:
How to fix error in my pyqt programm (first argument of unbound method must have type 'QDialog') ?
(1 answer)
Closed 3 years ago.
I'm trying to build a GUI app using PyQt5 and Python 3.7 and I've decided to break the code in different modules. When i try to import a function that creates an instance of a custom widget, an error related to 'sis'. What I read is that 'sis' is a way of encapsulation C/C++ code to be run in python. But how can I work with that?
This is the code that runs the app:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setGeometry(10,35,1500,800)
self.setWindowTitle("Cotizador TuCheff")
#self.setWindowIcon(QtGui.QIcon(''))
mainWindow(self)
def mainWindow(self):
from PyQt5 import QtCore, QtGui, QtWidgets
from Pages.Quote import quote
barMenu = QtWidgets.QTabWidget(self)
tab1 = QtWidgets.QWidget()
quoteLayout = QtWidgets.QVBoxLayout()
quoteGenerator = quote.makeQuoteWindow()
quoteLayout.addWidget(quoteGenerator)
tab1.setLayout(quoteLayout)
barMenu.addTab(tab1, "&Nueva Cotización")
self.setCentralWidget(barMenu)
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
And file, where I try to get a custom widget, is:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication
import sys
def makeQuoteWindow():
quoteWindow = QuoteWindow
quoteWindow.create()
#app = QApplication([])
#window = quoteWindow()
#window.show()
#status = app.exec_()
#sys.exit(status)
class QuoteWindow(QtWidgets.QWidget):
def __init__(self):
super(QuoteWindow, self).__init__()
def create(self):
mainWidget = QtWidgets.QWidget()
vLayout1 = QtWidgets.QVBoxLayout()
#=======------------------------ UPPER SIDE -------------------
hLayout1 = QtWidgets.QHBoxLayout()
##A LOT OF WIDGETS AND LAYOUTS
hLayout2 = QtWidgets.QHBoxLayout()
#display content
vLayout1.addLayout(hLayout1)
vLayout1.addLayout(hLayout2)
hLayout2.addItem(vSpacer1)
mainWidget.setLayout(vLayout1)
return mainWidget
if __name__ == "__main__":
makeQuoteWindow()
The error is:
TypeError: create(self, window: sip.voidptr = 0, initializeWindow: bool = True, destroyOldWindow: bool = True): first argument of unbound method must have type 'QWidget'
Try it:
main.py
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow
# from Pages.Quote import quote
from Quote import QuoteWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setGeometry(10,35,1500,800)
self.setWindowTitle("Cotizador TuCheff")
self.setWindowIcon(QtGui.QIcon('im.png'))
# mainWindow(self)
self.mainWindow()
def mainWindow(self):
# from Pages.Quote import quote
self.quoteWindow = QuoteWindow() # +++
barMenu = QtWidgets.QTabWidget(self)
tab1 = QtWidgets.QWidget()
quoteLayout = QtWidgets.QVBoxLayout()
# quoteGenerator = quote.makeQuoteWindow()
# quoteLayout.addWidget(quoteGenerator)
quoteLayout.addWidget(self.quoteWindow) # +++
tab1.setLayout(quoteLayout)
barMenu.addTab(tab1, "&Nueva Cotización")
self.setCentralWidget(barMenu)
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
Quote.py
from PyQt5 import QtCore, QtWidgets, QtGui
class QuoteWindow(QtWidgets.QWidget):
def __init__(self):
super(QuoteWindow, self).__init__()
def create(self):
mainWidget = QtWidgets.QWidget()
vLayout1 = QtWidgets.QVBoxLayout()
#=======------------------------ UPPER SIDE -------------------
hLayout1 = QtWidgets.QHBoxLayout()
##A LOT OF WIDGETS AND LAYOUTS
hLayout2 = QtWidgets.QHBoxLayout()
#display content
vLayout1.addLayout(hLayout1)
vLayout1.addLayout(hLayout2)
hLayout2.addItem(vSpacer1)
mainWidget.setLayout(vLayout1)
return mainWidget
I have an application on pyqt5. And if I click on button time lcd display start to countdown with thread I created. After the countdown finished I cant use the same thread for the same action. How can I terminate that thread and start it again with clicking button
class window(QtWidgets.QMainWindow):
def __init__(self):
super(window,self).__init__()
self.button1=QPushButton(self)
self.lcd=QLCDNumber(self)
self.tbutton1=threading.Thread(target=self.timing)
def initUI(self):
self.lcd.setVisible(False)
self.button1.clicked.connect(self.timing)
def timing(self):
self.tbutton1.start()
self.lcd.setVisible(True)
timing=self.spin.value()
for i in range(timing,-1,-1):
time.sleep(1)
if(i<10):
self.lcd.display("00:0{}".format(i))
else:
self.lcd.display("00:{}".format(i))
self.lcd.setVisible(False)
if __name__=='__main__':
app=QApplication(sys.argv)
win=window()
sys.exit(app.exec_())
Try it:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import threading
class window(QtWidgets.QMainWindow):
def __init__(self):
super(window,self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.button1 = QPushButton("Start to countdown", self)
self.lcd = QLCDNumber(self)
self.spin = QSpinBox(self)
grid = QGridLayout(centralWidget)
grid.addWidget(self.lcd)
grid.addWidget(self.spin)
grid.addWidget(self.button1)
self.initUI()
def initUI(self):
# self.lcd.setVisible(False)
self.button1.clicked.connect(self.timing)
def timing(self):
self.tbutton1 = threading.Thread(target=self.timingThread)
self.tbutton1.start()
# self.lcd.setVisible(True)
def timingThread(self):
timing=self.spin.value()
for i in range(timing, -1, -1):
# time.sleep(1)
QtCore.QThread.msleep(1000)
if(i<10):
self.lcd.display("00:0{}".format(i))
else:
self.lcd.display("00:{}".format(i))
# self.lcd.setVisible(False)
if __name__=='__main__':
app = QApplication(sys.argv)
win = window()
win.show()
sys.exit(app.exec_())
Tabs added before app.exec_() is called look and act as any other tabs u met, though if adding another after the app.exec_() call makes the new tab 'detach' from the main app window. Pic below :)
Why? How can I make it move inside the window?
import threading
import time
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QTabWidget
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QWidget
class ATry(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
time.sleep(1)
anotherTextEdit = QTextEdit()
anotherLineEdit = QLineEdit()
anotherLayout = QFormLayout()
anotherLayout.addRow(anotherTextEdit)
anotherLayout.addRow(anotherLineEdit)
anotherTab = QWidget()
anotherTab.setLayout(anotherLayout)
md.addTab(anotherTab, "Outside")
app = QApplication(sys.argv)
md = QTabWidget()
aTextEdit = QTextEdit()
aLineEdit = QLineEdit()
layout = QFormLayout()
layout.addRow(aTextEdit)
layout.addRow(aLineEdit)
thisTab = QWidget()
thisTab.setLayout(layout)
md.addTab(thisTab, "Inside")
a = ATry()
a.start()
md.show()
app.exec_()
Screen describing the problem
It works with QTimer or signals:
import sys
import time
from PyQt5.QtCore import QObject
from PyQt5.QtCore import QThread
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QTabWidget
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QWidget
class ATry(QThread):
def __init__(self, pointer):
super().__init__()
self.pointer = pointer
def run(self):
time.sleep(2)
self.pointer.emit()
def addTheTab():
anotherTextEdit = QTextEdit()
anotherLineEdit = QLineEdit()
anotherLayout = QFormLayout()
anotherLayout.addRow(anotherLineEdit)
anotherLayout.addRow(anotherTextEdit)
anotherTab = QWidget()
anotherTab.setLayout(anotherLayout)
md.addTab(anotherTab, "Whatever")
class MyQObject(QObject):
trigger = pyqtSignal()
def __init__(self):
super().__init__()
def connect_and_get_trigger(self):
self.trigger.connect(addTheTab)
return self.trigger
def getGFX(self):
app = QApplication(sys.argv)
md = QTabWidget()
md.show()
return app, md
obj = MyQObject()
app, md = obj.getGFX()
addTheTab()
a = ATry(obj.connect_and_get_trigger())
a.start()
# timer = QTimer()
# timer.timeout.connect(proba)
# timer.start(3000)
app.exec_()