The window appears but the menu bar shows only "Python3.7", which is what
it shows if I don't create a menu bar. This is taken almost verbatim from the tutorial here. MacOS High Sierra.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QPushButton, QAction
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'Menu Bar'
self.left = 10
self.top = 10
self.width = 640
self.height = 480
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
editMenu = mainMenu.addMenu('Edit')
viewMenu = mainMenu.addMenu('View')
searchMenu = mainMenu.addMenu('Search')
toolsMenu = mainMenu.addMenu('Tools')
helpMenu = mainMenu.addMenu('Help')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Here is a screen shot of the Mac menu bar and the top left portion of the window:
Update: I found this question: I need help making a menu bar in PyQt5 about the same problem. I ran the code that worked for the OP and it worked! I'll try to find the difference between that code and mine and post again.
It's a MacOS thing. I haven't researched this issue in depth, but two things seem clear: empty menus will not display and menu items with names beginning with
"About", "Exit", "Quit", will be placed under the program menu.
Play with this under OS X:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 menu bar test'
self.initUI()
def print_change(self):
print('change')
def print_byebye(self):
print('bye bye')
def initUI(self):
self.setWindowTitle(self.title)
menubar = self.menuBar()
filemenu = menubar.addMenu('File')
""" Play with these options in Mac OS X:
confuse_me = False, False
You see a File menu with two actions "Change" and "Bye Bye" respectively
printing "change" and "bye bye". The program menu contains "Services...",
"Hide ...", "Hide Others", and "Quit ..." which exits the program.
confuse_me = True, False
The File menu contains only "Bye Bye". The "About" item appears in the program
menu and prints "change". The "Quit" item still quits.
confuse_me = False, True
The File menu containd only "Change". There is no "About" in the program menu,
and the "Quit" item prints "bye bye"
confuse_me = True, True
The program menu has "About" and "Quit" respectively printing "change" and "bye
bye". These is no File menu.
"""
confuse_me = False, False
text = "About a Boy" if confuse_me[0] else "Change"
pathaction = filemenu.addAction(text)
pathaction.triggered.connect(self.print_change)
text = "Quitting is not an Option" if confuse_me[1] else "Bye Bye"
exitaction = filemenu.addAction(text)
exitaction.triggered.connect(self.print_byebye)
if __name__ == '__main__':
app = QApplication(sys.argv)
print(sys.argv)
w = Window()
w.setGeometry(500, 300, 300, 300)
w.show()
sys.exit(app.exec_())
Related
I want switch WindowTransparentForInput statement of sub-window.
At following code, I wrote, subwindow will close instead switch the statement.
Could you please to point the problem?
import sys
from PyQt5 import QtWidgets as qtw, QtGui as qtg, QtCore as qtc
class Main(qtw.QWidget):
def __init__(self):
super().__init__()
self.mainWindow = qtw.QWidget(self)
self.mainWindow.setGeometry(100,100,200,200)
label = qtw.QLabel('Main window', self)
self.switch = qtw.QCheckBox('Transparent for input on sub window', self)
self.switch.setChecked(False)
self.switch.stateChanged.connect(self.switchAction)
mainLayout = qtw.QVBoxLayout()
self.setLayout(mainLayout)
mainLayout.addWidget(label)
mainLayout.addWidget(self.switch)
self.subwindow = qtw.QWidget()
self.subwindow.setGeometry(150,100,200,200)
sublabel = qtw.QLabel('Sub window', self.subwindow)
self.show()
self.subwindow.show()
def switchAction(self):
if self.switch.isChecked:
self.subwindow.setWindowFlags(qtc.Qt.WindowTransparentForInput | qtc.Qt.FramelessWindowHint)
else:
self.subwindow.setWindowFlags(qtc.Qt.FramelessWindowHint)
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = Main()
sys.exit(app.exec())
It was solved by modifying switchAction() as follow.
I'm sorry for your notation.
def switchAction(self):
if self.switch.isChecked():
self.subwindow.close()
self.subwindow.setWindowFlags(self.subwindow.windowFlags() | qtc.Qt.WindowTransparentForInput)
self.subwindow.show()
else:
self.subwindow.close()
self.subwindow.setWindowFlags(self.subwindow.windowFlags() & ~qtc.Qt.WindowTransparentForInput)
self.subwindow.show()
I'm trying to set a hover event on a button to open an options menu implemented as a QDialog. Everything works so far except the hovering: the menu opens when the button is pressed and disappears if any of the options is selected or the mouse is moved away from the dialog.
Now I want to open the window without clicking the button but rather by hovering over it.
I've seen PyQt5 mouse hover functions and How to detect mouse hover event in PySide6 widget but i wasn't able to make it work this way.
My code looks like this:
class ElementWidget(QWidget):
def __init__ (self, p, element):
super().__init__(p)
layout = QHBoxLayout()
label = QLabel(element)
label.setFixedSize(200,39)
self.btn = QPushButton("btn")
self.btn.clicked.connect(self._openOptionsMenu)
self.btn.setFixedSize(50,39)
layout.addWidget(label)
layout.addWidget(self.btn)
self.setLayout(layout)
self.setFixedSize(250,60)
def _openOptionsMenu(self):
self.dlg = selfClosingDialog(self.closeOptionsMenu, parent = self)
self.dlg.setLayout(ElementOptionsLayout(self.closeOptionsMenu))
self.dlg.setWindowFlag(Qt.FramelessWindowHint)
self.dlg.setGeometry(QCursor.pos().x(), QCursor.pos().y() ,100,100)
self.dlg.show()
def closeOptionsMenu(self):
self.dlg.close()
if __name__ == "__main__":
app = QApplication([])
window = QMainWindow()
window.resize(500,400)
wid = ElementWidget(window,"Parabola_0")
window.show()
app.exec_()
with the custom dialog:
class selfClosingDialog(QDialog):
def __init__(self, closeFunc, parent=None):
super().__init__(parent)
self.closeFunc = closeFunc
def leaveEvent(self, event):
self.closeFunc()
The perfect solution would be to replace the clicked-event by some kind of an onHover
I found the answer.
It is not a signal but an event enterEvent that needs to be reimplemented by a subclass of QWidget
class HoverOpenBtn(QPushButton):
def __init__(self, text, openOtionsFunc, parent=None):
super().__init__(text, parent)
self.openFunc = openOtionsFunc
def enterEvent(self, event):
self.openFunc()
I have written a small script that would display the content of a file on the desktop in a transparent window (which is also always on top window). But when I click on some other window, the focus is automatically taken up by the script's window
Below is the script:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import argparse as ap
class Window(QWidget):
def __init__(self, content, width, height):
super().__init__()
self.content = content.strip()
self.swidth = width
self.sheight = height
self.setWindowTitle("Content Display")
self.setWindowOpacity(0.1)
self.setWindowFlags(Qt.WindowTransparentForInput)
self.setWindowFlags(Qt.WindowStaysOnTopHint)
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setAttribute(Qt.WA_TransparentForMouseEvents)
self.setGeometry(0, 0, self.swidth, self.sheight)
self.text_box = QPlainTextEdit(self)
self.text_box.move(10, 10)
self.tb_width = self.width()
self.tb_height = self.height()
self.text_box.resize(self.tb_width, self.tb_height)
self.content = f"{self.content} " * 1000
self.text_box.setPlainText(self.content)
self.show()
def resizeEvent(self, event):
self.tb_width = self.width()
self.tb_height = self.height()
self.text_box.resize(self.tb_width, self.tb_height)
def keyPressEvent(self, event):
if event.key() == Qt.Key_I:
if event.modifiers() & Qt.ControlModifier:
cur_opacity = self.windowOpacity()
self.setWindowOpacity(cur_opacity + 0.05)
if event.key() == Qt.Key_D:
if event.modifiers() & Qt.ControlModifier:
cur_opacity = self.windowOpacity()
self.setWindowOpacity(cur_opacity - 0.05)
if __name__ == "__main__":
parser = ap.ArgumentParser()
parser.add_argument("-f",
"--file",
required=True,
type=str,
help="File with content")
args = parser.parse_args()
file = args.file
content = ""
try:
fd = open(file, 'r')
content = fd.read()
fd.close()
except:
print("Unable to open the content file")
sys.exit(1)
app = QApplication(sys.argv)
screen = app.primaryScreen()
size = screen.size()
rect = screen.availableGeometry()
window = Window(content, rect.width(), rect.height())
sys.exit(app.exec())
Is there a way in which the focus on the window can be ignored when clicking on another window
I searched in Google usually many posts are talking about how to open a new window and not indicating how to close the window. I found several posts in this website but most of them are using dialog window which is not considered in my software.
I make a UI, which contains a spin box and a button, to demonstrate my problem. I can type in a number equal or less than 5 in spin box. When I click the button, a number of new windows will show up and how many windows will show up is depending on the number in the spin box. If I change to the number in spin box then click the button, the original windows will be closed and new windows will be shown.
Fox example, first I type in "2" in spin box then click the button. Then 2 new windows will show up. If I change the number in spin box to 3 then click the button, the original 2 windows will be closed and 3 new windows will show up.
Here is my main program code:
from PyQt5.QtWidgets import QApplication, QMainWindow
from uitest_review import Ui_MainWindow # import the UI module
# set up a class for main window
class window(QMainWindow):
def __init__(self, parent=None):
super(window, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Open.clicked.connect(self.openwindow)
def openwindow(self):
windownum = self.ui.windownum.value()
print("open window num:", windownum)
opennewwindow = newwindow(self)
opennewwindow.show()
class newwindow(QMainWindow):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
if __name__ == "__main__":
app = QApplication([])
gui = window()
gui.show()
app.exec_()
Here is my UI code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(816, 577)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 796, 537))
self.scrollAreaWidgetContents.setObjectName(\
"scrollAreaWidgetContents")
self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
self.verticalLayout.addItem(spacerItem)
self.windownum = QtWidgets.QSpinBox(self.scrollAreaWidgetContents)
self.windownum.setMaximum(5)
self.windownum.setObjectName("windownum")
self.verticalLayout.addWidget(self.windownum)
self.groupBox = QtWidgets.QGroupBox(self.scrollAreaWidgetContents)
self.groupBox.setTitle("")
self.groupBox.setObjectName("groupBox")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.Open = QtWidgets.QPushButton(self.groupBox)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.Open.setFont(font)
self.Open.setObjectName("Open")
self.horizontalLayout.addWidget(self.Open)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem2)
self.verticalLayout.addWidget(self.groupBox)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.Open.setText(_translate("MainWindow", "Open"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I create a new class (newwindow) in my main program and I can call this class to show a new window. But I cannot figure out how to detect how many windows is opened and how to close them. Does anyone can help me? Thank you so much.
I figured out by myself.
class window(QMainWindow):
def __init__(self, parent=None):
super(window, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Open.clicked.connect(self.openwindow)
self.openedwin = []
def openwindow(self):
windownum = self.ui.windownum.value()
if windownum != 0:
if self.openedwin != []:
for window in self.openedwin:
window.close()
for repeat in range(windownum):
opennewwindow = newwindow(self)
# print("opennewwindow:", opennewwindow)
self.openedwin.append(opennewwindow)
opennewwindow.show()
# print("self.openedwin:", self.openedwin)
class newwindow(QMainWindow):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
if __name__ == "__main__":
app = QApplication([])
gui = window()
gui.show()
app.exec_()
I add a list self.openedwin = [] to save all window objects. I can use "window object".close() command to close the window before opening new one.
I am writing a program with pyqt5 where pressing a button first cycles through some pictures then cycles through some videos.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
import argparse
import sys
class MainWindow(QMainWindow):
def __init__(self,args):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = CentralWidget(args)
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
QCoreApplication.instance().quit()
self.centralwidget.startvid()
class CentralWidget(QWidget):
def __init__(self,args):
super(CentralWidget, self).__init__()
self.layout = QVBoxLayout()
self.layout.setAlignment(Qt.AlignCenter)
self.setLayout(self.layout)
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.vw = QVideoWidget()
self.player.setVideoOutput(self.vw)
def startvid(self):
self.layout.addWidget(self.vw)
url= QUrl.fromLocalFile(glob.glob("videos/*")[0])
content= QMediaContent(url)
self.player.setMedia(content)
self.player.setVideoOutput(self.vw)
self.player.play()
if __name__== "__main__":
parser = argparse.ArgumentParser()
#~ parser.add_argument("-nb","--nobox",action="store_true", help="do not wait for the box connection")
args = parser.parse_args()
app = QApplication(sys.argv)
mainwindow = MainWindow(args)
#~ mainwindow.showFullScreen()
mainwindow.show()
sys.exit(app.exec_())
I tried to paste the minimal code. The thing is, I press the button nothing shows, although I used examples like this one PyQt5 - Can't play video using QVideoWidget to test if playing the video is ok, and these work. It's as if it is not adding the widget to the layout or something. Any idea what might be wrong?
I had to use QGraphicsView to achieve what I wanted, here is a fix:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import glob
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle('Navon test')
self.setWindowFlags(Qt.FramelessWindowHint)
# exit option for the menu bar File menu
self.exit = QAction('Exit', self)
self.exit.setShortcut('Ctrl+q')
# message for the status bar if mouse is over Exit
self.exit.setStatusTip('Exit program')
# newer connect style (PySide/PyQT 4.5 and higher)
self.exit.triggered.connect(app.quit)
self.setWindowIcon(QIcon('icon.ico'))
self.centralwidget = VideoPlayer()
self.setCentralWidget(self.centralwidget)
def keyPressEvent(self, QKeyEvent):
if QKeyEvent.key() == Qt.Key_Escape:
self.centralwidget.phaseQuit(2)
self.centralwidget.play()
class VideoPlayer(QWidget):
def __init__(self, parent=None):
super(VideoPlayer, self).__init__(parent)
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
self.videoItem = QGraphicsVideoItem()
self.videoItem.setSize(QSizeF(640, 480))
scene = QGraphicsScene(self)
graphicsView = QGraphicsView(scene)
scene.addItem(self.videoItem)
layout = QVBoxLayout()
layout.addWidget(graphicsView)
self.setLayout(layout)
self.mediaPlayer.setVideoOutput(self.videoItem)
self.counter = 0
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
pass
else:
self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(glob.glob("videos/*")[self.counter])))
self.mediaPlayer.play()
self.counter += 1
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
player = MainWindow()
player.show()
sys.exit(app.exec_())