I'm trying to create an application that contains a web browser within it, but when I add the web browser my menu bar visually disappears but functionally remains in place. The following are two images, one showing the "self.centralWidget(self.web_widget)" commented out, and the other allows that line to run. If you run the example code, you will also see that while visually the entire web page appears as if the menu bar wasn't present, you have to click slightly below each entry field and button in order to activate it, behaving as if the menu bar was in fact present.
Web Widget Commented Out
Web Widget Active
Example Code
import os
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
class WebPage(QWebEngineView):
def __init__(self, parent=None):
QWebEngineView.__init__(self)
self.current_url = ''
self.load(QUrl("https://facebook.com"))
self.loadFinished.connect(self._on_load_finished)
def _on_load_finished(self):
print("Url Loaded")
class MainWindow(QMainWindow):
def __init__(self, parent=None):
# Initialize the Main Window
super(MainWindow, self).__init__(parent)
self.create_menu()
self.add_web_widet()
self.show()
def create_menu(self):
''' Creates the Main Menu '''
self.main_menu = self.menuBar()
self.main_menu_actions = {}
self.file_menu = self.main_menu.addMenu("Example File Menu")
self.file_menu.addAction(QAction("Testing Testing", self))
def add_web_widet(self):
self.web_widget = WebPage(self)
self.setCentralWidget(self.web_widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.showMaximized()
sys.exit(app.exec_()) # only need one app, one running event loop
Development Environment
Windows 10, PyQt5, pyqt5-5.9
EDIT
The problem doesn't seem to be directly related to the menu bar. Even removing the menu bar the issue still occurs. That said, changing from showMaximized() to showFullScreen() does seem to solve the problem.
I no longer believe this is an issue with PyQt5 specifically but rather a problem with the graphics driver. Specifically, if you look at Atlassian's HipChat application it has a similar problem which is documented here:
https://jira.atlassian.com/browse/HCPUB-3177
Some individuals were able to solve the problem by running the application from the command prompt with the addendum "--disable-gpu" but that didn't work for my python application. On the other hand, rolling back the Intel(R) HD Graphics Driver did solve my problem. Version 21.20.16.4627 is the one that seems to be causing problems.
Related
I trying to connect my pyqt6 GUI app to move between stacked widget pages based on the icons you press in the toolbar. I saw that if i use the triggered method it suppose to work but for some reason when I run my python code, I always see the app on page 2 and not my default page 1 and the icons are not triggering movement to a different page. I checked the heirarchy of the elements that I built un the GUI in QT Designer and made sure there are two separate pages, you can see in the image below:
This is the code im running currently:
import sys
from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QMainWindow
from app_try import Ui_MainWindow
class MainWindow:
def __init__(self):
self.main_win = QMainWindow()
self.ui = Ui_MainWindow()
self.ui.setupUi(self.main_win)
def show_page(self, page):
print("showPage called with page", page)
self.ui.stackedWidget.setCurrentWidget(page)
self.ui.stackedWidget.setCurrentWidget(self.ui.page)
self.ui.action_send_info.triggered(lambda: self.show_page(self.ui.page))
print("Connected action_send_info to showPage")
self.ui.action_data_table.triggered(lambda: self.show_page(self.ui.page_2))
print("Connected action_data_table to showPage")
def show(self):
self.main_win.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
sys.exit(app.exec_())
app_try is the name of my python file which I import in order to get all the elemnts of the GUI. Am I missing something that i need to add in order for the icons to move between the page? thank you for any help!
I am working on a Python project that uses Qt Designer to build interface. when working on building a plugin capability, I was able to allow dynamic loading of user plugins and create a new QMenu item to add to the main menubar. The problem is that there seems to be no way of removing that top level QMenu once it is added to the main menubar. I researched/searched quite a bit on this topic and it seems that every solution related to this topic is for removing sub-menu items from a QMenu via removing its actions, not for removing that dynamically-added QMenu itself. I hope someone would point out this to be a simple thing, and provide a code snippet to demo how this is done.
Achayan's solution above crashes on python2 qt4 (Windows) for the deletion
Better way for it is to to use the clear function.
Adding to the solution above,
def removeMenu():
self.main_menu.clear()
Hope this will give you idea for what you upto. And I took some part from another post, which is same qmenu thing
import sys
# This is bad, but Iam lazy
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.main_menu = self.menuBar()
widget = QWidget()
self.menuList = []
layout2 = QVBoxLayout(widget)
self.menuButton = QPushButton("Add Menu")
self.menuRmButton = QPushButton("Remove Menu")
layout2.addWidget(self.menuButton)
layout2.addWidget(self.menuRmButton)
self.menuButton.clicked.connect(self.create_menu)
self.menuRmButton.clicked.connect(self.removeMenu)
self.setCentralWidget(widget)
def create_menu(self):
menu2 = self.main_menu.addMenu('Menu 1')
self.menuList.append(menu2)
Action1=QAction('Menu 1 0',self)
Action1.triggered.connect(self.action_1)
menu2.addAction(Action1)
Action2=QAction('Menu 1 1',self)
Action2.triggered.connect(self.action_2)
menu2.addAction(Action2)
def removeMenu(self):
if self.menuList:
for eachMenu in self.menuList:
menuAct = eachMenu.menuAction()
self.main_menu.removeAction(menuAct)
# just for safe side
menuAct.deleteLater()
eachMenu.deleteLater()
def action_1(self):
print('Menu 1 0')
def action_2(self):
print('Menu 1 1')
if __name__ == '__main__':
app=QApplication(sys.argv)
new=MyWindow()
new.show()
app.exec_()
I need to update the existing menu items for a system tray application. At first when the app loads, there will be two menu items. Later when I click a button these menu items need to be replaced with new menu items. How can I achieve that ? Here is my code.
from PySide.QtGui import *
import sys
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.tray = QSystemTrayIcon(QApplication.style().standardIcon(QStyle.SP_DriveDVDIcon), self)
self.m = QMenu()
self.m.addAction('First')
self.m.addAction('Second')
self.tray.setContextMenu(self.m)
self.tray.show()
p = QPushButton("Click Me", self)
self.setCentralWidget(p)
p.clicked.connect(self.onClick)
def onClick(self):
self.m.clear()
self.m.addAction('First')
self.m.addAction('Third')
self.tray.setContextMenu(self.m)
app = QApplication(sys.argv)
w = MainWindow()
w.show();
sys.exit(app.exec_())
However this is not working. If I try removing self.m.clear()the new menu items will append to the existing (Which is the normal behaviour in this case). Isn't menu.clear() clears the current menu & the new menu should be populated here ?
I have seen this similar question Qt QSystemTrayIcon change menu items and the solution doesn't work for me. I am running Ubuntu 14.04.
I figured it out, the problem is due to the self.tray.setContextMenu(self.m). Remove this line from onClick method. This should work fine on Ubuntu.
I'm building a GUI with PyQt, and I'd like to make it possible to stop all the buttons doing anything while code is running. Lets say the user is copying a lot of data from a table - it would be easy for them to click another button while it is happening even if the cursor has changed to the egg timer. Any ideas or workarounds for this without going through all buttons and greying them out one by one? I'd be happy with a workaround too!
Thanks for any ideas,
Pete
You could use a modal QDialog. From the QDialog pyqt documentation:
A modal dialog is a dialog that blocks input
to other visible windows in the same application.
Also, QProgressDialog is a very convenient tool to handle blocking action in a very simple way. Here is an example :
from PyQt4 import QtGui, QtCore
from time import sleep
class Test(QtGui.QDialog):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
button = QtGui.QPushButton("Button")
hbox = QtGui.QHBoxLayout()
hbox.addWidget(button)
self.setLayout(hbox)
button.clicked.connect(self.slot)
def slot(self):
progress = QtGui.QProgressDialog(self)
progress.setWindowModality(QtCore.Qt.WindowModal)
progress.setLabel(QtGui.QLabel("Doing things..."))
progress.setAutoClose(True)
for i in range(101):
progress.setValue(i);
sleep(0.05)
if progress.wasCanceled():
break
if __name__=="__main__":
import sys
app = QtGui.QApplication(sys.argv)
myapp = Test()
myapp.show()
sys.exit(app.exec_())
I'm trying to set up an app in Linux using PyQt4 designer and I'm struggling to connect signals and slots to it. Right now all I want it to do is connect a button clicked signal to a custom slot, saveEnergyScheme which simply prints 'energy list' to the terminal.
I've translated the .ui code for my app to a python class with pyuic4 -w sumcorr.ui > sumcorr_ui.py. This created a class in the sumcorr_ui.py module called SumCorr_ui:
class SumCorr_ui(QtGui.QMainWindow, Ui_SumCorr_ui):
def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
QtGui.QMainWindow.__init__(self, parent, f)
self.setupUi(self)
I then made my app as a custom widget and tried to add a simple signal-slot connection to a button to show it works:
from PyQt4 import QtGui, QtCore
from sumcorr_ui import SumCorr_ui
class SumCorr(SumCorr_ui):
def __init__(self):
SumCorr_ui.__init__(self)
self.save_energies_button.clicked.connect(self.saveEnergyScheme)
def saveEnergyScheme(self):
print 'energyList'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
mySumCorr = QtGui.QMainWindow()
ui = SumCorr()
ui.setupUi(mySumCorr)
mySumCorr.show()
sys.exit(app.exec_())
I expect to get the line 'energy list' when I click the button named save_energies_button, but nothing happens. Could this be because I haven't built the UI as a widget, but as a main window? Why doesn't it print out??
Try to add ui.show() and you'll see that your code is creating two different windows, one should have the signal connected and one doesn't. That's because you are showing only the mySumCorr window, but you call only setupUi on it, which does not connect the signal.
When you create the SumCorr instance, you are creating a window and setting it up, then, by no reason, you do ui.setupUi(mySumCorr), which setups the mySumCorr instance without connecting the signal, and you show this last window.
I believe your code should be like this:
class SumCorr(QtGui.QMainWindow, Ui_SumCorr_ui):
def __init__(self):
SumCorr_ui.__init__(self)
self.setupUi(self)
self.save_energies_button.clicked.connect(self.saveEnergyScheme)
def saveEnergyScheme(self):
print 'energyList'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
mySumCorr = SumCorr()
mySumCorr.show()
sys.exit(app.exec_())
Note that it doesn't make any sense to have a SumCorr_ui class, that's because Qt is a UI library so you are just introducing a worthless level of abstraction. The designer file already gives you an abstraction over the ui layout.