Content of QAxWidget disappears when not in focus - python

I am currently exploring the possibilities of building a GUI that can directly interact with and display PowerPoint-presentations. For that I am using Python and PyQt5 on a windows machine with PowerPoint installed. The PowerPoint-presentation is embedded inside a QAxWidget and generally works as intended.
Unfortunately there is a small but hugely annoying bug that I haven't yet found a solution for. When the focus is not set on the QAxWidget, the content disappears until I click into the QAxWidget again.
Here's a gif that showcases this by clicking into other GUI elements:
I've already learned about setFocus(), but that doesn't seem to be applicable here.
Also I've looked into a couple of Qt-development-books for Python and C++, but I haven't found a single one working with ActiveX controls and QAxWidgets. Any research material working with QAxWidgets, ActiveX, anything that might suit my needs, is also highly appreciated. Only research material I am aware of is the C++ reference and posts on forums.
With the following minimal example code and the requirements stated in the beginning, you should be able to reproduce what I've shown in the GIF:
import sys
from PyQt5.QAxContainer import QAxWidget
from PyQt5.QtCore import QEvent
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.menuBar().addMenu("&About")
self.centralwidget = QWidget(self)
self.centralwidget_vlayout = QVBoxLayout(self.centralwidget)
self.axwidget = QAxWidget(self.centralwidget)
self.axwidget.installEventFilter(self)
self.axwidget.setControl(r"C:\path\to\presentation.pptx")
self.pushbutton = QPushButton(self.centralwidget)
self.pushbutton.setText("Press me!")
self.centralwidget_vlayout.addWidget(self.axwidget)
self.centralwidget_vlayout.addWidget(self.pushbutton)
self.setCentralWidget(self.centralwidget)
self.show()
def eventFilter(self, widget: QWidget, event: QEvent):
if event.type() == QEvent.Resize and widget is self.axwidget:
self.axwidget.setFixedHeight(int(self.axwidget.width() / 16 * 9))
return super(MainWindow, self).eventFilter(widget, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
sys.exit(app.exec())
Now to the main question: How can I make sure that the PowerPoint-presentation is visible at all times, even when the focus is set to another GUI-element?

Related

PyQt6 Accessing UI Object Attributes

I'm trying to create a simple GUI in Python using PyQt6 and Qt Designer.
I've already made the .ui file, and am able to load it properly and have it shown when running the code.
I can't, however, seem able to access any of the objects, i.e buttons and such.
When I print out the children of the AppWindow object I do see all of them listed, but I can't change their attributes via self.button (inside the class init function)- it says 'unresolved attribute reference'.
To my understanding it's supposed to be something trivial, so I'm not quite sure what I had managed to get wrong here.
Would appreciate any help since I'm stumped.
Thank you.
Here's my code-
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from PyQt6.QtCore import Qt
from PyQt6 import uic
class AppWindow(QWidget):
def __init__(self):
super().__init__()
uic.loadUi('gui.ui', self)
self.setWindowTitle('API-SF App')
if __name__ == '__main__':
app = QApplication(sys.argv)
app_window = AppWindow()
app_window.show()
sys.exit(app.exec())

Stretch stopped working after parenting widget to layout pyqt

I am here with pyqt question again.
I think, this question was probably answered somewhere, but I can't phrase my problem properly in a way to find it in google, so sorry if it's duplicated the question.
I wrote simple code to show the problem I am facing.
import sys
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QApplication, QMenu, QWidget, QPushButton
class MainWindow(QDialog):
def __init__(self):
QDialog.__init__(self)
self.mainLayout = QVBoxLayout()
self.setLayout(self.mainLayout)
self.create()
def create(self):
btn_widget_a = QWidget()
btn_layout_a = QHBoxLayout(btn_widget_a)
self.mainLayout.addWidget(btn_widget_a)
btn_a = QPushButton()
btn_layout_a.addWidget(btn_a)
btn_a.setFixedSize(60, 60)
btn_b = QPushButton()
btn_layout_a.addWidget(btn_b)
btn_b.setFixedSize(60, 60)
tool_widget = QWidget()
btn_layout_a.addWidget(tool_widget)
tool_menu= QMenu(tool_widget)
tool_menu.addMenu('Options')
btn_a.setMenu(tool_menu)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
app.exec_()
Problem is this btn_layout_a.addWidget(tool_widget) when I add QMenu inside the widget in my layout, buttons don't stretch anymore when you resize your UI. Is there a way to fix it? I know that if simply delete btn_layout_a.addWidget(tool_widget) it will work properly, but thing is that unless I put it in a widget, QMenu doesn't work properly inside the software called Maya. I tried adding stretch as an argument to widget/layout and tried command addStrerch() but nothing seems to give any result. Any suggestions? Thank you!

How to implement an interactive QAction with Pyside ? (i.e. How to catch event in a QAction ?)

It might be a very simple question but I can't figure out how to do it.
The context:
I am making an application that can draw polygons in a QGraphicsScene. I would like to implement interactive actions. For example, the user clicks on a button, then clicks on the scene to draw temporary lines, finally the app cuts the polygon with the line.
What I try to achieve
What I did
Since I didn't find anything here or in the doc, I looked in the LibreCad repository to know how they do it.
https://github.com/LibreCAD/LibreCAD/blob/768285653c46e734a75460928142cda1a33c2c53/librecad/src/lib/actions/rs_actioninterface.h
Their base class inherits from QObject to handle events. It seems that they don't inherit from QAction despite line 40 where one can read "class QAction;". My C++ skills end here.
In an act of faith, I wrote the following minimal non-working example in python with PySide.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PySide2.QtCore import QObject
from PySide2.QtWidgets import (QApplication, QMainWindow, QWidget,
QGraphicsView, QGraphicsScene,
QToolBar, QAction)
class Action(QAction, QObject):
def __init__(self, name, parent=None):
super().__init__(name, parent)
# I also tried to add this, obviously I don't know what I am doing
#QObject.__init__(parent)
def keyPressEvent(self, event):
print("Event handled")
super().keyPressEvent(event)
class MainWindow(QMainWindow,):
def __init__(self):
super(MainWindow, self).__init__()
self.centralwidget = QWidget()
self.graphicsView = QGraphicsView(self.centralwidget)
self.setCentralWidget(self.centralwidget)
self.scene = QGraphicsScene(0,0,1000,1000)
self.graphicsView.setScene(self.scene)
toolbar = QToolBar("My toolbar")
self.addToolBar(toolbar)
knifeActionButton = Action("Knife", self)
knifeActionButton.setShortcut("K")
knifeActionButton.triggered.connect(self.cutPolygon)
toolbar.addAction(knifeActionButton)
def cutPolygon(self):
print("Action triggered")
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
The question:
How to handle events in a QAction to make it interactive?
Please excuse my English, I am a non-native speaker

PyQt icons missing?

I am new to PyQt and I am learning to make GUIs based on online tutorials I found. One of the examples in the tutorials uses an icon, here is the code from the tutorial:
import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
from PyQt5.QtGui import QIcon
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
exitAct = QAction(QIcon('exit24.png'), 'Exit', self)
exitAct.setShortcut('Ctrl+Q')
exitAct.triggered.connect(qApp.quit)
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAct)
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Toolbar')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
The output according to the tutorial should be
But for me it's this
As I said, I just started with PyQt and I just installed PyQt through pip
pip install PyQt5
I'm using Python3.6 and PyQt5. Any help is greatly appreciated!
Yes, PyQt5 does come with a list of default icons. You can find them here:
List of PyQt Icons
However, it seems the "exit" icon from the tutorial you refrenced used a local icon downloaded on their computer. You need to download the same icon and name it 'exit24.png' next to your python file.

Detect Ctrl+S ion QTextedit?

So, I'm making a QTextEdit that edits a text file. I got the loading and saving working fine with buttons. But I got the habit of pressing Ctrl+S to save every time I paste something into the textedit because I used that in Notepad before. So I've been trying to implement it. But I can't wrap my head around how to detect and execute my save function. Lets call it savetext.
I've been going around trying to get keyPressEvent to work, but I just don't understand how it works. So I've been pretty helpless in trying to learn it.
My heavily simplified code looks like this:
class GUI(QProcess):
def init etc...
"Button creations and connect to save/load function"
self.textedit=QTextEdit()
def savetext(self):
code
def loadtext(self):
code
Now, how do I detect a key combination being detected in the QTextEdit, or anywhere in my program for that matter, and cause it to do savetext? In my case, Ctrl+S, though I'd just love a general explanation so I could apply it to any combo.
Use QShortcut and QKeySequence
from PyQt5.QtWidgets import QApplication, QTextEdit, QShortcut
from PyQt5.QtGui import QKeySequence
import sys
def slot():
print("Ctrl+S")
app = QApplication(sys.argv)
textedit=QTextEdit()
shortcut = QShortcut(QKeySequence("Ctrl+S"), textedit)
shortcut.activated.connect(slot)
textedit.show()
sys.exit(app.exec_())
You can probably use QShortcut, and right now it will activate only when textedit in focus. If you want to change the behavior please take a look here
Here is a example
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
layout = QtGui.QVBoxLayout(self)
self.edit = QtGui.QTextEdit()
layout.addWidget(self.edit)
self.button = QtGui.QPushButton('Test')
layout.addWidget(self.button)
foo = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+S"), self.edit, self.saveCall, context=QtCore.Qt.WidgetShortcut)
def saveCall(self):
self.edit.append('Please save me')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec_())

Categories

Resources