QWidgetAction doesn't show up in QMenu in tray - python-3.x

Actually, my question is the same as this question but the answer didn't help too much, tried the same but didn't work.
I want to make a slider works in the tray but what I got is a blank field only.
Is it possible to accomplish this in PyQt5? I tried a lot of things but couldn't find a solution. If it is not possible in PyQt5 then which else library can I use for this?
My code:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
QSlider,
QHBoxLayout,
QLabel,
QApplication,
QWidgetAction,
)
from PyQt5.QtCore import Qt
def change_sound(value):
print(value)
class SliderWidgetAction(QFrame):
pass
class SliderAction(QWidgetAction):
def __init__(self, label="", parent=None):
QWidgetAction.__init__(self, parent)
self._widget = SliderWidgetAction(parent)
self._label = QLabel(label, self._widget)
self._slider = QSlider(Qt.Horizontal, self._widget)
self._slider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.value_changed = self._slider.valueChanged
def widget(self):
return self._widget
def label(self):
return self._label
def slider(self):
return self._slider
def createWidget(self, menu):
"""
This method is called by the QWidgetAction base class.
"""
actionWidget = self.widget()
actionLayout = QHBoxLayout(actionWidget)
actionLayout.setContentsMargins(0, 0, 0, 0)
actionLayout.addWidget(self.label())
actionLayout.addWidget(self.slider())
actionWidget.setLayout(actionLayout)
return actionWidget
app = QApplication([])
app.setQuitOnLastWindowClosed(False)
icon = QIcon("icon.png")
tray = QSystemTrayIcon()
tray.setIcon(icon)
tray.setVisible(True)
menu = QMenu()
action = SliderAction("Test", menu)
action.slider().setMinimum(10)
action.slider().setMaximum(100)
action.slider().setValue(90)
action.slider().valueChanged.connect(change_sound)
label_widget = QLabel("Hello World")
action.setDefaultWidget(label_widget)
menu.addAction(action)
tray.setContextMenu(menu)
app.exec_()

Related

PyQt5.QIcon Is not showing any icon

I am trying to show the icon in the window bar and this is not simply working. I tried several solutions but still it doesn't work. Any solution for this code?
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.browser = QWebEngineView()
self.browser.setUrl(QUrl('http://gmail.com'))
self.setCentralWidget(self.browser)
self.showMaximized()
self.setWindowTitle('G')
self.setWindowIcon(QIcon(os.path.join('cil.png')))
self.show()
app = QApplication(sys.argv)
window = MainWindow()
app.exec_()
Try putting the icon like this
icon = QIcon()
icon.addPixmap(QtGui.QPixmap()) #add full path or respective path to the icon image inside QtGui.QPixmap()
self.setWindowIcon(icon)

How to get dockwiget splitter-handler?

I want to get handle in QDockWidget(red line show in picture),So that when handle was click, move, or mouse event and so on.I want to catch it and then do something else,But I can't find how to get it,Can someone know how to get it?
Code Sample
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class View(QMainWindow):
def __init__(self):
super().__init__()
self.addDockWidget(Qt.LeftDockWidgetArea, QDockWidget("abc", self))
self.setCentralWidget(QPushButton("ABC"))
app = QApplication([])
v = View()
v.show()
app.exec()
Below Is New Update
The view in the QDockWidget,When mouse drag handle,I want to the view always show global mini map of the scene,but use re-szie event will be very slow.So I want to get mouse-release event,then use fitInView redraw mini map.
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import random
import math
r = lambda : random.randint(0, 255)
r255 = lambda : (r(), r(), r())
class Scene(QGraphicsScene):
def __init__(self):
super().__init__()
for i in range(1000*300):
item = QGraphicsEllipseItem()
item.setRect(0, 0, r(), r())
item.setBrush(QColor(*r255()))
item.setPos(r()*100, r()*100)
self.addItem(item)
class MainView(QGraphicsView):
def wheelEvent(self, event: QWheelEvent) -> None:
factor = math.pow(2.7, event.angleDelta().y()/360)
self.scale(factor, factor)
super().wheelEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.scene = Scene()
self.main = MainView()
self.main.setDragMode(QGraphicsView.ScrollHandDrag)
self.side = QGraphicsView()
self.side.setBackgroundBrush(Qt.black)
self.main.setScene(self.scene)
self.side.setScene(self.scene)
self.setCentralWidget(self.main)
dock = QDockWidget()
dock.setWidget(self.side)
self.addDockWidget(Qt.LeftDockWidgetArea, dock)
#
dock.installEventFilter(self)
def eventFilter(self, w: 'QObject', e: 'QEvent') -> bool:
if isinstance(e, QResizeEvent):
self.side.fitInView(self.scene.itemsBoundingRect(), Qt.KeepAspectRatio)
return super().eventFilter(w, e)
app = QApplication([])
v = MainWindow()
v.show()
app.exec()

Issue in Pyqt with next and previous Pages

so I'm currently working on a little project but I have an issue and all what I've tried did not work. I have 2 files :
Page1test :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
import sys
from page2test import Page2
class Page1(QWidget):
def __init__(self):
super(Page1, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Next page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def closePage1_OpenPage2(self):
self.Open = Page2()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Page1()
window.showMaximized()
sys.exit(app.exec_())
And page2test :
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel
from Page1test import Page1
class Page2(QWidget):
def __init__(self):
super(Page2, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = Page1()
self.Open.showMaximized()
self.close()
I run the code of Page1test : empty window with just a Qpushbutton "Next Page", goal : we click on it and it open Page 2 (and close Page 1). And, when we are in Page 2, we have A Qpushbutton with "Previous Page" and when we click on it, it opens page 1, and close Page 2. Like a loop.
But, when I run the code, it returns an error :
cannot import name 'Page2' from partially initialized module 'page2test' (most likely due to a circular import)
and I have no idea how to fix it...
If someone had an idea, it would be really helpful.
So, I've finally found the solution, that was not so difficult in the end. Here it is (if it can help someone) :
Instead of making 2 files, I've done just 1 file. Here is the code :
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QWidget, QLabel, QMainWindow
import sys
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.setWindowTitle("Page 1")
label1 = QLabel(self)
label1.setText("\n PAGE 1")
self.btn_inMyApp = QPushButton ('Page suivante', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage1_OpenPage2)
self.show()
def btn1_onClicked(self):
pass
def closePage1_OpenPage2(self):
self.Open = NewApp()
self.Open.showMaximized()
self.close()
class NewApp(QMainWindow):
def __init__(self):
super(NewApp, self).__init__()
self.setWindowTitle("Test window principale")
label1 = QLabel(self)
label1.setText("\n Page2")
self.btn_inMyApp = QPushButton ('previous Page', self)
self.btn_inMyApp.setGeometry(1500,800,275,125)
self.btn_inMyApp.clicked.connect(self.closePage2_OpenPage1)
self.show()
def closePage2_OpenPage1(self):
self.Open = MyApp()
self.Open.showMaximized()
self.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.showMaximized()
sys.exit(app.exec_())
```

I am unable to get the buttons to work in GUI any solutions?

This is the code.
I am using pyCharm and python 3.7
I am able to get the GUI with all the buttons but when i click on the button it won't show in the display box until I click on the display box that is if i click on "5" it won't show in the display box until i click on the display box.
I am using MacOsCatalina.
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QPushButton
from functools import partial
__version__ = "0.1"
ERROR_MSG = "ERROR"
>The Main GUI class
class calcgui(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("calc")
self.setFixedSize(300,300)
self.generalLayout = QVBoxLayout()
self._centralWidget = QWidget(self)
self.setCentralWidget(self._centralWidget)
self._centralWidget.setLayout(self.generalLayout)
self._createDisplay()
self._createButtons()
def _createDisplay(self):
self.display = QLineEdit()
self.display.setFixedHeight(50)
self.display.setAlignment(Qt.AlignRight)
self.display.setReadOnly(True)
self.generalLayout.addWidget(self.display)
def _createButtons(self):
self.buttons = {}
buttonsLayout = QGridLayout()
buttons = {"7":(0,0),
"8":(0,1),
"9":(0,2),
"C":(0,3),
"/":(0,4),
"4":(1,0),
"5":(1,1),
"6":(1,2),
"*":(1,3),
"(":(1,4),
"1":(2,0),
"2":(2,1),
"3":(2,2),
"-":(2,3),
")":(2,4),
"0":(3,0),
"00":(3,1),
".":(3,2),
"+":(3,3),
"=":(3,4)
}
for btnText, pos in buttons.items():
self.buttons[btnText] = QPushButton(btnText)
self.buttons[btnText].setFixedSize(50,50)
buttonsLayout.addWidget(self.buttons[btnText],pos[0],pos[1])
self.generalLayout.addLayout(buttonsLayout)
def setDisplayText(self, text):
self.display.setText(text)
self.display.setFocus()
def DisplayText(self):
return self.display.text()
def clearDisplay(self):
self.setDisplayText("")
>This is the linking class
class pycalcu:
def __init__(self,model,view):
self._evaluate = model
self._view = view
self._connectSignals()
def _calculateResult(self):
result = self._evaluate(expression=self._view.DisplayText())
self._view.setDisplayText(result)
def _buildExpression(self,sub_exp):
if self._view.DisplayText() == ERROR_MSG:
self._view.clearDisplay()
expression = self._view.DisplayText() + sub_exp
self._view.setDisplayText(expression)
def _connectSignals(self):
for btnText, btn in self._view.buttons.items():
if btnText not in {"C","="}:
btn.clicked.connect(partial(self._buildExpression,btnText))
self._view.buttons["="].clicked.connect(self._calculateResult)
return self._view.display.returnPressed.connect(self._calculateResult)
self._view.buttons["C"].clicked.connect(self._view.clearDisplay)
def evaluateExpression(expression):
try:
result = str(eval(expression, {}, {}))
except Exception:
result = ERROR_MSG
return result
def main():
pycalc = QApplication(sys.argv)
view = calcgui()
view.show()
model = evaluateExpression
pycalcu(model=model,view=view)
sys.exit(pycalc.exec_())
if __name__ == "__main__":
main()
Sorry, I didn’t really delve into your program logic.
I noted the changes that I made.
Give it a try.
import sys
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QMainWindow,
QGridLayout, QVBoxLayout, QLineEdit, QPushButton)
from PyQt5.QtCore import Qt
from functools import partial
__version__ = "0.1"
ERROR_MSG = "ERROR"
# >The Main GUI class
class calcgui(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("calc")
self.setFixedSize(300,300)
self._centralWidget = QWidget(self)
self.setCentralWidget(self._centralWidget)
self.generalLayout = QVBoxLayout(self._centralWidget)
self._createDisplay()
self._createButtons()
def _createDisplay(self):
self.display = QLineEdit()
self.display.setFixedHeight(50)
self.display.setAlignment(Qt.AlignRight)
self.display.setReadOnly(True)
self.generalLayout.addWidget(self.display)
def _createButtons(self):
self.buttons = {}
buttonsLayout = QGridLayout()
buttons = {
"7":(0,0),
"8":(0,1),
"9":(0,2),
"C":(0,3),
"/":(0,4),
"4":(1,0),
"5":(1,1),
"6":(1,2),
"*":(1,3),
"(":(1,4),
"1":(2,0),
"2":(2,1),
"3":(2,2),
"-":(2,3),
")":(2,4),
"0":(3,0),
"00":(3,1),
".":(3,2),
"+":(3,3),
"=":(3,4)
}
for btnText, pos in buttons.items():
self.buttons[btnText] = QPushButton(btnText)
self.buttons[btnText].setFixedSize(50,50)
buttonsLayout.addWidget(self.buttons[btnText],pos[0],pos[1])
# <----
self.generalLayout.addLayout(buttonsLayout) # <----
def setDisplayText(self, text):
self.display.setText(text)
self.display.setFocus()
def DisplayText(self):
return self.display.text()
def clearDisplay(self):
self.setDisplayText("")
# >This is the linking class
class pycalcu:
def __init__(self,model, view):
self._evaluate = model
self._view = view
self._connectSignals()
def _calculateResult(self):
result = self._evaluate(expression=self._view.DisplayText())
self._view.setDisplayText(result)
def _buildExpression(self, sub_exp):
if self._view.DisplayText() == ERROR_MSG:
self._view.clearDisplay()
expression = self._view.DisplayText() + sub_exp
self._view.setDisplayText(expression)
def _connectSignals(self):
for btnText, btn in self._view.buttons.items():
if btnText not in {"C", "="}:
btn.clicked.connect(partial(self._buildExpression, btnText))
self._view.buttons["="].clicked.connect(self._calculateResult)
self._view.buttons["C"].clicked.connect(self._view.clearDisplay) # +++
return self._view.display.returnPressed.connect(self._calculateResult)
# ? self._view.buttons["C"].clicked.connect(self._view.clearDisplay) # ---
def evaluateExpression(expression):
try:
result = str(eval(expression, {}, {}))
except Exception:
result = ERROR_MSG
return result
def main():
pycalc = QApplication(sys.argv)
view = calcgui()
view.show()
model = evaluateExpression
pycalcu(model=model, view=view)
sys.exit(pycalc.exec_())
if __name__ == "__main__":
main()

QGraphicsview + scene + QGroupBox movement issue

For past few days I was trying to solve the issue of widget movement. At some point I tried rewriting QComboBox classes with mouse signals but that did not work. As a work around I settled for parenting my widget to a QGraphicsWidget but once I try to add another item it does not display any more and I'm not sure what to do. Here is full test script:
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import QApplication,QGraphicsItem, QGraphicsView, QGraphicsScene, QDesktopWidget, QCheckBox, QGroupBox, QPushButton, QGridLayout, QLabel, QLineEdit, QComboBox, QFont, QRadioButton, QButtonGroup, QWidget, QShortcut, QKeySequence, QIcon, QListView, QStandardItemModel, QStandardItem, QAction, QIntValidator, QListWidget, QProgressBar, QSpacerItem
from PyQt4.QtCore import QRect
from functools import partial
import sys
class node_GUI(QtGui.QWidget):
def __init__(self):
super(node_GUI, self).__init__()
class Main(QtGui.QMainWindow):
def __init__(self, *args):
super(Main, self).__init__(*args)#QtGui.QMainWindow.__init__(self)
self.init_defaults()
def init_defaults(self):
self.setGeometry(800,800,500,200)
self.lay_main = QGridLayout()
self.centralwidget = QtGui.QWidget()
self.centralwidget.setLayout(self.lay_main)
self.setCentralWidget(self.centralwidget)
btn_create_node = QPushButton("Create Node View")
btn_create_node.clicked.connect(self.create_node_view)
self.lay_main.addWidget(btn_create_node)
def showWindow(self,window):
window.show()
def printTest(self):
print "Start"
box = QGroupBox("subWidget")
box_btn = QPushButton("Test")
box_btn.clicked.connect(self.printTest)
le_edit = QLineEdit()
lay = QGridLayout()
box.setLayout(lay)
lay.addWidget(box_btn)
lay.addWidget(le_edit)
area = QtGui.QGraphicsWidget()
area.setMinimumSize(QtCore.QSizeF(400,300))
area.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
area.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
proxy = self.scene.addWidget(box)
proxy.setParentItem(area)
print "END"
def create_node_view(self):
print "creting node view"
window = node_GUI()
window.setGeometry(QRect(100, 100, 400, 200))
window.setWindowTitle("node ")
window.setObjectName("node")
show_window = QPushButton("Show Node Editor")
show_window.setObjectName("btn")
show_window.clicked.connect(partial(self.showWindow,window))
self.lay_main.addWidget(show_window)
box = QGroupBox("Widgets")
box_btn = QPushButton("Test")
box_btn.clicked.connect(self.printTest)
le_edit = QLineEdit()
lay = QGridLayout()
box.setLayout(lay)
lay.addWidget(box_btn)
lay.addWidget(le_edit)
area = QtGui.QGraphicsWidget()
area.setMinimumSize(QtCore.QSizeF(300,300))
area.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
area.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
area.setAutoFillBackground(True)
ecs = QtGui.QGraphicsEllipseItem()
ecs.setRect(QtCore.QRectF(79,79,79,79))
ecs.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
ecs.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
view = QGraphicsView()
self.scene = QGraphicsScene()
self.scene.addItem(area)
proxy = self.scene.addWidget(box)
proxy.setParentItem(area)
self.scene.addItem(ecs)
view.setScene(self.scene)
lay_window = QGridLayout()
window.setLayout(lay_window)
lay_window.addWidget(view)
def main():
app = QtGui.QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
When you click on Create Node View > Show Node Editor > Test button > a new GroupBox should appear but that does not work. Not sure why.
Right so I stopped using QGraphicsWidget() and instead I just use QGraphicsRectItem(ecs for example) once I did that change everything started to work as expected.

Resources