Affect one window with another in PYQT5 - python

I have a Main window that has a settings window that pops out. I want to be able to change one of the settings and it affects the Main window
So far I have
mainwindow.py (the function I want to run to make a frame visible)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.button_open_settings.clicked.connect
(self.open_settings)
def open_settings(self):
self.settings_window = settings.MainWindow_settings(self)
self.settings_window.show()
def set_toggle_vis(self, toggle):
self.ui.frame_toggle_list.setVisible(toggle)
settings window.py
class MainWindow_settings(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow_settings, self).__init__(*args,**kwargs)
self.ui = settings_ui.Ui_Form()
self.ui.setupUi(self)
def change_toggle(self):
toggle_enabled = 1
from mainwindow import MainWindow
MWind = MainWindow()
MWind.set_toggle_vis(toggle_enabled)
This kinda works, but it doesn't set the visibility of the frame to 1 as it would if I ran it from the mainwindow, it created a whole new main window, so now 2 are open.
How do I get it to refresh the mainwindow rather than opening a new one?

Answering my own question (with the help of musicamante)
Instead of calling the function I use pyqtSignals to send a signal
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.button_open_settings.clicked.connect
(self.open_settings)
def open_settings(self):
self.settings_window = settings.MainWindow_settings(self)
self.settings_window.toggle_submitter.connect(self.set_toggle_vis)
self.settings_window.show()
def set_toggle_vis(self, toggle):
self.ui.frame_toggle_list.setVisible(toggle)
settings window.py
class MainWindow_settings(QMainWindow):
toggle_submitter = pyqtSignal(int)
def __init__(self, *args, **kwargs):
super(MainWindow_settings, self).__init__(*args,**kwargs)
self.ui = settings_ui.Ui_Form()
self.ui.setupUi(self)
def change_toggle(self)
toggle_enabled = 1
self.toggle_submitter.emit(toggle_enabled)

Related

How can I make a button be used repeatedly to make text fields appear one by one using PyQt5

This is the current code I am using:
class Opening(QDialog):
def __init__(self):
super(Opening, self).__init__()
loadUi("reminder2.ui", self)
self.startbutton.clicked.connect(self.gotomain)
def gotomain(self):
main = MainWindow()
widget.addWidget(main)
widget.setCurrentIndex(widget.currentIndex()+1)
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("reminder.ui",self)
self.typebutton.clicked.connect(self.med)
self.searchbutton.clicked.connect(self.medd)
self.med2.hide()
self.med3.hide()
self.med4.hide()
self.med5.hide()
self.med6.hide()
self.med7.hide()
self.med8.hide()
self.addbutton.clicked.connect(self.clickAdd)
def med(self):
self.stackedWidget.setCurrentWidget(self.typemed)
def medd(self):
self.stackedWidget.setCurrentWidget(self.searchmed)
def clickAdd(self):
self.med2.show()

Dialog widgets values are not being updated in PyQt

I'm trying to send variables from a dialog back to the Main Window. However, so far I have only been able to pass the default values. My code looks like this:
class OptionsDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_Advanced_Options()
self.ui.setupUi(self)
self.ui.buttonbox_options.accepted.connect(self.Get_Data)
def Get_Data(self):
self.value = self.ui.sellingSpin.value()
return self.value
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
"""data about MainWindow"""
def get_input_data(self):
Options = OptionsDialog(self)
self.value = Options.Get_Data()
print(self.value) # this is just an example to see what variable I got
In the dialog I count with many spinboxes. Since the default value is 1, I always get 1. No matter if I had changed it before or not.

PyQT5 Nested Layouts not showing

I'm currently trying myself at PyQT5 and tried to create a custom widget which contains a nested layout with some labels.
However, when I try to run the code there are no errors thrown but the window stays blank.
What could be the problem here?
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setWindowTitle("This is a test")
devicewidget = DeviceWidget()
self.setCentralWidget(devicewidget)
class DeviceWidget(QWidget):
def __init__(self, *args, **kwargs):
super(DeviceWidget, self).__init__(*args, **kwargs)
layout = QVBoxLayout()
save_image_btn = QPushButton("Save Image")
restore_image_btn = QPushButton("Install Image")
device_size_layout = QHBoxLayout()
device_size_desc_lbl = QLabel("Space:")
device_size_lbl = QLabel("69420MB")
device_size_layout.addWidget(device_size_desc_lbl)
device_size_layout.addWidget(device_size_lbl)
layout.addWidget(save_image_btn)
layout.addWidget(save_image_btn)
layout.addLayout(device_size_layout)
#Initialization
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
Just to be clear, this is what I am currently trying to accomplish:
The solution was that I forgot to set the layout in the DeviceWidget class.
self.setLayout(layout) or layout= QVBoxLayout(self)
helped.

PyQt - Easily add a QWidget to all Views

I have the following
class MyView(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QVBoxLayout()
layout.addWidget(QLabel('Hello World'))
self.setLayout(layout)
class NavigationMenu(QWidget):
pass
# Renders a bar of full width and 15 px height
What is the easiest way to add the NavigationMenu to MyView?
In the future, I would have to also add the NavigationMenu to all other Views, so I am looking for something scalable from a typing and maintainability stand point.
I tried decorators (just #NavigationMenuDecorator on top of the class), but I either cannot bind them or they get initialized at parse time and error QWidget: Must construct a QApplication before a QWidget.
I tried just adding it into MyView, but there is a lot of boilerplate
class MyWidget(Widget.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = Widget.QVBoxLayout()
layout.addWidget(QLabel('Hello World'))
topLayout = Widget.QVBoxLayout()
topLayout.setContentsMargins(0, 0, 0, 0)
topLayout.addWidget(NavigationMenu())
topLayout.addLayout(layout)
self.setLayout(topLayout)
A possible solution is to use metaclass:
from PyQt5 import QtCore, QtWidgets
class NavigationMenu(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QLabel("NavigationMenu"))
class MetaNavigationMenu(type(QtWidgets.QWidget), type):
def __call__(cls, *args, **kw):
obj = super().__call__(*args, **kw)
lay = obj.layout()
if lay is not None:
lay.addWidget(NavigationMenu())
return obj
class View(QtWidgets.QWidget, metaclass=MetaNavigationMenu):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(QtWidgets.QLabel('Hello World'))
self.setLayout(layout)
if __name__=="__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())
Update:
With the following method you can inject the view and the additional arguments that the view requires:
from PyQt5 import QtCore, QtWidgets
class NavigationMenu(QtWidgets.QWidget):
def __init__(self, value, text="", parent=None):
super().__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QLabel(text))
print(value)
class MetaMenu(type(QtWidgets.QWidget), type):
def __new__(cls, class_name, parents, attrs, **kwargs):
cls._view = kwargs.pop('view', None)
cls._args = kwargs.pop('args', tuple())
cls._kwargs = kwargs.pop('kwargs', dict())
return type.__new__(cls, class_name, parents, attrs)
def __call__(cls, *args, **kw):
obj = super().__call__(*args, **kw)
layout = getattr(obj, 'layout', None)
if callable(layout) and View is not None:
layout().addWidget(cls._view(*cls._args, **cls._kwargs))
return obj
class View(QtWidgets.QWidget, metaclass=MetaMenu, view=NavigationMenu, args=(10, ), kwargs={"text": "NavigationMenu"}):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(QtWidgets.QLabel('Hello World'))
self.setLayout(layout)
if __name__=="__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = View()
w.show()
sys.exit(app.exec_())
The other solution here is amazing and I learned a lot about metaclasses. However, it is quite hard to read and adds unnecessary complexity. I settled for a composition-based approach, where I just extracted the boilerplate to a separate function.
The add_navigation() function wraps the old layout in a widget, creates a QVBoxLayout with the NavigationMenu and the old layout, and finally swaps the layouts.
def add_navigation(widget, title)
main = QWidget()
main.setLayout(widget.layout())
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.addWidget(NavigationBar(title))
layout.addWidget(main)
widget.setLayout(layout)
We then have just a 1-liner of boilerplate and the code then becomes.
class MyView(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
layout = QVBoxLayout()
layout.addWidget(QLabel('Hello World'))
self.setLayout(layout)
add_navigation(self, 'Navigation Title')
class NavigationMenu(QWidget):
pass
# Renders a bar of full width and 15 px height

Modify listbox from another class with pyqt

I'm doing a GUI for a database through PyQt and Python. The main window (class Window) has a listbox where I put all my data, for this example I put "The program is working". Furthermore, The other window (class AddWin) help me to add new costumers to the database, but I couldn't modify the listbox from the class Addwin. I have the following code in my program and I would like to clean the listbox from the class AddWin, can you help me? or what is my mistake in the following code?
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
#Listbox
self.lista = QtGui.QListWidget(self)
self.lista.move(155,221)
self.lista.resize(855,455)
self.lista.addItem("The program is working")
class AddWin(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
main = Window()
main.lista.clear()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Your mistake is that code doesn't instantiate AddWin anywhere, so lista.clear is never called.
Your can test it by changing
window = Window()
to
window = AddWin()
LAST EDITED 21 / 8 / 2014 12 : 42
If your want to shard QtGui.QListWidget from QtGui.QMainWindow to QtGui.QDialog, Your can use pass value by reference to QtGui.QDialog.
Assume your QtGui.QMainWindow must have QtGui.QDialog (Or AddWin);
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
#Listbox
self.lista = QtGui.QListWidget(self)
self.lista.move(155,221)
self.lista.resize(855,455)
self.lista.addItem("The program is working")
self.myAddWin = AddWin(self.lista, self) # <- Pass QListWidget to your class
class AddWin(QtGui.QDialog):
def __init__(self, refQListWidget, parent=None):
QtGui.QDialog.__init__(self, parent)
self.myRefQListWidget = refQListWidget
self.myRefQListWidget.clear()

Categories

Resources