Initiating a custom QWidget within another QWidget class' function - python

I'm new to python and pyqt. I am am trying to create a matrix of QToolButtons where upon pressing a button, a QDialog pops up for user input (more than one field).
I have a class for a button matrix object and a class for a dialog but can't seem to get a function within the button matrix class initiate an instance of the dialog class / widget.
Can anyone please advise me on what I'm doing wrong?
I have provided the code below:
from PyQt4 import QtGui
from PyQt4.QtGui import QApplication, QWidget, QFormLayout, QInputDialog, QPushButton, QToolButton, QLabel, QVBoxLayout, QHBoxLayout, QLineEdit
class Pixel(object):
def __init__(self, pixel_number, r_value, g_value, b_value):
self.pixel = pixel_number
self.red_value = r_value
self.green_value = g_value
self.blue_value = b_value
class inputdialogdemo(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
#super(inputdialogdemo, self).__init__(parent)
layout = QFormLayout()
self.btn1 = QPushButton("Enter red value")
self.le1 = QLineEdit()
self.btn1.clicked.connect(self.getRed)
layout.addRow(self.btn1,self.le1)
self.btn2= QPushButton("Enter green value")
self.le2 = QLineEdit()
self.btn2.clicked.connect(self.getGreen)
layout.addRow(self.btn1,self.le2)
self.btn3 = QPushButton("Enter blue value")
self.le3 = QLineEdit()
self.btn3.clicked.connect(self.getBlue)
layout.addRow(self.btn3,self.le3)
self.setLayout(layout)
self.setWindowTitle("RGB input dialog ")
def getRed(self):
num, ok = QInputDialog.getText(self, 'Red Input Dialog', 'Enter your name:')
if ok:
self.le1.setText(str(num))
def getGreen(self):
num,ok = QInputDialog.getInt(self,"Green input dualog","enter a number")
if ok:
self.le2.setText(str(num))
def getBlue(self):
num,ok = QInputDialog.getInt(self,"Blue input dualog","enter a number")
if ok:
self.le3.setText(str(num))
class ClusterArray(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
#self.button_layout = QHBoxLayout()
self.button_layout = QtGui.QGridLayout()
self.widget_layout = QtGui.QGridLayout()
for cluster_number in range(1, 15):
for pixel_number in range(1, 5):
button = QToolButton()
button.setText(str(cluster_number) + str(pixel_number))
button.setObjectName(f"Cluster{cluster_number},Pixel{pixel_number}")
button.released.connect(self.button_released)
self.button_layout.addWidget(button, cluster_number, pixel_number)
self.status_label = QLabel('No button clicked')
self.widget_layout.addItem(self.button_layout)
self.widget_layout.addWidget(self.status_label)
self.setLayout(self.widget_layout)
ex = inputdialogdemo()
def button_released(self):
sending_button = self.sender()
self.status_label.setText('%s Clicked!' % str(sending_button.objectName()))
ex = inputdialogdemo()
ex.show()
#i, okPressed = QInputDialog.getInt(self, "Get integer","Percentage:", 28, 0, 100, 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = ClusterArray()
widget.show()
# ex = inputdialogdemo()
# ex.show()
sys.exit(app.exec_()
At the moment I've just tried to get my class' function to create an object from some demo code in a class called 'inputdialogdemo'
Also, I would like to keep the inputted values associated with the corresponding button on the matrix somehow. I'm thinking the values should be stored in another object that each button represents. My object would be 'Pixel' that holds red, green and blue values. I have yet to code this functionality. Does this method sound feasible?

The inputdialogdemo instance is correctly created both in the __init__ and in button_released, the problem is that as soon as those function return, the ex instance gets garbage collected: since there is no persistent reference (ex is just a local variable), python automatically deletes it to avoid unnecessary memory consumption.
Since you're needing a dialog, the best solution is to inherit from QDialog instead of QWidget; this has two important benefits: it keeps the dialog modal (it stays on top of other windows and avoid interaction with them) and provides the exec_() method, which does not return until the dialog is closed; then you can add a QDialogButtonBox for standard Ok/Cancel buttons, and connect its accepted and rejected to the accept() and reject() slots of the dialog.
from PyQt4.QtGui import (QApplication, QWidget, QFormLayout, QInputDialog, QPushButton, QToolButton,
QLabel, QVBoxLayout, QHBoxLayout, QLineEdit, QDialog, QDialogButtonBox)
class inputdialogdemo(QDialog):
def __init__(self, parent = None):
# ...
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
layout.addRow(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
class ClusterArray(QWidget):
# ...
def button_released(self):
sending_button = self.sender()
self.status_label.setText('%s Clicked!' % str(sending_button.objectName()))
ex = inputdialogdemo()
if ex.exec_():
red = ex.le1.text()
green = ex.le2.text()
blue = ex.le2.text()
Some suggestions:
if you need a numerical value, don't use QLineEdit, but QSpinBox;
to add a layout to another, use setLayout(), not addItem();
to connect to a button click, use the clicked signal, not released;
while special characters are not strictly forbidden for object names, it's usually better to avoid them; also, use the object names for actual object names, not for keeping track of some properties
you can keep track of custom properties of any QObject using dynamic properties:
button.setProperty('cluster', cluster_number)
button.setProperty('pixel', pixel_number)
unless you have mandatory system requirements, you should really consider to switch to PyQt5, as PyQt4 is considered obsolete and deprecated/unsupported since 2015;
always prefer capitalized names for classes, as lower case names are normally used for variables and attributes only; read more on the
Style Guide for Python Code;

Related

Window Manager parent-children relationship weird behavior in python PyQt5

What I want to achieve in python PyQt5 is when I open the script I open a parent window automatically with a button on the middle of the screen. When I click this button a new window suppose to open, and when I close the window I can close separately the parent window and the child window. I want to be able to close the parent window first. I've done that and it works but there is a weird behavior when I open more than 10 windows sometimes when I close a window it recreates another window by itself, and sometimes one of the windows closes all of the other opened windows. How to fix this issue, the code has no errors, but it does not work as intended.
I've tried to convert the first child window to a parent window, and if all parent windows are closed the remaining child windows to become parent. This is somewhat successful, but not what I want. Here is the code:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QAction, QFileDialog
from PyQt5.QtGui import QKeySequence
from PyQt5.QtCore import Qt
class WindowManager(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.button = QPushButton("Create New Window", self)
self.button.clicked.connect(self.new_window)
self.setCentralWidget(self.button)
self.children = []
if self.parent() is not None and len(self.parent().children) > 0 and self.parent().children[0] == self:
self.is_first_child = True
else:
self.is_first_child = False
def new_window(self):
window_manager = WindowManager(self)
window_manager.resize(self.size())
window_manager.setWindowModality(Qt.NonModal)
window_manager.setWindowFlag(Qt.Window)
window_manager.create_new_window_on_close = True
self.children.append(window_manager)
window_manager.show()
def closeEvent(self, event):
if self.parent() is None:
if self.children:
if all(child.parent() is not None for child in self.children):
self.children[0].setParent(None)
self.children[0].setWindowModality(Qt.NonModal)
self.children[0].setWindowFlag(Qt.Window)
self.children[0].show()
self.children[0].children = self.children[1:]
self.close()
else:
if self in self.parent().children:
self.parent().children.remove(self)
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window_manager = WindowManager()
window_manager.show()
sys.exit(app.exec_())
Code 2 :
import sys
from random import randint
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QMenu,
QMenuBar,
QPushButton,
QVBoxLayout,
QWidget,
)
class AnotherWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.label = QLabel("Another Window % d" % randint(0, 100))
layout.addWidget(self.label)
self.setLayout(layout)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.windows1 = []
menubar = self.menuBar()
self.file_menu = menubar.addMenu("File")
self.button1 = QPushButton("New")
self.button1.clicked.connect(self.create_window1)
self.file_menu.addAction(self.button1.text(), lambda: self.create_window1())
def create_window1(self):
window = QMainWindow(None)
window.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
menubar = window.menuBar()
menubar.addMenu(self.file_menu)
self.windows1.append(window)
window.show()
def closeEvent(self, event):
event.accept()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec()
I rewrote your script to fix the bugs, but I removed some unused parts:
is_first_child flag
create_new_window_on_close flag
Unused QKeySequence, QAction and QFileDialog imports
The main problem I found about was the WindowManager.children reference which messed up in the code. From what I could understand, only the parent should contain the current reference to the children list with updated data. Whenever the parent would be closed, this updated reference should be passed into one of the children.
The main flaw was in this line:
def new_window(self):
# ... code ...
self.children.append(window_manager)
# ... code ...
You're always inserting a new child into the current's instance reference of child. That is, if you click on the child QPushButton, you're never updating the parent's children list. You're always updating the current instance one.
In short words: it got confusing. So I reworked that into using a single shared list between all instances of WindowManager. Whenever a parent window is created, it creates it's own list. Whenever a child is created, it acquires the parent's list reference.
Here's my version of your script:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
from PyQt5.QtCore import Qt
from random import randint
# Store taken indexes
taken = []
# If you're on Windows, this might not work unless you use another terminal
# application that allows ansi colors. (default windows console does not
# support it)
red = '\033[91m%s\033[0m'
green = '\033[92m%s\033[0m'
# With this we can open 1000 different windows on our testing environment
# ensuring each window contains a different index value
def uniqueIndex():
idx = randint(0, 1000)
while (idx in taken):
idx = randint(0, 1000)
taken.append(idx)
return idx
class WindowManager(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
# Get an unique identifier (only for testing)
self.index = uniqueIndex()
# If this instance is the parent, create a new shared reference.
if (parent is None):
self.children = []
# Otherwise, acquire the reference from the parent window, and add
# itself inside it.
else:
self.children = parent.children
# print on terminal that we're adding a window
print('%s %d' % (green % 'Adding: ', self.index))
# Update the window title, and add it to the shared children list
self.update_parent(parent)
self.children.append(self)
self.button = QPushButton("Create New Window", self)
self.button.clicked.connect(self.new_window)
self.setCentralWidget(self.button)
self.setMinimumWidth(300)
def new_window(self):
window_manager = WindowManager(self)
window_manager.resize(self.size())
window_manager.setWindowModality(Qt.NonModal)
window_manager.setWindowFlag(Qt.Window)
window_manager.show()
# Used just for testing.
def update_parent(self, parent=None):
if (parent is None):
self.setWindowTitle('Parent %d' % self.index)
else:
self.setWindowTitle('Parent %d: Index %d' % (parent.index, self.index))
self.setParent(parent)
def closeEvent(self, event):
# Remove the self from the shared children list
self.children.remove(self)
# print on the terminal that we're removing a window
print('%s: %d' % (red % 'Removing:', self.index))
# If the array is not empty:
if (self.children):
# Reparent all children based on the current parent (which can be None)
for child in self.children:
if (child.parent() == self):
child.update_parent(self.parent())
# set parent clears all window flags.
child.setWindowModality(Qt.NonModal)
child.setWindowFlag(Qt.Window)
# ensure the child is visible
child.show()
# Ensure we're closing the current window.
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
window_manager = WindowManager()
window_manager.show()
sys.exit(app.exec_())

PyQT5 - mix VBox and HBox Layout?

I created the following windows which generally works fine:
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout)
import sys
class Dialog(QDialog):
NumGridRows = 3
NumButtons = 4
def __init__(self):
super(Dialog, self).__init__()
self.createFormGroupBox()
self.Button1 = QPushButton(self)
self.Button1.setText("Calc")
self.Button2 = QPushButton(self)
self.Button2.setText("Reset")
# buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
# buttonBox.accepted.connect(self.accept)
# buttonBox.rejected.connect(self.reject)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.formGroupBox)
# mainLayout.addWidget(buttonBox)
mainLayout.addWidget(self.Button1)
mainLayout.addWidget(self.Button2)
self.setLayout(mainLayout)
self.setWindowTitle("Form Layout")
def createFormGroupBox(self):
self.formGroupBox = QGroupBox("Form layout")
layout = QFormLayout()
layout.addRow(QLabel("Name:"), QLineEdit())
layout.addRow(QLabel("Country:"), QComboBox())
layout.addRow(QLabel("Age:"), QSpinBox())
self.formGroupBox.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Dialog()
sys.exit(dialog.exec_())
The only thing I would like to change is that the buttons are horizontally arranged under the form layout and not vertically.
How can I achieve that to mix a vertical box with a horizontally box inside?
A Qt layout manager is a "container" of QLayoutItems, which are abstract items that represent visual objects that can be layed out.
Those items usually contain a Qt widget, but they can also be other objects, like spacers (QSpacerItem) or even other layouts (note that QLayout actually inherits from QLayoutItem).
You can actually do nested layouts.
The solution to your problem is actually pretty easy:
create a horizontal layout;
add the buttons to that layout;
add the layout to the main layout;
class Dialog(QDialog):
NumGridRows = 3
NumButtons = 4
def __init__(self):
super(Dialog, self).__init__()
self.setWindowTitle("Form Layout")
self.createFormGroupBox()
# QLayout(widget) automatically sets the layout on "widget" so you
# don't need to call widget.setLayout()
mainLayout = QVBoxLayout(self)
mainLayout.addWidget(self.formGroupBox)
self.button1 = QPushButton("Calc")
self.button2 = QPushButton("Reset")
buttonLayout = QHBoxLayout()
buttonLayout.addWidget(self.button1)
buttonLayout.addWidget(self.button2)
mainLayout.addLayout(buttonLayout)
Notes:
when widgets are going to be added to a layout, there's no point in providing the widget argument (self, in this case), as adding them to a layout that is set on a widget automatically reparents them;
only classes and constants should have capitalized names, not variables, functions or instance attributes (that's why I changed button1 and button2); remember that readability is very important, see the official Style Guide for Python Code to know more;
QDialogButtonBox is a QWidget on its own, with its internal layout; you can still use it for custom buttons, though; for instance, you could change the text of the Ok button doing buttonBox.button(buttonBox.Ok).setText("Calc"); or you could add a custom button by doing okButton = QPushButton("Calc") and buttonBox.addButton(okButton, buttonBox.AcceptRole); please carefully study the documentation to better understand the behavior of that class;

PyQt5 Application Window Not Showing

I am trying to code an application that will allow the user to view a list of Tag IDs, as well as its description, and allow the user to check off each Tag ID that they would like to import data from. At this point I am working on developing the UI only.
The code below worked and would show the application window until I added the itemChanged function & connection. Now, when I run this code, only the print statement from the new function will show. The window never shows and the entire application promptly exits (see image for outcome of running script).
Additionally, you'll notice that we get the checkState of each type of item - I only want the checkState of the Tag ID.
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLineEdit, QTableView, QHeaderView, QVBoxLayout, QAbstractItemView
from PyQt5.QtCore import Qt, QSortFilterProxyModel
from PyQt5.QtGui import QStandardItemModel, QStandardItem
class myApp(QWidget):
def __init__(self):
super().__init__()
self.resize(1000, 500)
mainLayout = QVBoxLayout()
tagIDs = ('Tag_1', 'Tag_2', 'Tag_3', 'Tag_4', 'Tag_5')
descriptions = ('Description_1', 'Description_2', 'Description_3', 'Description_4', 'Description_5')
model = QStandardItemModel(len(tagIDs), 2)
model.itemChanged.connect(self.itemChanged)
model.setHorizontalHeaderLabels(['Tag IDs', 'Description'])
for i in range(len(tagIDs)):
item1 = QStandardItem(tagIDs[i])
item1.setCheckable(True)
item2 = QStandardItem(descriptions[i])
model.setItem(i, 0, item1)
model.setItem(i, 1, item2)
filterProxyModel = QSortFilterProxyModel()
filterProxyModel.setSourceModel(model)
filterProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
filterProxyModel.setFilterKeyColumn(1)
searchField = QLineEdit()
searchField.setStyleSheet('font-size: 20px; height: 30px')
searchField.textChanged.connect(filterProxyModel.setFilterRegExp)
mainLayout.addWidget(searchField)
table = QTableView()
table.setStyleSheet('font-size: 20px;')
table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
table.setModel(filterProxyModel)
table.setEditTriggers(QAbstractItemView.NoEditTriggers)
mainLayout.addWidget(table)
self.setLayout(mainLayout)
def itemChanged(self, item):
print("Item {!r} checkState: {}".format(item.text(), item.checkState()))
def main():
app = QApplication(sys.argv)
myAppControl = myApp()
myAppControl.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Header settings that depend on the model must always be set when a model is set.
Move table.setModel(filterProxyModel) right after the creation of the table or, at least, before table.horizontalHeader().setSectionResizeMode (the vertical setSectionResizeMode() is generic for the whole header and doesn't cause problems).

QDockWidget with widgets in titlebar can't be collapsed

I have a QDockWidget and I have put some widgets on it's titlebar like in this MRE:
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QWidget, QCheckBox, QMainWindow, QLabel, QDockWidget, QApplication, QHBoxLayout,
QSizePolicy)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
central_widget = QLabel("Window stuff!")
self.setCentralWidget(central_widget)
self.dock = QDockWidget()
self.docker_layout = QHBoxLayout()
self.docker_layout.setContentsMargins(0, 0, 0, 0)
self.docker_layout.setAlignment(Qt.AlignLeft)
container = QWidget()
container.setLayout(self.docker_layout)
label = QLabel("Docker name")
label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
self.dock.setTitleBarWidget(container)
# Widgets creation:
self.docker_layout.addWidget(label)
self.check_1 = QCheckBox("Check 1")
self.docker_layout.addWidget(self.check_1)
self.check_2 = QCheckBox("Check 2", checked=True)
self.docker_layout.addWidget(self.check_2)
self.check_3 = QCheckBox("Check 3", checked=True)
self.docker_layout.addWidget(self.check_3)
self.check_4 = QCheckBox("You cant hide me haha!", checked=True)
self.docker_layout.addWidget(self.check_4)
self.dock.setTitleBarWidget(container)
self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
self.dock_content = QLabel("Dock stuff!")
self.dock.setWidget(self.dock_content)
self.show()
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
app.exec()
But as you can see in the following giph, the dock is not collapsable due to the widgets in the sidebar. How can I allow the widgets to get out of screen and resize the dock freely?
That depends by the fact that the dock widget sets the minimum width based on that of the title bar widget: if no explicit minimum width is set, then the width returned by minimumSizeHint() is used.
A possible solution is to subclass the layout and reimplement both minimumWidth() and setGeometry().
The first ensures that the title bar can be resized to a smaller width, while the second lays outs the items by ignoring the given geometry at all.
The result is, obviously, that part of the title bar will be hidden.
class IgnoreWidthLayout(QHBoxLayout):
def minimumSize(self):
return QSize(80, super().minimumSize().height())
def setGeometry(self, geometry):
geometry.setWidth(super().minimumSize().width())
super().setGeometry(geometry)
class MainWindow(QMainWindow):
def __init__(self):
# ...
self.docker_layout = IgnoreWidthLayout()
Note that:
setting the Minimum size policy on the label is not required in this situation (and you probably should need Maximum instead, consider that QSizePolicy flags have names that are unintuitive at first);
you're calling setTitleBarWidget twice;
setting the alignment on the layout has usually little use (and is almost useless in this specific case): it doesn't tell the alignment of the child items, it specifies the alignment that layout manager will have once it's set on a parent widget or added to another layout;

How to return variables from PyQt5 UI to Main function - Python

I have design a customized formlayout ui using pyqt5 and want to import variables back to the main function for further execution of the main function.
I have tried many ways to get the return values from the main function when the "OK" button has clicked but unable to get the variables from the main function.
Can you please guide me, how can i get the variables from the pyqt5 formlayout ui to main function -
Here is the Code of PyQt5 FormLayout UI function -
from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog,
QDialogButtonBox, QFormLayout, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QLineEdit, QMenu, QMenuBar, QPushButton, QSpinBox, QTextEdit,
QVBoxLayout,QCheckBox)
import sys
app = QApplication([])
class Dialog(QDialog):
def __init__(self,dinput):
super(Dialog, self).__init__()
self.createFormGroupBox(dinput)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.formGroupBox)
mainLayout.addWidget(buttonBox)
self.setLayout(mainLayout)
self.setWindowTitle("Form Layout")
def accept(self):
print(self.linedit1.text())
print(self.combox1.currentText())
print(self.spinbox1.value())
self.closeEvent()
def reject(self):
print('Cancelled')
self.closeEvent()
def getoutput(self):
return self.linedit1.text()
def createFormGroupBox(self,dinput):
self.formGroupBox = QGroupBox("Form layout")
layout = QFormLayout()
self.linedit1 = QLineEdit()
self.linedit1.setText('TestName')
layout.addRow(QLabel(dinput[0]), self.linedit1)
self.combox1 = QComboBox()
self.combox1.setToolTip('Hello')
self.combox1.addItems(['India','France','UK','USA','Germany'])
layout.addRow(QLabel(dinput[1]), self.combox1)
self.spinbox1 = QSpinBox()
layout.addRow(QLabel(dinput[2]), self.spinbox1)
self.formGroupBox.setLayout(layout)
Main Function is -
import os
import sys
import pyformlayout as pyfl
# Staring Functions for Execution
dinput = ['LastName','Country','Age']
# Call the UI and get the inputs
dialog = pyfl.Dialog(dinput)
if(dialog.exec_()):
TName = dialog.getoutput
print('------------------')
print(TName)
# Main Function Continous by getting the inputs
# from UI
I am unable to get the desired values to the output function. Even i have used the getoutput function to return the values and get the output to "TName". But i am not able to get the value into the TName variable and nothing is displaying.
The Result i am getting is - (which is basically printing the accept button function but not the TName variable which is returned to Main function.
TestName
India
25
How can i get the return values from PyQt5 Formlayout UI function to Main function..?
In the first place, FormLayout is a layout, that is, a class that is responsible for positioning the widgets within a window, so it is irrelevant for these cases. On the other hand, closeEvent() should never be invoked, that is a function that serves to handle the closed window event.
Going to the point the accept method is called when Ok is pressed, so it is the right place to get the values so it must be stored in a variable, and then returned in the get_output() method:
pyformlayout.py
import sys
from PyQt5 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
class Dialog(QtWidgets.QDialog):
def __init__(self, dinput):
super(Dialog, self).__init__()
self.createFormGroupBox(dinput)
buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
mainLayout = QtWidgets.QVBoxLayout(self)
mainLayout.addWidget(self.formGroupBox)
mainLayout.addWidget(buttonBox)
self.setWindowTitle("Form Layout")
def createFormGroupBox(self, dinput):
layout = QtWidgets.QFormLayout()
self.linedit1 = QtWidgets.QLineEdit('TestName')
self.combox1 = QtWidgets.QComboBox()
self.combox1.setToolTip('Hello')
self.combox1.addItems(['India','France','UK','USA','Germany'])
self.spinbox1 = QtWidgets.QSpinBox()
for text, w in zip(dinput, (self.linedit1, self.combox1, self.spinbox1)):
layout.addRow(text, w)
self.formGroupBox = QtWidgets.QGroupBox("Form layout")
self.formGroupBox.setLayout(layout)
def accept(self):
self._output = self.linedit1.text(), self.combox1.currentText(), self.spinbox1.value()
super(Dialog, self).accept()
def get_output(self):
return self._output
And in the file main.py I get the value if only the ok button has been pressed:
main.py
import pyformlayout as pyfl
# Staring Functions for Execution
dinput = ['LastName','Country','Age']
# Call the UI and get the inputs
dialog = pyfl.Dialog(dinput)
if dialog.exec_() == pyfl.Dialog.Accepted:
name, item, value = dialog.get_output()
print(name, item, value)

Categories

Resources