In the minimal example given below, the context menu (right click on white section of the gui) is displayed only briefly and then disappears. This is the case if the app is started from the IPython (0.13.1) console. When started normally from shell it works as it should.
import sys
from PySide import QtGui, QtCore
from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
class ContextTestGui(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_ContextTestWindow()
self.ui.setupUi(self)
self.ui.treeView.addAction(self.ui.actionCopy)
self.ui.treeView.addAction(self.ui.actionShow)
class Ui_ContextTestWindow(object):
def setupUi(self, ContextTestWindow):
ContextTestWindow.resize(200, 100)
self.treeView = QtGui.QTreeView(ContextTestWindow)
self.treeView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.treeView.setMinimumSize(QtCore.QSize(100, 100))
self.actionCopy = QtGui.QAction("Copy",ContextTestWindow)
self.actionShow = QtGui.QAction("Show",ContextTestWindow)
def create_window(window_class,**kwargs):
app = get_app_qt4(sys.argv)
window = window_class()
window.show()
start_event_loop_qt4(app)
return window
if __name__ == '__main__':
simgui = create_window(ContextTestGui)
I believe this is IPython Issue #2380, which should be fixed in current git master.
If you want your app to workaround this bug in 0.13, you will have to ship with your own code a version of IPython/lib/inputhookqt4.py from master, and monkeypatch IPython with:
from IPython.lib import inputhook
inputhook.enable_qt4 = my_enable_qt4
OR, alternatively, just override create_inputhook_qt4
from IPython.lib import inputhookqt4
inputhookqt4.create_inputhook_qt4 = my_create_inputhook_qt4
I expect both approaches should work, as long as you do it before %gui qt is called.
How do you run the application ? In[1]: %run file.py?
I can't reproduce it on ~last master (feb 4 f46bfec 08389b4) with OS X
Related
I have the following simple Qt app that creates a system tray icon from a given text. When I run the app via vscode terminal, everything seems to be fine (see the screenshot below):
Strangely, when I run the app via system terminal (bash), icon size is not respected, and the text is shrunk (see below):
I'd appreciate it if anyone could shed some light what might be causing this strange behaviour. Here's the code:
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtWidgets, QtGui, QtSvg
def create_tray_icon(label):
r"""Creates QIcon with the given label."""
w, h = 22*4, 22
pixmap = QtGui.QPixmap(w, h)
pixmap.fill(QtCore.Qt.transparent) # alternative: QtGui.QColor("white")
painter = QtGui.QPainter(pixmap)
painter.setPen(QtGui.QColor("white"))
align = int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
painter.drawText(pixmap.rect(), align, str(label))
painter.end()
icon = QtGui.QIcon()
icon.addPixmap(pixmap)
return icon
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
self.menu = QtWidgets.QMenu(parent)
exitAction = self.menu.addAction("Exit")
exitAction.triggered.connect(lambda: sys.exit())
self.setContextMenu(self.menu)
def memprofilerApp():
r"""Runs the Qt Application."""
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
icon = create_tray_icon(label="Hello world!")
trayIcon = SystemTrayIcon(icon)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
memprofilerApp()
After inspecting environment variables (by running env) on vscode terminal and comparing it with that on system terminal, it turned out that the culprit was XDG_CURRENT_DESKTOP! In vscode terminal (which QIcon size is respected), it is set to UNITY, whereas in system terminal it is set to ubuntu:GNOME.
I don't know the root cause, but a quick fix is to use the following script to run the app:
#!/bin/bash
XDG_CURRENT_DESKTOP=Unity
/path/to/python main.py
Just out of curiosity, if anyone knows why ubuntu:GNOME cause the QIcon sizing to break, please let us know!
Is there a way to change default menu title for native menu on MacOS for a simple pyqt5 app?
I'm trying to change "Python" menu entry on above image. Is there a way to rename it? Can I hide it somehow?
This code prints only "File":
menubar = self.menuBar()
for item in menubar.actions():
print(item.text())
menubar.setNativeMenuBar(False) doesn't help too (just move "File" into the MainWindow).
Update Sample app code:
from PyQt5 import QtCore, QtWidgets, uic
import sys
class Ui(QtWidgets.QMainWindow):
def __init__(self):
super(Ui, self).__init__()
# QtCore.QCoreApplication.setApplicationName('QtFoo') # doesn't work
uic.loadUi('App.ui', self)
self.show()
# app = QtWidgets.QApplication(sys.argv)
app = QtWidgets.QApplication(["MyCoolApp"])
# app.setApplicationName("QtFoo") # doesn't work
# app.setApplicationDisplayName("Display Name")
window = Ui()
app.exec()
If you are not willing to package your app, you could create a temporary symbolic link to python as described here. This link can be used to execute python apps while displaying a custom name in the title bar:
go to the location of your app (e.g. my_app.py) file in the terminal
create symbolic link (replace location to your python interpreter, replace "BeautifulNaming" with desired name)
ln -s /Users/Christian/miniconda3/bin/python BeautifulNaming
call link to python with your script
./BeautifulNaming my_app.py
The "python" in the system menu bar appears because you run the script from the python, as soon as you package the application the title will disappear. For example the following code
# FileName PyQt5MenuProblem.py
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow
class AppTest(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("My application")
self._createMenuBar()
def _createMenuBar(self):
self.menuBar = self.menuBar()
self.menuBar.setNativeMenuBar(False)
fileMenu = self.menuBar.addMenu("&File")
editMenu = self.menuBar.addMenu("&Edit")
if __name__== "__main__":
app = QApplication(sys.argv)
plotWindow = AppTest()
plotWindow.showMaximized()
sys.exit(app.exec_())
after packaging with
pyinstaller --onefile PyQt5MenuProblem.py
looks like
Key words: MacOS, User Interface, LSUIElement, pyinstaller, pyqt5
I guess that I am not closing my PyQT5 Window correctly. I am using spyder (3.3.5) which I have installed with anaconda, to program a pyqt5 program. I am using qt creator to design my ui file, which I load using the loadUi function in pyqt package. Everything works fine with the code, until I need to close it. I close the window via the close button (the x button in the top right). The window itself is closed, but it seems like the console (or shell) is stuck, and I can't give it further commands or to re run the program, without having to restart the kernel (to completely close my IDE and re opening it).
I have tried looking for solutions to the problem in the internet, but none seems to work for me. Including changing the IPython Console > Graphics to automatic.
Edit: Also Created an issure:
https://github.com/spyder-ide/spyder/issues/9991
import sys
from PyQt5 import QtWidgets,uic
from PyQt5.QtWidgets import QMainWindow
class Mic_Analysis(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui=uic.loadUi("qt_test.ui",self)
...
if __name__ == "__main__":
def run_app():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app=QtWidgets.QApplication.instance()
mainWin=Mic_Analysis()
mainWin.show()
app.exec_()
run_app()
If someone have any suggestion I would be very happy to hear them.
For me, it helped to remove the 'app.exec_()' command.
But then it closes immediatly when running the code. To keep the window open, I needed to return the MainWindow instance to the global scope (or make it a global object). My code looks like this:
from PyQt5 import QtWidgets
import sys
def main():
if not QtWidgets.QApplication.instance():
app = QtWidgets.QApplication(sys.argv)
else:
app = QtWidgets.QApplication.instance()
main = MainWindow()
main.show()
return main
if __name__ == '__main__':
m = main()
Try adding :
app.setQuitOnLastWindowClosed(True)
to your main() function
def main():
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(True)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Surprizinglly, for me this works well. No QApplication is needed.
It seems to work in another thread.
from PyQt5 import QtWidgets,uic
class Ui(QtWidgets.QDialog):
def __init__(self):
super().__init__()
uic.loadUi('./test.ui',self)
self.show()
w=Ui()
I want to restart my app, but I follow the tutorial and add systemtray icon. every time restart the app, the systemtray not disappear, I found the app not really restart by some reason.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
EXIT_CODE_REBOOT = 122
def __init__(self):
super().__init__()
self.restart_button = QPushButton('restart')
self.restart_button.clicked.connect(self.onRestart)
self.setCentralWidget(self.restart_button)
self.systray = QSystemTrayIcon(self)
icon = self.style().standardIcon(QStyle.SP_TrashIcon)
self.systray.setIcon(icon)
self.systray.show()
def onRestart(self, checked):
QApplication.exit(self.EXIT_CODE_REBOOT)
if __name__ == '__main__':
currentExitCode = MainWindow.EXIT_CODE_REBOOT
while currentExitCode == MainWindow.EXIT_CODE_REBOOT:
app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
currentExitCode = app.exec()
app = None
each time restart the app, the previous system tray always existing, it is like it start an other process, I want the only process and not consuming any resources.
I tried your code and it works fine on Linux, but I also found similar reports (like this) about persistent icon after quit on Windows.
While doing a self.systray.hide() before quitting should be fine enough, I think that deleting the object from Qt's side (not by using del) might be better:
def onRestart(self, checked):
self.systray.deleteLater()
QApplication.exit(self.EXIT_CODE_REBOOT)
I try to build an interface. I installed PyQt 5 (5.6.0) in Anaconda 3.6 (Python 3.6.3). I use Spyder (3.2.6) as my compiler.
import sys
from PyQt5 import QtGui,QtCore
from PyQt5.QtWidgets import QPushButton,QApplication,QMainWindow
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(50,50,500,300)
self.setWindowTitle("PyQt!")
self.show()
if __name__ == "__main__":
def run():
App=QApplication(sys.argv)
Window()
App.exec()
run()
There is no error while running this command. However, there is no output too. Shouldn't I see a window of 500 pixels x 300 pixels at (50, 50)?
Thanks for your insights :)