pyside QPushButton setCheckable - python

I would like to create a QPushButton that stays pressed until the user presses it again. I know I can use setCheckable for this. But I am unsure how to create a proper signal for the button that is triggered when the button changes state, pressed and unpressed. Toggled seems to work, but it is sending 3 arguments. I am unsure what the 3 args being sent are in my example.
import maya.cmds as cmds
import os
import maya.OpenMayaUI as mui
from PySide2 import QtWidgets,QtCore,QtGui
import shiboken2
class widget():
def __init__(self):
self.objs = ["box_1","box_2","box_3"]
def label_event(self,text):
print("this is the pressed button's label", text)
def populate(self):
for obj in self.objs:
label = QtWidgets.QPushButton(obj)
label.setCheckable(True)
label.toggled.connect(partial(self.label_event, obj))
self.vertical_layout_main.addWidget(label)
def palette_ui(self):
windowName = "palette"
if cmds.window(windowName,exists = True):
cmds.deleteUI(windowName, wnd = True)
pointer = mui.MQtUtil.mainWindow()
parent = shiboken2.wrapInstance(long(pointer),QtWidgets.QWidget)
self.window = QtWidgets.QMainWindow(parent)
self.window.setObjectName(windowName)
self.window.setWindowTitle(windowName)
self.mainWidget = QtWidgets.QWidget()
self.window.setCentralWidget(self.mainWidget)
self.vertical_layout_main = QtWidgets.QVBoxLayout(self.mainWidget)
self.populate()
self.window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.window.show()
lg = widget()
lg.palette_ui()

You have to activate the property with setCheckable(True) and use the toggled signal:
import sys
from PySide import QtGui
def function(checked):
print("is checked?: ", checked)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
button = QtGui.QPushButton("press me")
button.setCheckable(True)
button.toggled.connect(function)
button.show()
sys.exit(app.exec_())
Update:
Do not use object is a reserved word, on the other hand the signal passes the parameter checked, if you want to pass another parameter you must also place it in the function:
def label_event(self, text, checked): # <---
print("this is the pressed button's label", text, checked)
def populate(self):
for obj in self.objects:
label = QtWidgets.QPushButton(obj)
label.setCheckable(True)
label.toggled.connect(partial(self.label_event, obj))
self.vertical_layout_main.addWidget(label)

Related

Open popup notification on the same monitor where the mainwindow is in python an pyqt5

In my QMainWindow i have a button which opens a new QDialog in the bottom right monitorcorner with a successmessage when i click it.
Now, if i move the QMainWindow to another monitor (i have 3 monitor) and click the button the successmessage popup appears in the monitor where the QMainWindow was opened. What i want is that the popup message appears in the monitor where my QMainWindow actually is. So if i move the QMainWindow to Monitor 1 and click the button, the successpopup should opens in monitor 1. If the QMainWindow is in monitor 2, the successpopup should open in monitor 2 an same for monitor 3.
with
screenNumber = QDesktopWidget().screenNumber(self)
i can read the screennumber where the mainwindow is. and this works fine. Evertime i click the button i read out the screennumber. But i don't found a way, to set the screennumber to my notification.
Any ideas?
Edit:
maybe it helps if i show my notify class
notes.py
from UIs.UI_notify import Ui_Notification
from PyQt5.QtWidgets import QDialog, QApplication, QDesktopWidget
from PyQt5 import QtCore
from PyQt5.QtCore import QRect, QPropertyAnimation, QTimer
import sys
class icon():
checked = "check-circle"
alert = "times-circle"
question = "question-circle"
class notify(QDialog, Ui_Notification):
def __init__(self, parent=None):
super(notify,self).__init__(parent)
self.setupUi(self)
self.setWindowFlag(QtCore.Qt.WindowType.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_TranslucentBackground)
## Some helping stuff
############################################################
parent_sSize = QDesktopWidget().screenGeometry(parent)
parent_screenNumber = QDesktopWidget().screenNumber(parent)
sSize = QDesktopWidget().screenGeometry()
screenNumber = QDesktopWidget().screenNumber()
print("notification ScreenNumber = " + str(screenNumber))
print(sSize.width())
print(sSize.height())
print("Parents ScreenNumber = " + str(parent_screenNumber))
print(parent_sSize.width())
print(parent_sSize.height())
self.Note_Exit.clicked.connect(self.close)
## ScreenSize from parent
############################################################
self.hidedPos = QRect(parent_sSize.width()-self.width()-10,
parent_sSize.height()-self.height()+200,
self.frameGeometry().width(),
self.frameGeometry().height())
self.showPos = QRect(parent_sSize.width()-self.width()-10,
parent_sSize.height()-self.height()-50,
self.frameGeometry().width(),
self.frameGeometry().height())
def setNote(self, icon=icon.checked, headline="Headline", text="Text"):
self.icon = icon
self.headline = headline
self.text = text
self.noty_Label_Icon.setText(self.icon)
self.noty_Label_Headline.setText(self.headline)
self.noty_Label_Text.setText(self.text)
self.setGeometry(self.hidedPos)
self.anim = QPropertyAnimation(self,b"geometry")
self.anim.setDuration(700)
self.anim.setEasingCurve(QtCore.QEasingCurve.OutBack)
self.anim.setEndValue(self.showPos)
self.anim.start()
self.notyTimer = QTimer()
self.notyTimer.singleShot(4000,self.hideNote)
def hideNote(self):
self.anim = QPropertyAnimation(self,b"geometry")
self.anim.setDuration(700)
self.anim.setEasingCurve(QtCore.QEasingCurve.InOutBack)
self.anim.setEndValue(self.hidedPos)
self.anim.start()
self.anim.finished.connect(self.close)
if __name__ == "__main__":
notes = QApplication(sys.argv)
dialog = notify()
dialog.show()
sys.exit(notes.exec())
You cannot use the size of the widget during its construction, as at that moment it has a default size (640x480 for top level widgets, 100x30 for widgets created with a parent, including dialogs): the only reliable option is to use the sizeHint() or ensure that the layout has been properly activated with adjustSize().
Then, you don't need the screen to get the target position, as the parent geometry will suffice, but you do need it for the start position, otherwise the dialog will "pop up" at an arbitrary point below the window. Note that QDesktopWidget is considered obsolete, and you should use QScreen instead.
Finally, since you might want to reuse the notification, the start position should be set when the popup is actually being shown, not before. The same goes for the position when hiding (in case the notification could be moved).
class Notify(QDialog, Ui_Notification):
def __init__(self, parent):
super().__init__(parent)
self.setupUi(self)
self.setWindowFlag(QtCore.Qt.WindowType.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.showAnim = QPropertyAnimation(self, b'geometry')
self.showAnim.setDuration(700)
self.showAnim.setEasingCurve(QtCore.QEasingCurve.OutBack)
self.hideAnim = QPropertyAnimation(self, b'geometry')
self.hideAnim.setDuration(700)
self.hideAnim.setEasingCurve(QtCore.QEasingCurve.InOutBack)
self.hideTimer = QTimer(self, singleShot=True)
self.hideTimer.setInterval(4000)
self.hideTimer.timeout.connect(self.hideNote)
self.showAnim.finished.connect(self.hideTimer.start)
self.hideAnim.finished.connect(self.close)
def setNote(self, icon=icon.checked, headline="Headline", text="Text"):
self.icon = icon
self.headline = headline
self.text = text
self.noty_Label_Icon.setText(self.icon)
self.noty_Label_Headline.setText(self.headline)
self.noty_Label_Text.setText(self.text)
self.adjustSize() # important!
endRect = self.rect()
center = self.parent().geometry().center()
endRect.moveCenter(center)
screen = QApplication.screenAt(center)
startRect = QRect(endRect)
startRect.moveTop(screen.geometry().bottom())
self.setGeometry(startRect)
self.showAnim.setStartValue(startRect)
self.showAnim.setEndValue(endRect)
self.showAnim.start()
self.show()
def hideNote(self):
rect = self.geometry()
self.hideAnim.setStartValue(rect)
screen = QApplication.screenAt(rect.center())
rect.moveTop(screen.geometry().bottom())
self.hideAnim.setEndValue(rect)
self.hideAnim.start()
if __name__ == "__main__":
notes = QApplication(sys.argv)
notes.setStyle('fusion')
w = QMainWindow()
b = QPushButton('click!')
w.setCentralWidget(b)
w.show()
notify = Notify(w)
b.clicked.connect(lambda: notify.setNote())
sys.exit(notes.exec())
Be aware that if you're going to create the popup every time, you should also set the WA_DeleteOnClose attribute in order to destroy it when closed, otherwise it will be kept in memory.
Note: QTimer.singleShot() is a static function, creating an instance of QTimer to use it is pointless, as that instance won't be used and a new QTimer would be created anyway.
Thank you.
In the meantime i found a solution which works for me.
Look a little dirty but works.
could you tell me, whats the difference between my code an yours?
Why should i use your code, except the fact that you are a better programmer ;-)
I set the WA_DeleteOnClose Attribute.
Good to know that. Thanks
notes.py
from UIs.UI_notify import Ui_Notification
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5 import QtCore
from PyQt5.QtCore import QRect, QPropertyAnimation, QTimer
import sys
class icon():
checked = "check-circle"
alert = "times-circle"
question = "question-circle"
clock = "clock"
class notify(QDialog, Ui_Notification):
def __init__(self, parent=None):
super(notify,self).__init__(parent)
self.setupUi(self)
self.setWindowFlag(QtCore.Qt.WindowType.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_TranslucentBackground)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
self.setWindowModality(QtCore.Qt.NonModal)
self.Note_Exit.clicked.connect(self.close)
self.parent_h = self.parent().geometry().height()
self.parent_w = self.parent().geometry().width()
self.parent_x = self.parent().geometry().x()
self.parent_y = self.parent().geometry().y()
self.dialog_w = self.width()
self.dialog_h = self.height()
self.setGeometry(self.parent_x+self.parent_w-self.dialog_w-10, self.parent_y+self.parent_h-self.dialog_h+120, self.dialog_w, self.dialog_h)
## ScreenSize from parent
############################################################
def setNote(self, icon=icon.checked, headline="Headline", text="Text"):
self.icon = icon
self.headline = headline
self.text = text
self.noty_Label_Icon.setText(self.icon)
self.noty_Label_Headline.setText(self.headline)
self.noty_Label_Text.setText(self.text)
self.anim = QPropertyAnimation(self,b"geometry")
self.anim.setDuration(700)
self.anim.setEasingCurve(QtCore.QEasingCurve.OutBack)
self.anim.setEndValue(QRect(self.parent_x+self.parent_w-self.dialog_w-10, self.parent_y+self.parent_h-self.dialog_h-20, self.dialog_w, self.dialog_h))
self.anim.start()
self.notyTimer = QTimer()
self.notyTimer.singleShot(4000,self.hideNote)
def hideNote(self):
self.anim = QPropertyAnimation(self,b"geometry")
self.anim.setDuration(700)
self.anim.setEasingCurve(QtCore.QEasingCurve.InOutBack)
self.anim.setEndValue(QRect(self.parent_x+self.parent_w-self.dialog_w-10, self.parent_y+self.parent_h-self.dialog_h+120, self.dialog_w, self.dialog_h))
self.anim.start()
self.anim.finished.connect(self.close)
if __name__ == "__main__":
notes = QApplication(sys.argv)
dialog = notify()
dialog.show()
sys.exit(notes.exec())

I want to change the sound that plays every time a button is pressed depending on a checked actiion in a QMenu

I have a QMainWindow, inside there is a QMenu, QLineEdit, and one QPushButton.
Every time I click the button, it plays a sound and then adds a text to the QLineEdit.
In my QMenu the user must be able to choose which sound plays by checking it.
I tried to achieve this by changing a variable self.s inside the MainWindow class every time a QAction is checked, meanwhile, the other QAction's are unchecked. So in my playsound() I just put the self.view.s as the argument.
But it seems that it's only reading the original self.view.s, which is the first sound. My signals to change self.view.s does not work. Also, the other QActions aren't unchecked as I wanted them to.
Below is my code:
import sys
from functools import partial
from playsound import playsound
from threading import Thread
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.buttons = {}
self.setWindowTitle("Try")
central_widget = QWidget()
self.setCentralWidget(central_widget)
self.lay = QVBoxLayout(central_widget)
self.lineedit()
button = {"HEY! ": (0, 0, 0, 0)}
page = QWidget()
layout = QGridLayout(page)
for btnText, pos in button.items():
self.buttons[btnText] = QPushButton(btnText)
layout.addWidget(self.buttons[btnText], *pos)
self.lay.addWidget(page)
self.music()
def music(self):
self.s = 'sound1.mp3'
self.x = 'sound1.mp3'
self.y = 'sound2.mp3'
self.z = 'disable.mp3'
def lineedit(self):
self.le = QLineEdit()
self.le.setFixedHeight(35)
self.lay.addWidget(self.le)
def set_lineedit(self, text):
self.le.setText(text)
self.le.setFocus()
def line(self):
return self.le.text()
class Menu:
def __init__(self, MainWindow):
super().__init__()
self.view = MainWindow
self.menuBar()
#self.actionSignals()
def menuBar(self):
self.menuBar = QMenuBar()
self.view.setMenuBar(self.menuBar)
self.menu = QMenu(self.menuBar)
self.menu.setTitle('Menu')
self.sounds = QMenu(self.menu)
self.sounds.setTitle('Select Sound')
self.sound1 = QAction(self.menuBar)
self.sound2 = QAction(self.menuBar)
self.disable = QAction(self.menuBar)
self.mute = QAction(self.menuBar)
self.mute.setText('Mute Background')
self.mute.setCheckable(True)
self.mute.setChecked(False)
self.sound1.setText('Sound 1')
self.sound1.setCheckable(True)
self.sound1.setChecked(True)
self.sound2.setText('Sound 2')
self.sound2.setCheckable(True)
self.sound2.setChecked(False)
self.disable.setText('Disable Sound')
self.disable.setCheckable(True)
self.disable.setChecked(False)
self.sounds.addAction(self.sound1)
self.sounds.addAction(self.sound2)
self.sounds.addAction(self.disable)
self.menuBar.addAction(self.menu.menuAction())
self.menu.addAction(self.mute)
self.menu.addAction(self.sounds.menuAction())
def menu_signals(self):
self.sound1.triggered.connect(self.sound_1)
self.sound2.triggered.connect(self.sound_2)
self.disable.triggered.connect(self.disabled)
def sound_1(self, checked):
if checked:
self.sound2.setChecked(False)
self.disable.setChecked(False)
self.view.s = self.view.x
else:
self.sound1.setChecked(True)
def sound_2(self, checked):
if checked:
self.sound1.setChecked(False)
self.disable.setChecked(False)
self.view.s = self.view.y
else:
self.sound2.setChecked(True)
def disabled(self, checked):
if checked:
self.sound2.setChecked(False)
self.sound1.setChecked(False)
self.view.s = self.view.z
else:
self.sound1.setChecked(True)
class Controller:
def __init__(self, MainWindow):
self.view = MainWindow
self.connectSignals()
def background(self):
while True:
playsound('background.mp3')
def playsound(self):
playsound(self.view.s, False)
def buildExpression(self, sub_exp):
expression = self.view.line() + sub_exp
self.view.set_lineedit(expression)
def connectSignals(self):
for btnText, btn in self.view.buttons.items():
self.view.buttons[btnText].clicked.connect(self.playsound)
self.view.buttons[btnText].clicked.connect(partial(self.buildExpression, btnText))
app = QApplication(sys.argv)
w = MainWindow()
x = Controller(w)
Thread(target = x.background, daemon = True).start()
m = Menu(w)
w.show()
app.exec()
I want to be able to change the value within playsound() depending on which QAction is checked in the Menu Bar. While one QAction is checked, the other QAction's should be unchecked.
This is where an action group comes into play. QActionGroup allows for mutually exclusive actions. It also provides convenient access to the selected action through the checkedAction method.
Create a QActionGroup object (e.g. self.soundGroup = QActionGroup(self))
Create your actions with the group as parent (e.g. self.sound1 = QAction(self.soundGroup))
For each of your actions, set their corresponding sound as their data, e.g. self.sound1.setData('sound1.mp3')
Ensure the action group is exclusive (I believe it's the default, but you may use self.soundGroup.setExclusive(True))
Use self.soundGroup.checkedAction() to get the checked action (selected sound) instead of self.view.s: playsound(self.soundGroup.checkedAction().data(), False)
You do not need any of your wiring between the actions and updates to self.view.s anymore. Just remove all of that.

PyQt5 QTabWidget showing currentWidget() "NoneType"

I'm building a simple browser with python, PyQt5 QWebEnjineView.
I want to make the reload button to be hidden when the page is loading and "stop loading" button visible,
When loading is finished, then reload button will be visible again and "stop loading" button will be hidden.
My QWebEnjineView is in a method called add_new_tab and I've defined QTabWidget as self.tabs in the init method.
import os
import sys
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEngineView
class mainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(mainWindow, self).__init__()
# create tabs
self.tabs = QTabWidget()
self.tabs.tabBarDoubleClicked.connect(self.tab_open_doubleclick)
self.tabs.setTabsClosable(True)
self.tabs.tabCloseRequested.connect(self.close_current_tab)
self.tabs.currentWidget().loadProgress.connect(self.loadProgressHandler)
self.tabs.currentWidget().loadFinished.connect(self.loadFinishedHandler)
self.setCentralWidget(self.tabs)
# self.setCentralWidget(self.browser)
self.showMaximized()
# nav bar
self.navbar = QToolBar()
self.navbar.setMovable(False)
self.addToolBar(self.navbar)
# Refresh button
self.reload_butn = QPushButton(self, text="Reload")
self.reload_butn.clicked.connect(self.reload_tab)
# Set reload button visible
self.reload_butn.setHidden(False)
# Stop button
self.stop_btn = QPushButton(self, text="Stop")
self.stop_btn.clicked.connect(self.stop_loading_tab)
self.stop_btn.setHidden(True)
# Set stop_butn hidden initially
self.stop_btn.setHidden(True)
# Add Refresh and Stop button
self.navbar.addWidget(self.stop_btn)
self.navbar.addWidget(self.reload_butn)
# Add Address bar
self.url_bar = QLineEdit()
self.url_bar.returnPressed.connect(self.navigate_to_url)
self.navbar.addWidget(self.url_bar)
# on startup
self.add_new_tab(QUrl("https://www.google.com/"), "Homepage")
self.show()
#QtCore.pyqtSlot(int)
def loadProgressHandler(self, prog):
self.stop_btn.setHidden(False) # When any page is loading, then stop_butn will visible
self.reload_butn.setHidden(True) # When any page is loading, then reload_butn will hidde
#QtCore.pyqtSlot()
def loadFinishedHandler(self):
self.reload_butn.setHidden(False) # When loading is finished, then reload_butn will be visible again for the user
self.stop_btn.setHidden(True) # When load finished, stop button will be hidden
# reload tab
def reload_tab(self):
self.tabs.currentWidget().reload()
def stop_loading_tab(self):
self.tabs.currentWidget().stop()
def close_current_tab(self, i):
if self.tabs.count() < 2 :
return
self.tabs.removeTab(i)
# stop load current tab
def stop_loading_tab(self):
self.tabs.currentWidget().stop()
# doubleclick on empty space for new tab
def tab_open_doubleclick(self, i):
if i == -1: # No tab under the click
self.add_new_tab(QUrl("http://www.google.com/"), label="New tab")
# function to add new tab
def add_new_tab(self, qurl=None, label="Blank"):
if qurl is None:
qurl = QUrl('https://www.google.com/')
browser = QWebEngineView()
browser.setUrl(qurl)
i = self.tabs.addTab(browser, label)
self.tabs.setCurrentIndex(i)
def navigate_to_url(self):
self.tabs.currentWidget().setUrl(QUrl(self.url_bar.text()))
app = QApplication(sys.argv)
app.setApplicationName("browser")
window = mainWindow()
app.exec_()
I have some button for reload, back, home etc. where I called self.tabs.currentWidget().reload() for example in the reload method,
But when I'm adding self.tabs.currentWidget().loadProgress.connect(self.loadProgressHandler)
for the operation, then It's giving me a error
self.tabs.currentWidget().loadProgress.connect(self.loadProgressHandler)
AttributeError: 'NoneType' object has no attribute 'loadProgress'
Can anyone tell me why is it showing that the self.tabs.currentWidget() is NoneType?
Is there a way to fix it? Ask me if you need more details
Thank you!
The cause of the error is:
self.tabs.currentWidget().loadProgress.connect(self.loadProgressHandler)
self.tabs.currentWidget().loadFinished.connect(self.loadFinishedHandler)
Where the OP is assuming that the connection will occur with all the pages, and that is incorrect since it will only occur with the current widget which in that case is None causing the error.
In this case the solution is to connect each QWebEngineView created and check in the slots if the sender() matches the currentWidget().
remove
self.tabs.currentWidget().loadProgress.connect(self.loadProgressHandler)
self.tabs.currentWidget().loadFinished.connect(self.loadFinishedHandler)
add connection:
def add_new_tab(self, qurl=None, label="Blank"):
if qurl is None:
qurl = QUrl('https://www.google.com/')
browser = QWebEngineView()
browser.loadProgress.connect(self.loadProgressHandler)
browser.loadFinished.connect(self.loadFinishedHandler)
i = self.tabs.addTab(browser, label)
self.tabs.setCurrentIndex(i)
browser.load(qurl)
Validate:
#QtCore.pyqtSlot(int)
def loadProgressHandler(self, prog):
if self.tabs.currentWidget() is not self.sender():
return
self.stop_btn.show()
self.reload_butn.hide()
#QtCore.pyqtSlot()
def loadFinishedHandler(self):
if self.tabs.currentWidget() is not self.sender():
return
self.reload_butn.show()
self.stop_btn.hide()
Update:
There are the following errors:
The visibility of the widgets added to the QToolBar are managed using the associated QActions.
Instead of managing 2 slots associated with the progress and completion of loading, only one of them should be used since, for example, the associated slot is also called when it is loaded at 100% so it could be hidden since it can be invoked together with finished.
It is better to verify that the variables that can be None to avoid exceptions.
Considering the above, the solution is:
import sys
from PyQt5.QtCore import pyqtSlot, QUrl
from PyQt5.QtWidgets import (
QApplication,
QLineEdit,
QMainWindow,
QPushButton,
QTabWidget,
QToolBar,
)
from PyQt5.QtWebEngineWidgets import QWebEngineView
class mainWindow(QMainWindow):
def __init__(self, parent=None):
super(mainWindow, self).__init__(parent)
self.tabs = QTabWidget(tabsClosable=True)
self.tabs.tabBarDoubleClicked.connect(self.tab_open_doubleclick)
self.tabs.tabCloseRequested.connect(self.close_current_tab)
self.navbar = QToolBar(movable=True)
self.addToolBar(self.navbar)
self.reload_butn = QPushButton(self, text="Reload")
self.reload_butn.clicked.connect(self.reload_tab)
self.stop_btn = QPushButton(self, text="Stop")
self.stop_btn.clicked.connect(self.stop_loading_tab)
self.url_bar = QLineEdit()
self.url_bar.returnPressed.connect(self.navigate_to_url)
self.stop_action = self.navbar.addWidget(self.stop_btn)
self.reload_action = self.navbar.addWidget(self.reload_butn)
self.navbar.addWidget(self.url_bar)
self.stop_action.setVisible(False)
self.add_new_tab(QUrl("https://www.google.com/"), "Homepage")
self.setCentralWidget(self.tabs)
self.showMaximized()
#pyqtSlot(int)
def loadProgressHandler(self, prog):
if self.tabs.currentWidget() is not self.sender():
return
loading = prog < 100
self.stop_action.setVisible(loading)
self.reload_action.setVisible(not loading)
def reload_tab(self):
self.tabs.currentWidget().reload()
def stop_loading_tab(self):
self.tabs.currentWidget().stop()
def close_current_tab(self, i):
if self.tabs.count() < 2:
return
self.tabs.removeTab(i)
def stop_loading_tab(self):
if self.tabs.currentWidget() is None:
return
self.tabs.currentWidget().stop()
def tab_open_doubleclick(self, i):
if i == -1:
self.add_new_tab(QUrl("http://www.google.com/"), label="New tab")
def add_new_tab(self, qurl=None, label="Blank"):
if qurl is None:
qurl = QUrl("https://www.google.com/")
browser = QWebEngineView()
browser.loadProgress.connect(self.loadProgressHandler)
i = self.tabs.addTab(browser, label)
self.tabs.setCurrentIndex(i)
browser.load(qurl)
def navigate_to_url(self):
if self.tabs.currentWidget() is None:
return
self.tabs.currentWidget().load(QUrl.fromString(self.url_bar.text()))
def main():
app = QApplication(sys.argv)
app.setApplicationName("browser")
window = mainWindow()
app.exec_()
if __name__ == "__main__":
main()

The PyQt button does not show up

So....I am using the PyQt lib for python to make a Graphics class which abstracts away most of the features of the QtGui class.I"ll be using it later for my other projects.This seems to be working fine,except that the button and the other widgets do not show up,although the window gets created.
import sys
from PyQt4 import QtGui
class Graphics:
def __init__(self):
self.app=QtGui.QApplication(sys.argv)
self.widgets={}
self.labels={}
self.buttons={}
def getApp(self):
return self.app
def newWidget(self,name:str):
self.widgets[name]=QtGui.QWidget()
return self.widgets[name]
def addButton(self,name:str,text:str):
self.buttons[name]=QtGui.QPushButton(text)
return self.buttons[name]
def addLabel(self,name:str,text:str):
self.labels[name]=QtGui.QLabel()
self.labels[name].setText(text)
return self.labels[name]
def start(self):
for widget in self.widgets:
self.widgets[widget].show()
sys.exit(self.app.exec_())
^ That's the code.Down below shows how i implement the class
from graphics import Graphics
gui=Graphics()
w1=gui.newWidget("hmm")
bt1=gui.addButton("hey","hello")
print(bt1)
gui.start()
It'd be great if you could provide insight as to why this is happening.Thank You
In Qt there is a basic rule: the QWidget children are drawn with respect to the parent QWidget, and if it does not have a parent this will be a window, which is called top-level.
Another concept is QPushButton, QLabel, QSpinBox, etc. are QWidgets since they inherit from this class.
So, since QPushButton does not have a parent, it should show itself as a window, and for that you should use show():
def start(self):
[w.show() for name, w in self.widgets.items()]
[button.show() for name, button in self.buttons.items()]
[label.show() for name, label in self.labels.items()]
sys.exit(self.app.exec_())
If your intention is that some QLabel or QPushButton be part of some QWidget then we must indicate that widget as parent, for example in my next solution I propose to add the name of the widget, and if the widget does not exist it should be created:
import sys
from PyQt4 import QtGui
class Graphics:
def __init__(self):
self.app=QtGui.QApplication(sys.argv)
self.widgets={}
self.labels={}
self.buttons={}
def getApp(self):
return self.app
def newWidget(self, name:str):
w = QtGui.QWidget()
self.widgets[name] = w
return w
def addButton(self, widget_name:str, name:str, text:str):
if widget_name in self.widgets:
w = self.widgets[widget_name]
else:
w = self.newWidget(widget_name)
button = QtGui.QPushButton(text, parent=w)
self.buttons[name] = button
return button
def addLabel(self, widget_name:str, name:str, text:str):
if widget_name in self.widgets:
w = self.widgets[widget_name]
else:
w = self.newWidget(widget_name)
label = QtGui.QLabel(text, parent=w)
self.labels[name] = label
return label
def start(self):
[w.show() for name, w in self.widgets.items()]
sys.exit(self.app.exec_())
If you want to add a parent after the button is created then you can use setParent():
graphics.py
import sys
from PyQt4 import QtGui
class Graphics:
def __init__(self):
self.app=QtGui.QApplication(sys.argv)
self.widgets={}
self.labels={}
self.buttons={}
def getApp(self):
return self.app
def newWidget(self, name:str):
w = QtGui.QWidget()
self.widgets[name] = w
return w
def addButton(self, name:str, text:str):
button = QtGui.QPushButton(text)
self.buttons[name] = button
return button
def addLabel(self, name:str, text:str):
label = QtGui.QLabel(text)
self.labels[name] = label
return label
def start(self):
for _, w in in self.widgets.items():
w.show()
sys.exit(self.app.exec_())
main.py
gui=Graphics()
w1 = gui.newWidget("hmm")
bt1 = gui.addButton("hey","hello")
bt1.setParent(w1) # <-- set w1 as parent of bt1
gui.start()

buttonClicked signal of QMessageBox isn't working

I would like use a Qmessagebox in order to display some info about a running computation and as a stop function when I click on the OK button.
However when I use the signal buttonClicked nothing is happenning and hte function connect with it is never called
Here a code to illustrate my issue:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SenderObject(QObject):
something_happened = pyqtSignal( )
class myfunc():
updateTime = SenderObject()
def __init__(self):
self.i = 0
self.stop = True
def run(self):
while self.stop :
self.i+=1
if self.i%100 == 0:
self.updateTime.something_happened.emit()
print('infinit loop',self.i)
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.setFixedWidth(200)
self.setFixedHeight(200)
self.wid = QWidget()
self.setCentralWidget(self.wid)
self.groups = QHBoxLayout() ####
self.Run = QPushButton('Run')
self.groups.addWidget(self.Run)
self.wid.setLayout(self.groups)
self.Run.clicked.connect(self.run)
self.myfunc = myfunc()
self.myfunc.updateTime.something_happened.connect(self.updateTime)
def run(self):
self.msg = QMessageBox()
self.msg.setText('Click Ok to stop the loop')
self.msg.setWindowTitle(" ")
self.msg.setModal(False)
self.msg.show()
self.myfunc.run()
self.msg.buttonClicked.connect(self.Okpressed)
def Okpressed(self):
self.myfunc.stop = False
#pyqtSlot( )
def updateTime(self ):
self.msg.setText('Click Ok to stop the loop\ni = '+str(self.myfunc.i))
self.parent.processEvents()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
ex.show()
sys.exit(app.exec_( ))
So theself.msg.buttonClicked.connect(self.Okpressed) line never call the function Okpressed. Therefore, myfunc.run is never stopped.
Somebody could help on this?
write
self.msg.buttonClicked.connect(self.Okpressed)
before
self.myfunc.run()
If you call run function before subscribing click event, curse will stuck into infinite while loop. so your click event never subscribed.
First subscribe click event and then call "run" function of "myfunc"
And yes never do this -
from PyQt4.QtGui import *
from PyQt4.QtCore import *
Its vbad programming practice. You can write like
from PyQt4 import QtGui
And use into code like
QtGui.QMessagebox

Categories