I'm running a Qt5 application with a main application window and trying to show a progress dialog window. I have a multi screen system, when starting the application the main window is displayed on the screen where it has been executed which is fine, but the progress dialog when executed is shown on a different screen!?
Here is a simple example code that causes the problem for me
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class Example(QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self._show_progress()
def _show_progress(self):
self._progress = QProgressDialog('msg', None, 0, 0, self)
self._progress.setWindowTitle('Please wait...')
self._progress.setWindowModality(Qt.WindowModal)
self._progress.show()
def main():
app = QApplication(sys.argv)
cb_app = Example()
cb_app.show()
app.exec_()
if __name__ == '__main__':
main()
Can I somehow specify where the the dialog should be shown (ideally on top of the main window)?
I'm using Linux Mint 18.2, window manager X-Cinnamon and PyQt version 5.5.1
Related
Using PyQt5, I want to implement a two windows displaying one after another automatically, without the user interacting with any window. Something like this:
While True:
Show Window1
wait 2 seconds
Close Window1
Show Window2
wait 2 seconds
Close Window2
The problem I am having is that the main UI thread is stuck in app.exec_() function, so it cannot implement the opening and closing logic.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
class Win1(QMainWindow):
def __init__(self):
super(Win1, self).__init__()
uic.loadUi('win1.ui', self)
self.show()
class Win2(QMainWindow):
def __init__(self):
super(Win2, self).__init__()
uic.loadUi('win2.ui', self)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
while True:
win = Win1()
time.sleep(1)
win.close()
win = Win2()
time.sleep(1)
win.close()
app.exec_() # <--------- Program blocks here
I would appreciate if someone can share a minimal example for this working without blocking. Or please point to the mechanism that should be used.
If you are going to work with Qt then you should forget about sequential logic but you have to implement the logic using events. For example, in your case you want one window to be shown every time T and another to be hidden, so that can be implemented with a QTimer and a flag:
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import uic
class Win1(QMainWindow):
def __init__(self):
super(Win1, self).__init__()
uic.loadUi('win1.ui', self)
self.show()
class Win2(QMainWindow):
def __init__(self):
super(Win2, self).__init__()
uic.loadUi('win2.ui', self)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
timer = QTimer()
timer.setProperty("flag", True)
win1 = Win1()
win2 = Win2()
def on_timeout():
flag = timer.property("flag")
if flag:
win1.show()
win2.close()
else:
win2.show()
win1.close()
timer.setProperty("flag", not flag)
timer.timeout.connect(on_timeout)
timer.start(1 * 1000)
on_timeout()
app.exec_()
You should not use while loop or time.sleep since they block the eventloop in which the GUI lives, that is: they freeze the windows
I'm new to PyQt4 and I have 2 questions.
I want to create a GUI by which for example when I press a button, a terminal command run (e.g. ping www.google.com)
can I import cvlc in part of GUI
to wrap up I want to create a GUI in which when I press a button
cvlc -v v4l2:///dev/video0
runs and the cvlc window is shown in the GUI.
Any help would be appreciated
This will solve first part i.e. when ping button is pressed it pings google.com and the output is displayed on a terminal.
import sys,os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(150, 150, 150,150)
self.ping = QPushButton('Press to ping', self)
self.ping.move(10,20)
self.ping.clicked.connect(self.gotoPing)
def gotoPing(self):
os.system("ping www.google.com")
def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I am having problems showing a QWidget window for the user to input some data.
My script has not GUI, but I just want to show this small QWidget window.
I created the window with QtDesigner, and now I am trying to show the QWidget window like this:
from PyQt4 import QtGui
from input_data_window import Ui_Form
class childInputData(QtGui.QWidget ):
def __init__(self, parent=None):
super(childInputData, self).__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setFocus(True)
self.show()
And then, from my main class, I am doing like that:
class myMainClass():
childWindow = childInputData()
That gave me the error:
QWidget: Must construct a QApplication before a QPaintDevice
So now I am doing, from my main class:
class myMainClass():
app = QtGui.QApplication(sys.argv)
childWindow = childInputData()
Now there is no error, but the window is showed twice and the script does not wait until the data is entered, it just shows the window and continues without waiting.
What is wrong here?
It's perfectly normal that the window is shown and the script goes on: you never told the script to wait for the user to answer. You just told it to show a window.
What you would like is the script to stop until the user is done and the window is closed.
Here's one way to do it:
from PyQt4 import QtGui,QtCore
import sys
class childInputData(QtGui.QWidget):
def __init__(self, parent=None):
super(childInputData, self).__init__()
self.show()
class mainClass():
def __init__(self):
app=QtGui.QApplication(sys.argv)
win=childInputData()
print("this will print even if the window is not closed")
app.exec_()
print("this will be print after the window is closed")
if __name__ == "__main__":
m=mainClass()
The exec() method "Enters the main event loop and waits until exit() is called" (doc):
the script will be blocked on the line app.exec_() until the window is closed.
NB: using sys.exit(app.exec_()) would cause the script to end when the window is closed.
An other way is to use QDialog instead of QWidget. You then replace self.show() by self.exec(), which will block the script
From the doc:
int QDialog::exec()
Shows the dialog as a modal dialog, blocking until the user closes it
Finally, this answer of a related question advocates not to use exec, but to set the window modality with win.setWindowModality(QtCore.Qt.ApplicationModal). However this doesn't work here: it blocks inputs in other windows, but do not block the script.
you dont need the myMainClass...do something like this:
import sys
from PyQt4 import QtGui
from input_data_window import Ui_Form
class childInputData(QtGui.QWidget):
def __init__(self, parent=None):
super(childInputData, self).__init__(parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
self.setFocus(True)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
win = childInputData()
win.show()
sys.exit(app.exec_())
I'm writing in python using Qt
I want to create the application window (with decorations) to occupy the full screen size. Currently this is the code I have:
avGeom = QtGui.QDesktopWidget().availableGeometry()
self.setGeometry(avGeom)
the problem is that it ignores window decorations so the frame is larger... I googled and what not, found this:
http://harmattan-dev.nokia.com/docs/library/html/qt4/application-windows.html#window-geometry
which seems to indicate I need to set the frameGeometry to the avGeom however I haven't found a way to do that. Also, in the comments in the above link it says what I'm after may not be even possible as the programme can't set the frameGeometry before running... If that is the case I just want confirmation that my problem is not solvable.
EDIT:
So I played around with the code a bit and this gives what I want... however the number 24 is basically through trial and error until the window title is visible.... I want some better way to do this... which is window manager independent..
avGeom = QtGui.QDesktopWidget().availableGeometry()
avGeom.setTop(24)
self.setGeometry(avGeom)
Now I can do what I want but purely out of trial and error
Running Ubuntu, using Spyder as an IDE
thanks
Use QtGui.QApplication().desktop().availableGeometry() for the size of the window:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.pushButtonClose = QtGui.QPushButton(self)
self.pushButtonClose.setText("Close")
self.pushButtonClose.clicked.connect(self.on_pushButtonClose_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.pushButtonClose)
titleBarHeight = self.style().pixelMetric(
QtGui.QStyle.PM_TitleBarHeight,
QtGui.QStyleOptionTitleBar(),
self
)
geometry = app.desktop().availableGeometry()
geometry.setHeight(geometry.height() - (titleBarHeight*2))
self.setGeometry(geometry)
#QtCore.pyqtSlot()
def on_pushButtonClose_clicked(self):
QtGui.QApplication.instance().quit()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
sys.exit(app.exec_())
I've always found inheritting from the QMainWindow class to be particularly useful. Like this:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class Some_APP(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
### this line here is what you'd be looking for
self.setWindowState(Qt.WindowMaximized)
###
self.show()
def main():
app = QApplication(sys.argv)
some_app = Some_APP()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I would like to ask, as I write in the title, how to open a new window and close (completely) the current window?
There are two .py files. They are independent from each other, that means, each of them can be run on its own.
In MyApp.py there is a button. If the button is clicked, I want to close the current window/file and open the new window/file.
In my code below I can open the new window/file, but the old window is not closed. And if I close the second window, the old window will be closed as well. I have tried some methods with my knowledge/search, but none of them worked fine.
Here is the code for MyApp.py
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import NewApp
# NewApp.py in the same folder
# in NewApp.py there is a class NewApp
qtCreatorFile_MyApp = "F:\\MyApp.ui"
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
uic.loadUi(qtCreatorFile_MyApp, self)
self.show()
self.btn_inMyApp.clicked.connect(self.closeMyApp_OpenNewApp)
def closeMyApp_OpenNewApp(self):
self.Open = NewApp.NewApp()
self.Open.show()
# My Problem: How to close the MyApp completely and open NewApp?
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
sys.exit(app.exec_())
NewApp.py has similar code structure. For the purpose of integrity of this quesiton, I paste the code as follows.
qtCreatorFile_NewApp = "F:\\NewApp.ui"
class NewApp(QWidget):
def __init__(self):
super(NewApp, self).__init__()
uic.loadUi(qtCreatorFile_NewApp, self)
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = NewApp()
sys.exit(app.exec_())
Thank you for the help!