Getting PySide Hello App to run under Canopy - python

A Canopy user here learning about PySide. When I run the demo code below, QApplication complains the event loop is already running.'
import sys
from PySide.QtCore import *
from PySide.QtGui import *
# Create a Qt application
#app = QApplication(sys.argv) #QApplication complains an instance already exists
app = QApplication.instance() #So we just ask for the instance.
#app.aboutToQuit.connect(app.deleteLater)
# Create a Label and show it
label = QLabel("Hello World")
label.show()
# Enter Qt application main loop
app.exec_()
sys.exit()
So how can I get this simple code to run?

Yes, Pylab is a mode of IPython which starts an event loop for the IPython front end so that you can interact at the IPython command line with your GUI.
Here's an simple example of code which will run with or without Pylab.
import sys
from PySide import QtGui
app = QtGui.QApplication.instance()
standalone = app is None
if standalone:
app = QtGui.QApplication(sys.argv)
wid = QtGui.QWidget()
wid.resize(250,150)
wid.setWindowTitle('Simple')
wid.show()
if standalone:
sys.exit(app.exec_())
else:
print "We're back with the Qt window still active"

Related

Grab keyboard on XEmbed window

I'm trying to migrate open source application written in PyQt4 to Qt5 (PyQt5 or PySide2) and I have a problem with migration of QtGui.QX11EmbedContainer to Qt5. It looks that XEmbed container created with QtWidgets.QWidget.createWindowContainer cannot grab keyboard properly.
In Qt4 it was possible to grab keyboard in such way (for simplicity I'll attach xterm):
import sys
from PyQt4 import QtGui, QtCore
def clientEmbed():
container.grabKeyboard()
print("Keyboard grabbed")
def clientClosed():
container.releaseKeyboard()
print("Keyboard released")
app = QtGui.QApplication(sys.argv)
mainWidget = QtGui.QWidget()
container = QtGui.QX11EmbedContainer(mainWidget)
container.clientIsEmbedded.connect(clientEmbed)
container.clientClosed.connect(clientClosed)
vBoxLayout = QtGui.QVBoxLayout()
vBoxLayout.addWidget(container)
mainWidget.setLayout(vBoxLayout)
process = QtCore.QProcess(container)
winId = container.winId()
mainWidget.show()
process.start("xterm", "-into {} -xrm xterm*.allowSendEvents:true".format(winId).split())
sys.exit(app.exec_())
In this case any key event was sent to xterm, but in Qt5 analogous code doesn't work properly and xterm doesn't receives any key events:
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
app = QtWidgets.QApplication(sys.argv)
def processStarted():
container.grabKeyboard()
print("Process started")
mainWidget = QtWidgets.QWidget()
mainWidget.showMaximized()
window = QtGui.QWindow()
container = QtWidgets.QWidget.createWindowContainer(window, mainWidget)
vBoxLayout = QtWidgets.QVBoxLayout()
vBoxLayout.addWidget(container)
mainWidget.setLayout(vBoxLayout)
mainWidget.show()
winId = int(window.winId())
process = QtCore.QProcess(container)
process.started.connect(processStarted)
process.start("xterm", "-into {} -xrm xterm*.allowSendEvents:true".format(winId).split())
sys.exit(app.exec_())
At this time I'm considering migration from Qt4 to GTK3 which plays nice with grabbing keyboard on XEmbed, but it will be more time consuming. For example analogous working code in PyGTK:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
from subprocess import Popen
def plugged_added(plugged_socket):
Gdk.Seat.grab(seat, plugged_socket.get_window(), Gdk.SeatCapabilities.KEYBOARD, True)
print("xterm attached")
def plugged_removed(plugged_socket):
Gdk.Seat.ungrab(seat)
print("xterm detached")
seat = Gdk.Display.get_default().get_default_seat()
window = Gtk.Window(title="Xterm embed")
socket = Gtk.Socket()
window.add(socket)
sock_id = str(socket.get_id())
socket.connect("plug-added", plugged_added)
socket.connect("plug-removed", plugged_removed)
cmd = ["xterm", '-xrm', "xterm*.allowSendEvents: true", "-into", sock_id]
Popen(cmd)
socket.show()
window.show()
window.connect("destroy", Gtk.main_quit)
Gtk.main()
So does anybody have idea how to achieve grabbing keyboard in Qt5 like it is possible in Qt4 or PyGTK3? I'm also opened to solutions including xlib, xcb etc.

Python Shell restart after while loop with PyQt5

actually I try to do a displayer of html page. I have some of list of html that I need to display, each page must stay visible while x secondes.
But, after the first page is display, the application crash and the python shell restart in consequence.
On my mind, I would create the window to display the page and close the application because after I will try to display png/jpg, so I need to close app to use Pygame for pictures and re-build the app to display html page after.
My list looking for it :
html page/html page/picture/html page/picture/picture
So I have build a sample code to test in while boucle the displayer :
from PyQt5 import QtWidgets, QtWebEngineWidgets, QtCore
import sys
continuer = True
while continuer:
print("Application created")
# Create application
app = QtWidgets.QApplication(sys.argv)
# Add window
win = QtWidgets.QWidget()
win.setWindowTitle('My first rendering')
# Add layout
layout = QtWidgets.QVBoxLayout()
win.setLayout(layout)
# Create QWebView
view = QtWebEngineWidgets.QWebEngineView()
view.setUrl(QtCore.QUrl('https://google.com'))
# Add QWebView to the layout
layout.addWidget(view)
# Show window, run app
win.show()
QtCore.QTimer.singleShot(7*1000, win.close)
QtCore.QTimer.singleShot(7*1000, app.quit)
print("View displayed")
# While loop
app.exec_()
print('Close Application')
print("End While Loop")
Result after executing
It's probably sys.argv in app var the mistake, but I'm new in Python so I don't know how to fix the problem.
The problem is that QApplication is not necessarily eliminated and therefore you would be creating more than one QApplication what Qt forbids, a better solution is to rethink it verifying that if it does not exist then create a new one:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
continuer = True
while continuer:
print("Application created")
# Create application
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
# Add window
win = QtWidgets.QWidget()
win.setWindowTitle("My first rendering")
# Create QWebEngineView
view = QtWebEngineWidgets.QWebEngineView()
view.setUrl(QtCore.QUrl("https://google.com"))
# Add layout
layout = QtWidgets.QVBoxLayout(win)
win.setLayout(layout)
# Add QWebView to the layout
layout.addWidget(view)
# Show window, run app
win.show()
QtCore.QTimer.singleShot(7 * 1000, win.close)
QtCore.QTimer.singleShot(7 * 1000, app.quit)
print("View displayed")
# While loop
app.exec_()
print("Close Application")
print("End While Loop")

Loading python module with GUI

I have a organization setup question I need help with. Here is my current folder structure.
What i want to do is run the Main UI with the specified AppCommands module that contains functions. Based on which application i want to run the tool. Is there a way using another python file, where i can load the gui and the associated app commands moduel? So when users click the button it calls the corrects app command.
So say for example I create a python file like this pseudo code
main execute py file for Photoshop
Import photoshop.appcommands as cmds
Import GUI
Gui(cmds)
How do I then tell my main GUI tool to load the photoshop modules 'AppCommands' when it runs?
app #1 code:
def runTool():
msg = 'This is Notepad'
print msg
app #2 code:
def runTool():
msg = 'This is Photoshop'
print msg
Main ui code:
import sys
import os
from PySide import QtGui, QtCore
import AppCommands as cmds
class MainWindow(QtGui.QMainWindow):
def __init__(self,parent=None):
super(MainWindow, self).__init__(parent)
self.uiButton = QtGui.QPushButton('Button', self)
# layout
grid = QtGui.QGridLayout()
grid.addWidget(self.uiButton, 3, 1)
main_widget = QtGui.QWidget()
main_widget.setLayout(grid)
self.setCentralWidget(main_widget)
self.uiButton.clicked.connect(self.browse_clicked)
# actions
def browse_clicked(self):
print 'Execute Command'
cmds.runTool()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = MainWindow()
ex.show()
sys.exit(app.exec_())
Well, if I understood correctly, you need to choose the right module to load a function after then you started the program with some variable args?
In this case you may import both and try globals:
import notepad.AppCommands
import photoshop.AppCommands
...
# in your app init code:
x = 'photoshop' # an arg passed from config/CLI or from somewhere else
actual_module = globals()[x]
actual_module.AppComands.runTools()
++ But if you just don't know how to run a certain function from a certain module, follow #eyllanesc's answer.

Qt splash screen not shown in python

I'm trying to add an splash screen to my program, coded in python 2.7 and using pyqt4 libraries. My main file is:
#!/usr/bin/env python
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from logindialog import LoginDialog
from mainwindow import MainWindow
import time
import sys
if __name__ == "__main__":
try:
app = QApplication(sys.argv)
mw = MainWindow()
# Create and display the splash screen
splash_pix = QPixmap('images/sherlock_splash.png')
splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
splash.setMask(splash_pix.mask())
# adding progress bar
progressBar = QProgressBar(splash)
# adding message
splash.showMessage('Discovering Nodes...', Qt.AlignRight | Qt.AlignBottom, Qt.darkRed)
splash.show()
app.processEvents()
for i in range(0, 100):
progressBar.setValue(i)
# Simulate something that takes time
time.sleep(0.1)
splash.close()
# Show main window
mw.show()
app.exec_()
except Exception:
sys.exit(1)
sys.exit(0)
I've coded it using Pycharm IDE. If I run it using pycharm RUN functionality the splash screen is shown up properly, however if I run it in linux command line (./main.py) it does not show up splash screen when I start my application.
Anybody could help me?
Thanks a lot!
UPDATE & FIX
...
# Create and display the splash screen
image_path = os.path.dirname(os.path.realpath(__file__))
splash_pix = QPixmap('/'.join([image_path, 'images/sherlock_splash.png']))
splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
...
Thanks!
Check your project structure and be sure if the relative path to your .png file is correct
'images/sherlock_splash.png' when running from command line.
Also add following checking
if splash_pix is not None:
...

Window is closing immediately after I run program in PyQt 4 (anaconda) [PyCharm 4.5]

So, I am trying to run a very simple program (a window) in Pycharm that is running anaconda 2.7 & PyQt4. Whenever I click the Run button it opens my program but closes the window too fast for me to even see it. May anyone, please help? Thank you!
P.S.
I'm very new to programming.
{__author__ = 'Jay'
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.show()}
You need to block the execution of the program after you call window.show() so that the window object remains active otherwise it will be garbage collected. app.exec_() does this for you.
{__author__ = 'Jay'
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window.show()
app.exec_()} # added this line

Categories