Example code I am using:
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.open_about = False
self.openAction = QtWidgets.QAction('About', self)
self.openAction.triggered.connect(self.aboutDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.calendar = QtWidgets.QCalendarWidget(self)
self.setCentralWidget(self.calendar)
def about_state_upd(self, value):
self.open_about = value
def aboutDialog(self):
self._about = AboutDialog(self)
self._about.exec_()
def hideEvent(self, hideEvent):
if self.open_about == True:
self._about.setVisible(False)
def showEvent(self, showEvent):
if self.open_about == True:
if self._about.isHidden() == True:
self._about.setModal(True)
self._about.setVisible(True)
class AboutDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(AboutDialog, self).__init__(parent)
self.setMinimumSize(400, 350)
self.parent().about_state_upd(True)
def closeEvent(self, closeEvent):
self.parent().about_state_upd(False)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
This code basically works, but seems very complicated. Is there a simpler / cleaner way to make it so that when the modal QDialog is open, if the QMainWindow is minimized, the QDialog also gets minimized too (and reverse when QMainWindow is restored)?
Code is running on KDE Neon (Kubuntu-based distro).
May be you can use this: http://korbinin.blogspot.fr/search/label/minimize%20button
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainForm(QDialog):
def __init__(self, fn=None,parent=None):
super(MainForm, self).__init__(parent,\
flags=Qt.WindowMinimizeButtonHint|Qt.WindowMaximizeButtonHint)
Thanks to the people on the PyQt Mailing list, I managed to get a workaround for KDE. Instead of using exec_(), I am just using show() - then I use setDisabled() on QMainWindow to make dialog act in a modal fashion. Here is a (very quick and basic) example for anyone interested:
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QtWidgets.QAction('About', self)
self.openAction.triggered.connect(self.aboutDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.calendar = QtWidgets.QCalendarWidget(self)
self.setCentralWidget(self.calendar)
def aboutDialog(self):
self._about = AboutDialog(self)
self.setDisabled (True)
self._about.show()
def enableWidgets(self):
self.setDisabled(False)
class AboutDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(AboutDialog, self).__init__(parent)
self.setMinimumSize(400, 350)
def closeEvent(self, parent):
self.parent().enableWidgets()
def changeEvent(self, event):
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
self.parent().showMinimized()
else:
self.parent().showMaximized()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
Link to PyQt Mailing List posts.
Related
I have made a big app importing a big number of dialogs all in main app(main loop).These dialogs import time is pretty long so i made a splash screen but ofcourse splash screen in main loop is blocked from the long time imports.The think i'm not getting is that i cant move the imports in main loop because i get an error from classes creating the ui , witch running as the code is checked from interpreter.
Here the sample code:
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtWidgets import QDialog,QWidget,QApplication, QInputDialog, QLineEdit, QFileDialog,QProgressDialog, QMainWindow, QFrame,QSplashScreen
from PyQt5.QtCore import QThread , pyqtSignal,Qt
from PyQt5.QtGui import QIcon,QPainter,QPixmap
#here the slow import dialogs
from ui import Ui_MainWindow,HoverButton
from dialog1 import Ui_Dialog
from dialog2 import Ui_Dialog2
from dialog3 import Ui_dialog3
from dialog4 import Ui_Dialog4
from dialog5 import Ui_dialog5
from dialog6 import Ui_dialog6
#....... and so on
###after class methods###
class Dialog1(QtWidgets.QDialog,Ui_Dialog): #fuel button prompt dialog for inputs
def __init__(self,parent=None):
super(Dialog1, self).__init__(parent)
self.setupUi(self)
class Dialog2(QtWidgets.QDialog,Ui_Dialog2): #all errors dialog
def __init__(self,parent=None):
super(Dialog2, self).__init__(parent)
self.setupUi(self)
class Dialog3(QtWidgets.QDialog,Ui_dialog3): #that might take a while dialog
def __init__(self,parent=None):
super(Dialog3, self).__init__(parent)
self.setupUi(self)
class Dialog4(QtWidgets.QDialog,Ui_Dialog4): #input gross weight dialog
def __init__(self,parent=None):
super(Dialog4, self).__init__(parent)
self.setupUi(self)
class Dialog5(QtWidgets.QDialog,Ui_dialog5): #map viewer specifications dialog
def __init__(self,parent=None):
super(Dialog5, self).__init__(parent)
self.setupUi(self)
#etc
###MAIN GUI###
class mainProgram(QtWidgets.QMainWindow, Ui_MainWindow): #main window
def __init__(self, parent=None):
super(mainProgram, self).__init__(parent)
self.setupUi(self)
self.dialog = Dialog1(self)
self.dialog2 = Dialog2(self)
self.dialog3 = Dialog3(self)
self.dialog3.close()
self.dialog4 = Dialog4(self)
self.dialog5 = Dialog5(self)
self.dialog6 = Dialog6(self)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
splash_pix = QPixmap('loading.jpg')
splash_pix.scaled(200, 400, QtCore.Qt.KeepAspectRatio)
splash = QSplashScreen(splash_pix,Qt.WindowStaysOnTopHint)
splash.setMask(splash_pix.mask())
splash.show()
app.processEvents()
nextGui = mainProgram()
# nextGui.setWindowFlags(QtCore.Qt.FramelessWindowHint)
splash.finish(nextGui)
nextGui.showMaximized()
sys.exit(app.exec_())
Assuming that the only problem is the large number of dialogues and not that each dialogue itself has a task that consumes a lot of time so a possible option is to load each dialog every T ms so in the interim time the QSplashScreen works correctly.
# ...
###MAIN GUI###
class mainProgram(QtWidgets.QMainWindow, Ui_MainWindow):
loadFinished = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(mainProgram, self).__init__(parent)
self.setupUi(self)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self._T_dialogs = iter(
enumerate((Dialog1, Dialog2, Dialog3, Dialog4, Dialog5, Dialog6))
)
self._timer = QtCore.QTimer(self, timeout=self.create_dialogs, interval=100)
self._timer.start()
#QtCore.pyqtSlot()
def create_dialogs(self):
try:
i, T = next(self._T_dialogs)
w = T(self)
setattr(self, "dialog{}".format(i), w)
except StopIteration:
self._timer.stop()
self.showMaximized()
self.loadFinished.emit()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
splash_pix = QtGui.QPixmap("loading.jpg")
splash_pix.scaled(200, 400, QtCore.Qt.KeepAspectRatio)
splash = QtWidgets.QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint)
splash.setMask(splash_pix.mask())
splash.show()
nextGui = mainProgram()
nextGui.loadFinished.connect(splash.close)
sys.exit(app.exec_())
I open the dialog from the main window, where by clamping the keys, I fill the line with their names. The problem is that I can not understand where you need to do a cycle of checking all the keys on their state. Maybe there is another way to get the keys pressed? Or where you need to listen to the clamping so that the dialog box does not hang and the string is updated.
MainWindow:
def showBindings(self, param):
from dialogs import KeyBindingsDialog
self.dialog = KeyBindingsDialog()
self.dialog.show()
Dialog:
class KeyBindingsDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(KeyBindingsDialog, self).__init__(parent)
self.ui = KeyBindings()
self.ui.setupUi(self)
Use QKeySequenceEdit:
from PyQt5 import QtCore, QtGui, QtWidgets
class KeySequenceEdit(QtWidgets.QKeySequenceEdit):
def keyPressEvent(self, event):
super(KeySequenceEdit, self).keyPressEvent(event)
seq_string = self.keySequence().toString(QtGui.QKeySequence.NativeText)
if seq_string:
last_seq = seq_string.split(",")[-1].strip()
le = self.findChild(QtWidgets.QLineEdit, "qt_keysequenceedit_lineedit")
self.setKeySequence(QtGui.QKeySequence(last_seq))
le.setText(last_seq)
self.editingFinished.emit()
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._keysequenceedit = KeySequenceEdit(editingFinished=self.on_editingFinished)
button = QtWidgets.QPushButton("clear", clicked=self._keysequenceedit.clear)
hlay = QtWidgets.QHBoxLayout(self)
hlay.addWidget(self._keysequenceedit)
hlay.addWidget(button)
#QtCore.pyqtSlot()
def on_editingFinished(self):
sequence = self._keysequenceedit.keySequence()
seq_string = sequence.toString(QtGui.QKeySequence.NativeText)
print("sequence: ", seq_string)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Hi guys im new in python and PyQt already im using PyQt 5 lib and already faced with really primary problem.
I want to call print function (or any other functions like this) with just cursor moving no clicking on that.
some thing like tooltips that not needed to click on any button.
Thank you for your help.
There are several ways to implement:
1. customized button.
from PyQt5 import QtCore, QtWidgets
class HoverButton(QtWidgets.QPushButton):
hovered = QtCore.pyqtSignal()
def enterEvent(self, event):
self.hovered.emit()
super(HoverButton, self).enterEvent(event)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
btn = HoverButton("Press me")
btn.hovered.connect(self.onHovered)
lay.addWidget(btn)
lay.addWidget(QtWidgets.QLineEdit())
def onHovered(self):
print("hovered")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
2. eventFilter
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
self.btn = QtWidgets.QPushButton("Press me")
self.btn.installEventFilter(self)
lay.addWidget(self.btn)
lay.addWidget(QtWidgets.QLineEdit())
def eventFilter(self, obj, event):
if obj == self.btn and event.type() == QtCore.QEvent.HoverEnter:
self.onHovered()
return super(Widget, self).eventFilter(obj, event)
def onHovered(self):
print("hovered")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I was trying to set a shortcut for dropdown menu. The code is below
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QAction
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
super(SystemTrayIcon, self).__init__(icon, parent)
menu = QtWidgets.QMenu(parent)
# add actions and shortcuts for them.
exitAction = QAction('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(parent.close)
menu.addAction(exitAction)
restoreAction = QAction('Restore', self)
restoreAction.setShortcut("Ctrl+R")
restoreAction.triggered.connect(self.restore)
menu.addAction(restoreAction)
self.setContextMenu(menu)
def restore(self):
print 'restore'
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Icon')
self.tray_icon = SystemTrayIcon(QtGui.QIcon('/opt/WizNote/wiznote.png'), self)
self.tray_icon.show()
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication([])
w = MainWindow()
sys.exit(app.exec_())
The shortcut doesn't work. Is there something wrong with my code?
Python2.7 and PyQt5 was installed in my laptop.
I had exactly the same problem as yours, and I solved it by respecting the following pattern for each action:
menu.addAction(exitAction)
parent.addAction(exitAction) # line to be added
I have a button and two tablewidgets.Pressing the button does two different things depending on which one of the tablewidgets was activated before the push of the button.How can I get the right widget?
You could for example use the focusInEvent to store the activated widget and return it when pressing the button, something like this:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyTableWidget(QtGui.QTableWidget):
focusIn = QtCore.pyqtSignal(QtCore.QObject)
def __init__(self, parent=None):
super(MyTableWidget, self).__init__(parent)
def focusInEvent(self, event):
self.focusIn.emit(self)
return super(MyTableWidget, self).focusInEvent(event)
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.lastFocusedTableWidget = None
self.tableWidgetFirst = MyTableWidget(self)
self.tableWidgetFirst.setObjectName("tableWidgetFirst")
self.tableWidgetFirst.focusIn.connect(self.on_tableWidget_focusIn)
self.tableWidgetSecond = MyTableWidget(self)
self.tableWidgetSecond.setObjectName("tableWidgetSecond")
self.tableWidgetSecond.focusIn.connect(self.on_tableWidget_focusIn)
self.pushButtonLastFocused = QtGui.QPushButton(self)
self.pushButtonLastFocused.setText("Print the last focused QTableWidget!")
self.pushButtonLastFocused.clicked.connect(self.on_pushButtonLastFocused_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.tableWidgetFirst)
self.layoutVertical.addWidget(self.tableWidgetSecond)
self.layoutVertical.addWidget(self.pushButtonLastFocused)
#QtCore.pyqtSlot(QtCore.QObject)
def on_tableWidget_focusIn(self, obj):
self.lastFocusedTableWidget = obj
#QtCore.pyqtSlot()
def on_pushButtonLastFocused_clicked(self):
print self.lastFocusedTableWidget.objectName()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.resize(333, 111)
main.show()
sys.exit(app.exec_())