My code is supposed to add data to a two column table when "add" button is clicked. The problem is that when the "add" button is clicked, only the empty row is being added. Can someone please let me know what is wrong? Below is the part of the code that adds data1 and data2 to a table on the right side of the layout. The function add_entry is where the data is being added.
# Import dependencies
from PyQt5.QtWidgets import (QWidget, QApplication, QTableWidget, QTableWidgetItem,QHBoxLayout, QVBoxLayout, QHeaderView, QPushButton, QDialog,
QLabel, QFileDialog, QMainWindow, QAction, QLineEdit)
from PyQt5.Qt import Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtChart import QChart, QChartView, QLineSeries
import sys
import pandas as pd
import math
# ------------------------------------------------------UI-main----------------------------------------------------------------------------------
# Creates a QApplication instance
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.items=0
# Creates table on the left size
self.table_l = QTableWidget()
self.table_l.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# Creates layout object for the right side
self.layoutRight = QVBoxLayout()
# Creates chart widget
self.chartView = QChartView()
# Smooths the edge of the chart
self.chartView.setRenderHint(QPainter.Antialiasing)
# Creates table on the right size
self.table_r = QTableWidget()
self.table_r.setColumnCount(2)
# self.table_r.setRowCount()
self.table_r.setHorizontalHeaderLabels(('Data1', 'Data2'))
self.table_r.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.table_r.setMaximumSize(600, 300)
self.lineEditData1 = QLineEdit()
self.lineEditData2 = QLineEdit()
# Create push buttons
self.buttonAdd = QPushButton('Add')
self.buttonClear = QPushButton('Clear')
self.buttonQuit = QPushButton('Quit')
self.buttonAdd.setEnabled(False)
self.layoutRight.setSpacing(10)
self.layoutRight.addWidget(self.table_r, 50)
self.layoutRight.addWidget(QLabel('data1'))
self.layoutRight.addWidget(self.lineEditData1)
self.layoutRight.addWidget(QLabel('data2'))
self.layoutRight.addWidget(self.lineEditData2)
self.layoutRight.addWidget(self.buttonAdd)
self.layout = QHBoxLayout()
self.layout.addWidget(self.table_l, 50)
self.setLayout(self.layout)
self.layout.addLayout(self.layoutRight, 50)
# Connect button to function functions
self.buttonQuit.clicked.connect(lambda:app.quit())
self.buttonAdd.clicked.connect(self.add_entry)
self.buttonClear.clicked.connect(self.reset_table)
self.lineEditData1.textChanged[str].connect(self.check_disable)
self.lineEditData2.textChanged[str].connect(self.check_disable)
def add_entry(self):
Data1 = self.lineEditData1.text()
Data2 = self.lineEditData2.text()
try:
Data1Item = QTableWidgetItem(int(Data1))
Data2Item = QTableWidgetItem(float(Data2))
Data2Item.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)
self.table_r.insertRow(self.items)
self.table_r.setItem(self.items, 0, Data1Item)
self.table_r.setItem(self.items, 1, Data2Item)
self.items +=1
# after passing the item, clear the field by entering an empty string
self.lineEditData1.setText('')
self.lineEditData2.setText('')
except ValueError:
pass
# Creates main window object instance
class MainWindow(QMainWindow):
def __init__(self, widget):
super().__init__()
self.setWindowTitle('test')
self.resize(1200, 1200)
self.menuBar = self.menuBar()
self.fileMenu = self.menuBar.addMenu('File')
# import wind speed data
importAction = QAction('Open File', self)
importAction.setShortcut('Ctrl+O')
# exit action
exitAction = QAction('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(lambda: app.quit())
self.fileMenu.addAction(importAction)
self.fileMenu.addAction(exitAction)
self.setCentralWidget(widget)
if __name__ =='__main__':
# don't auto scale when drag app to a different monitor
#QGuiApplication.setHightDpiScaleFactorRoundingPolicy(Qt.HightDpiScaleFactorRoundingPolicy.PassThrough)
app = QApplication(sys.argv)
w = MyApp()
demo = MainWindow(w)
demo.show()
try:
sys.exit(app.exec())
except SystemExit:
print('Closing window...')
The objective of exceptions is not to hide errors but to know how to prevent them, so they must be as small as possible so as not to hide other errors. In this case, QTableWidgetItem accepts a string as an argument and not numerical values, therefore an exception is thrown preventing the code that adds the items from being executed. The solution is to use the setData() method of the QTableWidgetItem:
def add_entry(self):
data1 = self.lineEditData1.text()
data2 = self.lineEditData2.text()
try:
value1 = int(data1)
value2 = float(data2)
except ValueError:
print("failed conversion")
return
else:
data1_item = QTableWidgetItem()
data1_item.setData(Qt.DisplayRole, value1)
data2_item = QTableWidgetItem()
data2_item.setData(Qt.DisplayRole, value2)
data2_item.setTextAlignment(Qt.AlignRight | Qt.AlignCenter)
row = self.table_r.rowCount()
self.table_r.insertRow(row)
self.table_r.setItem(row, 0, data1_item)
self.table_r.setItem(row, 1, data2_item)
self.lineEditData1.clear()
self.lineEditData2.clear()
Related
the below example is my problem which can not figure it out! i appreciate if anyone can help on this problem. i have set of data which in this example i am reading from csv file. in next step i am filling my QTableWidget with the data. The problem is when i change data and close the tab and open it, the data does not refresh.
here is my sample code:
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QVBoxLayout
from PyQt5.QtWidgets import QAction, QTabWidget, QTableWidget, QTableWidgetItem
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 400, 400)
self.setup_ui()
self.show()
def setup_ui(self):
# toolbar
self.toolbar = self.addToolBar('Tool Bar')
self.test_btn = QAction('Test', self)
self.toolbar.addAction(self.test_btn)
self.test_btn.triggered.connect(self.load_data)
# tab
self.tabs = QTabWidget()
self.tab_test = QWidget()
self.tabs.setTabsClosable(True)
self.tabs.tabCloseRequested.connect(lambda tab_index: self.tabs.removeTab(tab_index))
self.setCentralWidget(self.tabs)
def load_data(self):
# get data
data = []
with open('test_data.csv', 'r') as f:
header = next(f).replace('\n', '').split(',')
for line in f:
data.append(line.replace('\n', '').split(','))
print(data)
# table and button widget
self.layout = QVBoxLayout()
self.tabs.addTab(self.tab_test, 'Test')
self.table = QTableWidget()
self.layout.addWidget(self.table)
self.tab_test.setLayout(self.layout)
# fill headers
self.table.setColumnCount(len(header))
for i, field_name in enumerate(header):
self.table.setHorizontalHeaderItem(i, QTableWidgetItem(field_name))
# fill data
for row, row_data in enumerate(data):
self.table.insertRow(row)
for col, data in enumerate(row_data):
self.table.setItem(row, col, QTableWidgetItem(str(data)))
def main():
app = QApplication([])
ui = MainWindow()
app.exec_()
if __name__ == '__main__':
main()
and this is the sample data for test_data.csv:
col_1,col_2
1,2
10,20
100,200
before updating data:
but after updating 100 to 1000 and 200 to 2000 in csv file then closing tab and opening it, the data has been updated but the items of table not!
what am i missing?
You're assigning a single QWidget instance at MainWindow.setup_ui, right here:
def setup_ui(self):
# toolbar
self.toolbar = self.addToolBar('Tool Bar')
self.test_btn = QAction('Test', self)
# .
# .
# tab
self.tabs = QTabWidget() # <--
# .
# .
# .
self.setCentralWidget(self.tabs)
This means that you're always adding the same QWidget over and over to the QTabWidget. So, when you call MainWindow.load_data, this function call self.tabs.addTab(tab_test, 'Test') does nothing, because the widget is already present on the table widget.
What you should do, is to create a new QWidget inside MainWindow.load_data, just like this:
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QVBoxLayout
from PyQt5.QtWidgets import QAction, QTabWidget, QTableWidget, QTableWidgetItem
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 400, 400)
self.setup_ui()
self.show()
def setup_ui(self):
# toolbar
toolbar = self.addToolBar('Tool Bar')
test_btn = QAction('Test', self)
toolbar.addAction(test_btn)
test_btn.triggered.connect(self.load_data)
# tab
self.tabs = QTabWidget()
self.tabs.setTabsClosable(True)
self.tabs.tabCloseRequested.connect(lambda tab_index: self.tabs.removeTab(tab_index))
self.setCentralWidget(self.tabs)
def load_data(self):
# get data
data = []
with open('test_data.csv', 'r') as f:
header = next(f).replace('\n', '').split(',')
for line in f:
data.append(line.replace('\n', '').split(','))
print(data)
# table and button widget
layout = QVBoxLayout()
tab_test = QWidget() ## MOVED THIS LINE FROM setup_ui
self.tabs.addTab(tab_test, 'Test')
table = QTableWidget()
layout.addWidget(table)
tab_test.setLayout(layout)
# fill headers
table.setColumnCount(len(header))
for i, field_name in enumerate(header):
table.setHorizontalHeaderItem(i, QTableWidgetItem(field_name))
# fill data
for row, row_data in enumerate(data):
table.insertRow(row)
for col, data in enumerate(row_data):
table.setItem(row, col, QTableWidgetItem(str(data)))
def main():
app = QApplication([])
ui = MainWindow()
app.exec_()
if __name__ == '__main__':
main()
Note that I used local variables on setup_ui and load_data scopes. As most variables in there are not being used in other MainWindow methods, it's not needed to store them to self, unlike self.tabs. Also, as every tab should be independent of each other, it's not a good thing to overwrite the self.test_tab variable, unless you do need to store only the last added tab.
I have a complex program in which I need to connect multiple windows. Unfortunately, I seem to be not fully understanding the concept/steps necessary to do this so bonus points if anyone can explain the steps/process well. In my current program, I have a list of items. Once I select them by moving them over to the right list widget, I need them to go to the third window. The third window should be activated by clicking the dots on the second window. The program runs and shows the second window appropriately but the signal/slot connection of the dots button does not work. However, the rest of the code is working because if I switch the toolkit to show the third window, that part is performing as expected. My code is below, and again, no errors are being returned, but clicking the dots button on the second window does nothing.
Also, a question - do I instantiate the third window within the second class, or only within the main window? Again, struggling to fully understand the process and I will need to do this multiple more times.
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QListWidget, QLineEdit, QTextEdit, QGridLayout, QHBoxLayout, QVBoxLayout, QSizePolicy, QFileDialog, QTabWidget, QCheckBox
import PyQt5.QtGui as qtg
import glob
import os
from PyQt5.QtCore import Qt, QSettings
import inspect
from PyQt5 import QtCore
import pandas as pd
import pathlib
import pyreadstat
import json
class ThirdWindow(QWidget):
def __init__(self):
super().__init__()
self.layout = QGridLayout()
self.setLayout(self.layout)
self.allVariables = QListWidget()
self.variablesSelected = QListWidget()
#self.allVariables.insertItem(0, 'Hello')
self.layout.addWidget(self.allVariables, 1,0)
self.layout.addWidget(self.variablesSelected, 1, 1)
def setItems(self, items):
self.allVariables.clear()
for item in items:
self.allVariables.addItem(item)
class SecondWindow(QWidget):
def __init__(self):
super().__init__()
##not sure if I am supposed to instantiate this here or only in the main window class
self.thirdWindow = ThirdWindow()
self.layout = QGridLayout(self)
self.by = QLabel("By")
self.byVariables = QLineEdit()
self.byButton = QPushButton("...")
self.layout.addWidget(self.by, 1, 0)
self.layout.addWidget(self.byVariables, 2, 0)
self.layout.addWidget(self.byButton, 2, 1)
def seconddWindowConnections(self):
self.byButton.clicked.connect(self.show_third_window)
#self.buttons['Toolkit'].clicked.connect(self.show_new_window)
def show_third_window(self):
self.thirdWindow.show()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
# Add a title
self.setWindowTitle("GUI Querying Program")
self.layout = QHBoxLayout()
self.setLayout(self.layout)
self.initUI()
self.setButtonConnections()
self.sw = SecondWindow()
self.tw = ThirdWindow()
def initUI(self):
subLayouts = {}
subLayouts['LeftColumn'] = QGridLayout()
self.layout.addLayout(subLayouts['LeftColumn'],1)
# Buttons
self.buttons = {}
self.buttons['addVariable'] = QPushButton('>')
self.buttons['removeVariable'] = QPushButton('<')
self.buttons['Toolkit'] = QPushButton('Toolkit')
self.variables = QListWidget()
self.selectedVariables = QListWidget()
subLayouts['LeftColumn'].addWidget(self.variables, 7,0,4,1)
subLayouts['LeftColumn'].addWidget(self.selectedVariables, 7,1,4,1)
subLayouts['LeftColumn'].addWidget(self.buttons['addVariable'], 10,0,1,1)
subLayouts['LeftColumn'].addWidget(self.buttons['removeVariable'], 10,1,1,1)
subLayouts['LeftColumn'].addWidget(self.buttons['Toolkit'], 11,1,1,1)
names = ['apple', 'banana', 'Cherry']
self.variables.insertItems(0, names)
def setButtonConnections(self):
self.buttons['addVariable'].clicked.connect(self.add_variable)
self.buttons['Toolkit'].clicked.connect(self.show_new_window)
self.buttons['Toolkit'].clicked.connect(self.add_selected_variables)
def add_variable(self):
for item in self.variables.selectedItems():
self.selectedVariables.addItem(item.clone())
def show_new_window(self):
self.sw.show()
def add_selected_variables(self):
items = []
for i in range(self.selectedVariables.count()):
items.append(self.selectedVariables.item(i).clone())
self.tw.setItems(items)
if __name__ == "__main__":
import sys
app = QApplication([])
mw = MainWindow()
mw.show()
app.exec()
The main issue with your code is that secondWindowConnections is never called so the button actually does nothing. I corrected that and fixed a few other issues I found in my example below. I left out the bits where I made no changes and all the changes I did make I made inline notes explaining them:
class SecondWindow(QWidget):
def __init__(self):
super().__init__()
self.thirdWindow = None # dont initialize until neccessary
self.thirdWindowItems = []
self.layout = QGridLayout(self)
self.by = QLabel("By")
self.byVariables = QLineEdit()
self.byButton = QPushButton("...")
self.layout.addWidget(self.by, 1, 0)
self.layout.addWidget(self.byVariables, 2, 0)
self.layout.addWidget(self.byButton, 2, 1)
self.secondWindowConnections() # Run this to setup the
# signal for the third window.
def secondWindowConnections(self): # this had a typo
self.byButton.clicked.connect(self.show_third_window)
def show_third_window(self):
if self.thirdWindow is None: # if window has been created yet
self.thirdWindow = ThirdWindow() # create window
if not self.thirdWindow.isVisible(): # if window is showing
self.thirdWindow.show() # show window
self.thirdWindow.setItems(self.thirdWindowItems) # send items to window
def send_items(self, items): # this is to collect the variable that
self.thirdWindowItems = items # move to the third window
class MainWindow(QWidget):
def __init__(self):
super().__init__()
# Add a title
self.setWindowTitle("GUI Querying Program")
self.layout = QHBoxLayout()
self.setLayout(self.layout)
self.initUI()
self.setButtonConnections()
self.sw = None # dont initialize until neccessary.
def initUI(self):
subLayouts = {}
subLayouts['LeftColumn'] = QGridLayout()
self.layout.addLayout(subLayouts['LeftColumn'],1)
self.buttons = {}
self.buttons['addVariable'] = QPushButton('>')
self.buttons['removeVariable'] = QPushButton('<')
self.buttons['Toolkit'] = QPushButton('Toolkit')
self.variables = QListWidget()
self.selectedVariables = QListWidget()
subLayouts['LeftColumn'].addWidget(self.variables, 7,0,4,1)
subLayouts['LeftColumn'].addWidget(self.selectedVariables, 7,1,4,1)
subLayouts['LeftColumn'].addWidget(self.buttons['addVariable'], 10,0,1,1)
subLayouts['LeftColumn'].addWidget(self.buttons['removeVariable'], 10,1,1,1)
subLayouts['LeftColumn'].addWidget(self.buttons['Toolkit'], 11,1,1,1)
names = ['apple', 'banana', 'Cherry']
self.variables.insertItems(0, names)
def setButtonConnections(self):
self.buttons['addVariable'].clicked.connect(self.add_variable)
self.buttons['Toolkit'].clicked.connect(self.show_new_window)
# self.buttons['Toolkit'].clicked.connect(self.add_selected_variables)
# only use one connnect slot
def add_variable(self):
for item in self.variables.selectedItems():
self.selectedVariables.addItem(item.clone())
def show_new_window(self):
if self.sw is None: # check if window has been constructed
self.sw = SecondWindow() # construct window
if not self.sw.isVisible(): # If winow is not showing
self.sw.show() # show window
self.sw.send_items(self.add_selected_variables()) # send selected
# variables to second window
def add_selected_variables(self):
items = []
for i in range(self.selectedVariables.count()):
items.append(self.selectedVariables.item(i).clone())
# self.tw.setItems(items) ... self.tw doesnt exist so return them
return items
I need to have ability to create endless widgets by .addWidget (in grid, new widget - new row). I already have it. But im also need ability to delete widgets by his position. I tried this:
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QTime, QTimer, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication, QLCDNumber, QPushButton, QGridLayout, QLabel, QLineEdit, QTextEdit, QGroupBox
import sys
from somethingtestui import Ui_MainWindow
global selection
selection = 1
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.add)
def add(self):
global selection
self.row = QTextEdit('')
self.text3 = QPushButton('Delete row')
self.ui.gridLayout.addWidget(self.row, selection, 0, 1, 1)
self.ui.gridLayout.addWidget(self.text3, selection, 1, 1, 1)
# global delf
def delf():
global selection
selection = selection-1
number = self.ui.gridLayout.itemAtPosition(selection,1)
print(number)
self.row.deleteLater()
self.rrow = None
self.text3.deleteLater()
self.text3 = None
self.text3.clicked.connect(delf)
selection = selection+1
app = QtWidgets.QApplication([])
application = mywindow()
application.show()
sys.exit(app.exec())
With it i can add many widgets. If there are one created widget i am free to delete it and repeat it. But if there are 2 or more created widget i can delete one of them, and after click button "Delete" in the other row it crash:
Traceback (most recent call last):
File "E:\Programs\YandexDisk\Tempfiles\TournamentBot\testi22.py", line 31, in delf
self.row.deleteLater()
RuntimeError: wrapped C/C++ object of type QTextEdit has been deleted
I found solution for myself
from somethingtestui import Ui_MainWindow
global rowcnt
rowcnt = 1
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.add)
self.ui.gridLayout.setRowMinimumHeight(50,50)
self.ui.gridLayout.setColumnMinimumWidth(50,50)
def add(self):
global rowcnt
self.row = QTextEdit('')
self.delbtn = QPushButton('Delete row')
self.ui.gridLayout.addWidget(self.row, rowcnt, 0, 1, 1)
self.ui.gridLayout.addWidget(self.delbtn, rowcnt, 1, 1, 1)
w = self.ui.gridLayout.itemAtPosition(rowcnt,1).widget()
def delf(currow):
global rowcnt
rowcnt = rowcnt-1
number = self.ui.gridLayout.itemAtPosition(currow,1).widget()
number2 = self.ui.gridLayout.itemAtPosition(currow,0).widget()
number.deleteLater()
number2.deleteLater()
w.clicked.connect(lambda: delf(mrowcnt))
rowcnt = rowcnt+1
mrowcnt = rowcnt-1
I need to get the table row index during a contextMenuEvent in pyQt5, but I keep getting odd row offsets. Since this is my first pyQt project, I'm quite lost. I have the following code.
def contextMenuEvent(self, event):
menu = QMenu(self)
openAction = menu.addAction('Open in browser')
action = menu.exec_(event.globalPos())
if action == openAction:
row = self.tableWidget.rowAt(event.y()) # Should this be event.globalY?
self.so_something(row)
Edit: adding code sample. You can see that when the execution gets to the event produced when right-clicking on a row, the printed number is not the correct row number. Usually it has an offset, and last rows produce -1.
import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel, QLineEdit, QWidget, \
QPushButton, QVBoxLayout, QHBoxLayout, QComboBox, \
QTableWidget, QHeaderView, QTableWidgetItem, \
QMenu, QApplication
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Window size and title
self.setWindowTitle('Test')
self.resize(700, 700)
self.setMinimumWidth(700)
# Label
addressLabel = QLabel('Testing')
addressLabel.setAlignment(Qt.AlignCenter)
# Dropdown
self.addressDropdown = QComboBox(self)
self.addressDropdown.addItem('A')
self.addressDropdown.addItem('B')
# Refresh button
refreshButton = QPushButton()
refreshButton.setMaximumSize(40, 40)
# Address layout
addressayout = QHBoxLayout()
addressayout.addWidget(addressLabel, 1)
addressayout.addWidget(self.addressDropdown, 7)
addressayout.addWidget(refreshButton)
# Balance label
balaceLabel = QLabel()
balaceLabel.setText('Testing')
balaceLabel.setAlignment(Qt.AlignCenter)
# Balance amount label
self.balaceAmountLabel = QLabel()
self.balaceAmountLabel.setText('Testing')
self.balaceAmountLabel.setAlignment(Qt.AlignCenter)
# Balance layout
balanceLayout = QVBoxLayout()
balanceLayout.addWidget(balaceLabel)
balanceLayout.addWidget(self.balaceAmountLabel)
# Transactions label
transactionsLabel = QLabel('Testing')
transactionsLabel.setAlignment(Qt.AlignCenter)
# Transactions table
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(10)
self.tableWidget.setColumnCount(1)
self.tableWidget.verticalHeader().setVisible(False)
self.tableWidget.horizontalHeader().setVisible(False)
self.tableWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
item = QTableWidgetItem('Testing')
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
self.tableWidget.setItem(0, 0, item)
# Transactions layout
transactionsLayout = QVBoxLayout()
transactionsLayout.addWidget(transactionsLabel)
transactionsLayout.addWidget(self.tableWidget)
# Send label A
sendLabelA = QLabel('Send')
sendLabelA.setAlignment(Qt.AlignCenter)
# Send amount
self.sendAmount = QLineEdit()
self.sendAmount.setAlignment(Qt.AlignCenter)
# Send label B
sendLabelB = QLabel('to')
sendLabelB.setAlignment(Qt.AlignCenter)
# Send address
self.sendAddress = QLineEdit()
self.sendAddress.setAlignment(Qt.AlignCenter)
# Send button
sendButton = QPushButton()
sendButton.setMaximumSize(40, 40)
sendIcon = QIcon.fromTheme("mail-send")
sendButton.setIcon(sendIcon)
sendButton.setIconSize(QSize(24,24))
# Send layout
sendLayout = QHBoxLayout()
sendLayout.addWidget(sendLabelA)
sendLayout.addWidget(self.sendAmount, 2)
sendLayout.addWidget(sendLabelB)
sendLayout.addWidget(self.sendAddress, 4)
sendLayout.addWidget(sendButton)
# Window layout
layout = QVBoxLayout()
layout.addLayout(addressayout)
layout.addLayout(balanceLayout)
layout.addLayout(transactionsLayout)
layout.addLayout(sendLayout)
self.setLayout(layout)
def contextMenuEvent(self, event):
menu = QMenu(self)
openAction = menu.addAction('Open in browser')
action = menu.exec_(event.globalPos())
row = self.tableWidget.rowAt(event.y())
if action == openAction:
print(row)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
The coordinate that rowAt() method requires must be with respect to the viewport of the QTableWidget so you must convert the global position to local using mapFromGlobal() method:
def contextMenuEvent(self, event):
gp = event.globalPos()
menu = QMenu(self)
openAction = menu.addAction("Open in browser")
action = menu.exec_(gp)
vp_pos = self.tableWidget.viewport().mapFromGlobal(gp)
row = self.tableWidget.rowAt(vp_pos.y())
if action == openAction:
print(row)
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)